Docker 入門指南

Docker 入門指南

目錄

  1. 基礎概念
  2. 安裝教程
  3. 基本操作
  4. 常用安裝
  5. 構建操作
  6. 容器編排

壹.基礎概念

什麼是Docker?

Docker是基於Go開發的應用容器引擎,屬於 Linux 容器的一種封裝,提供簡單易用的容器使用介面。

解決難題:

  • 環境配置不一致
  • 虛擬機累贅(資源佔用大、啟動慢等)

虛擬機與容器的差別

虛擬機與容器的差別

主要用途:

提供一次性的環境。比如,本地測試他人的軟體、持續集成的時候提供單元測試和構建的環境。

提供彈性的雲服務。因為 Docker 容器可以隨開隨關,很適合動態擴容和縮容,組建微服務架構。

當人們說 “Docker” 時,他們通常是指 Docker Engine,它是一個客戶端-伺服器應用程式, 由 Docker 守護進程、REST API、命令行介面(CLI)組成。

docker

結構

結構結構

  1. 客戶端調用 Docker
  2. Docker 從 Registry 拉取鏡像(image)
  3. 通過鏡像生成容器(container)實例

鏡像 image

Docker 把應用程式及其依賴,打包在 image 文件裡面。image 文件可以看作是容器的模板。Docker 根據 image 文件生成容器的實例

image 文件是通用的。一般來說,為了節省時間,我們應該盡量使用別人製作好的 image 文件。即使要訂製,也應該基於別人的 image 文件進行加工,而不是從零開始製作。

容器 container

容器是一個鏡像的可運行的實例,可以使用 Docker REST API 或者 CLI 來操作容器,容器可以擁有自己的 root 文件系統、自己的網路配置、自己的進程空間,甚至自己的用戶 ID 空間。

容器內的進程是運行在一個隔離的環境里,使用起來,就好像是在一個獨立於宿主的系統下操作一樣。這種特性使得容器封裝的應用比直接在宿主運行更加安全。

註冊表(倉庫)registry

存放鏡像的地方(公有/私有)

為了方便共享,image 文件製作完成後,可以上傳到網上的倉庫。Docker 的官方倉庫 Docker Hub 是最重要、最常用的 image 倉庫。

UnionFS 聯合文件系統

聯合文件系統(UnionFS)是一種分層、輕量級並且高性能的文件系統,它支援對文件系統的修改作為一次提交來一層層的疊加,同時可以將不同目錄掛載到同一個虛擬文件系統下。

聯合文件系統是 Docker 鏡像的基礎。鏡像可以通過分層來進行繼承,基於基礎鏡像(沒有父鏡像),可以製作各種具體的應用鏡像。

特性:一次同時載入多個文件系統,但從外面看起來只能看到一個文件系統。聯合載入會把各層文件系統疊加起來,這樣最終的文件系統會包含所有底層的文件和目錄。

鏡像載入原理

Docker的鏡像是由多層文件系統組成:

分層分層

bootfs(boot file system)主要包含 bootloader 和 kernel。bootloader 主要是引導載入kernel,完成後整個內核就都在記憶體中了。此時記憶體的使用權已由bootfs轉交給內核,系統卸載 bootfs。可以被不同的 Linux 發行版共用。

rootfs(root file system),包含典型Linux系統標準目錄和文件。相當於各種不同作業系統發行版(Ubuntu,Centos等)。因為底層直接用Host的kernel,rootfs只包含最基本的命令,工具和程式就可以了。 當進行修改或者更新時,會在當前鏡像層上新建新的層級。

分層結構分層結構

容器啟動時會在最上層創建一個可讀寫的容器層(其它層只讀)

不同鏡像的相同文件層無需再次下載

貳.安裝


不同版本安裝

Tips:需要卸載舊版本

Ubuntu

# 更新apt軟體包索引並允許使用儲存庫
$ sudo apt-get update
$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

# 添加Docker的官方GPG密鑰
$ sudo apt-get install docker-ce docker-ce-cli containerd.io

# 設置穩定的存儲庫
$ echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] //download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安裝最新的Docker引擎
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io

# 運行hello world
$ sudo docker run hello-world

# 顯示輸出:
> Hello from Docker!

Centos

# 安裝所需的軟體包。
$ sudo yum install -y yum-utils

# 使用以下命令來設置穩定的存儲庫。
$ sudo yum-config-manager --add-repo //download.docker.com/linux/centos/docker-ce.repo

# 安裝DOCKER引擎
# (centos8 此步containerd.io版本過低,解決方案://www.backendcloud.cn/2020/03/16/centos8installdocker/ )
$ sudo yum install docker-ce docker-ce-cli containerd.io

# 開機自啟並啟動
$ sudo systemctl enable docker
$ sudo systemctl start docker

# 測試安裝效果
$ docker version

Raspberry Pi OS (Raspbian)

# 不能直接使用存儲庫安裝,需要使用腳本二進位安裝:
# 註:其實無論什麼發行版都可以通過二進位安裝,也可以通過腳本自動安裝,不過要注意,使用腳本前需要確認腳本是否安全,並且因為腳本是全自動,也可能會安裝很多其他的東西 /滑稽

$ curl -fsSL //get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh --mirror Aliyun
$ sudo usermod -aG docker $USER

# 開機自啟,並啟動
$ sudo systemctl enable docker
$ sudo systemctl start docker

# 一般arm架構無法直接使用X86的image,需要使用Dockerfile重新構建arm版或使用別人編譯好的arm架構版image
# 可以在 docker Hub 搜 arm 或 rpi
# 還有常見的arm架構倉庫: arm32v7、arm64v8、hypriot

Manjaro

# 如果你的系統也和 Manjaro 一樣有包管理器的話那就簡單多了,這裡舉 pacman 或 yay 的例子:
# 更新包管理器
$ sudo pacman -Syu

# 安裝docker
$ sudo pacman -S docker

# 完事,確認下
$ sudo docker version

# 設置開機自啟並啟動
$ sudo systemctl enable docker
$ sudo systemctl start docker

其他系統

# win和mac官方都有桌面版可以直接下載安裝,並且還可以附帶UI操作介面應用
# win版需要開啟 WSL2 或者 Hyper_v 後才能安裝,但是以上2者跟虛擬機不兼容
# Debian 和 Fedora 在 Docker 官網文檔也有安裝方法

安裝後的通用操作

設置中國鏡像源

# 阿里加速服務://??????.mirror.aliyuncs.com (需自己申請個人加速服務地址,加速服務不只是提供鏡像加速,還有 docker 在各種作業系統的安裝文檔和加速,註冊地址://cr.console.aliyun.com/undefined/instances/mirrors)
# 或者一些其他的鏡像(建議使用阿里的鏡像):
# 官方 - //registry.docker-cn.com
# 網易 - //hub-mirror.c.163.com
# Azure 中國鏡像 - //dockerhub.azk8s.cn

# 這裡僅展示ubuntu和centos的操作,對於 Docker for Windows、Docker for Mac 在設置中編輯 daemon.json ,增加和下面一樣的字元串即可

# 使用vim編輯
$ sudo vim /etc/docker/daemon.json
# 複製進去:
{
"registry-mirrors": ["//??????.mirror.aliyuncs.com","//registry.docker-cn.com"]
}

# 或者命令寫入:
$ sudo mkdir -p /etc/docker
$ sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["//??????.mirror.aliyuncs.com"]
}
EOF

# 然後重啟服務
$ sudo systemctl daemon-reload && sudo systemctl restart docker
# 查看是否成功(看Registry Mirrors項):
$ docker info 

設置用戶組

設置用戶組,打 docker 命令不用加 sudo

# 添加組,一般安裝完會自動創建好了
$ sudo groupadd docker

# 把docker命令加入組中
$ sudo usermod -aG docker $USER

重新登錄或:
$ su ${USER}

設置開機自啟

# 用 systemctl 管理服務的 linux 版本可以直接這樣:
# 開機自啟並啟動
$ sudo systemctl enable docker

# 重新啟動
$ shutdown -r now
# 查看是否啟動狀態
$ systemctl status docker

其他安裝

docker-compose

# Win和Mac安裝完docker後自帶docker-compose

# linux上安裝docker-compose:
# 下載
$ sudo curl -L "//github.com/docker/compose/releases/download/1.29.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 設置可執行許可權
$ sudo chmod +x /usr/local/bin/docker-compose

# 安裝完成,查看版本
$ docker-compose --version

# 如需卸載:
$ sudo rm /usr/local/bin/docker-compose

叄.基本操作

docker命令圖解docker命令圖解

小Tisp1:linux中的命令行參數

-後面跟縮寫,如 -a,-q,-aq(相當於-a -q) –後面跟完整參數名,如–all,–quiet

小Tisp2:命令行中換行:

win換行: ^
linux換行: \

小Tisp3:win的路徑輸入:

還像在win中【d:\】嗎?不對喲,是:

/d/tool/DockerDesktop/minio/data

基本資訊

資訊查看

# 顯示docker的基本資訊
$ docker version 
# 系統資訊,鏡像和容器的數量
$ docker info 

# 查看docker事件
$ docker events [OPTIONS]

# 全部幫助
$ docker --help 
# 個別命令幫助
$ docker [命令] --help 

倉庫 registry

# 搜索鏡像
docker search [OPTIONS] 鏡像名

# 相當於在 hub.docker.com 頁面搜索

選項:
  -f,--filter filter 過濾輸出
    --format string  格式化輸出
    --limit int 最大搜索結果數(默認為25)
    --no-trunc 不截斷輸出
    
示例:
docker search mysql

docker login

# 登錄到registry
docker login [OPTIONS] [SERVER]

常用選項:
 -p ,--password  密碼
 -u ,--username  用戶名

示例:
docker login
>輸入帳號
>輸入密碼

# 登錄到私有registry
docker login localhost:8080
docker login -u username -p userpasswd 192.168.1.33:5000

# 註銷
docker logout [SERVER]

鏡像 image

docker images

docker images [OPTIONS] [REPOSITORY[:TAG]]
docker images = docker image ls

常用選項:
-a , --all   # 顯示所有(默認隱藏中間影像)
--digests		# 顯示摘要
-f , --filter filter # 過濾輸出
--format string	# 格式化輸出
--no-trunc		# 不截斷輸出(ID縮寫是12位,不截斷輸出就是64位)
-q , --quiet 	# 只顯示id

示例:

# 只顯示ID
docker images -aq

docker pull

# 拉取鏡像
docker pull [OPTIONS] NAME[:TAG|@DIGEST]

# 默認倉庫為docker.io/library/
# 默認版本為:latest
# 所以docker pull mysql 等價於 docker pull docker.io/library/mysql:latest

docker rmi

# 刪除鏡像
docker rmi [OPTIONS] IMAGE [IMAGE...]

常用選項:
-f 強制刪除影像

# 刪除所有( linux 小技巧)
$ docker rmi -f $(docker images -aq)
# 或
$ docker images -qa | xargs docker rmi

docker import 與 export

# 導出鏡像
docker export [OPTIONS] CONTAINER

常用選項:
-o,--output    寫入文件,而不是STDOUT

例子:
docker export exampleimage > exampleimage.tar
# 或
docker export --output="exampleimage.tar" exampleimage
# 導入鏡像
docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]

常用選項:
-c, --change  將Dockerfile指令應用於創建的映像(支援的Dockerfile指令: CMD| ENTRYPOINT| ENV| EXPOSE| ONBUILD| USER| VOLUME|WORKDIR)
-m,--message  設置導入影像的提交消息
--platform  API 1.32+ ;如果伺服器支援多平台,則設置平台

示例:

# 遠程
docker import //example.com/exampleimage.tgz

# 本地
docker import /path/to/exampleimage.tgz
# 或
cat exampleimage.tgz | docker import - exampleimagelocal:new

# 本地目錄
sudo tar -c . | docker import - exampleimagedir

容器 container

基礎操作

# 啟動容器
docker start
# 重啟容器
docker restart
# 停止容器
docker stop
# 殺掉容器
docker kill 

# 查看容器元數據(詳細資訊)
docker inspect 
# 查看內容佔用
docker stats 
# 查看容器中的進程資訊
docker top

docker ps

# 查看容器列表
docker ps [OPTIONS]
docker ps  = docker container ls

常用選項:
-a,--all   顯示所有容器(默認顯示正在運行)
-f,--filter    過濾輸出
  --format  使用Go模板格式化輸出
-n,--last  顯示n個最後創建的容器
-l ,--latest  顯示最新創建的容器
  --no-trunc  不要截斷輸出
-q, --quiet  僅顯示容器ID
-s, --size   顯示文件總大小

docker run

# 運行容器
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

# run的時候如果本地沒有鏡像的話,會自動執行拉取操作

常用選項:
-d,--detach 在後台運行容器並列印容器ID
-e,-env list 設置環境變數
-h,--hostname string 容器主機名
  --mount mount 綁定卷
  --name string 分配名稱
  --network 連接到網路
  --rm  退出時自動刪除容器
-v,-volume list 映射卷
-p 指定容器的埠 如-p 8080:8080
例子:
 -p ip:主機埠:容器埠
 -p 主機埠:容器埠
 -p 容器埠
  
-i 互動式操作。
-t --tty 分配一個偽TTY連接終端
-m --memory bytes  記憶體限制
  --privileged 賦予最高許可權(危,無限制,有主機許可權)
  --restart string 重啟策略,參數示例:
  --restart=always   自啟
  --restart=on-failure:3  非正常退出 重試3次
  --restart=unless-stopped 不嘗試啟動


示例:
# 容器停止後自動刪除
docker run --rm hello-world

# 後台運行並給它命名
docker run -itd --name uuu ubuntu

# run並且以終端模式進入該容器
docker run -it ubuntu /bin/bash
# 輸入 exit 回車 停止並退出容器
# 或快捷鍵 Ctrl + P + Q 不停止容器的退出

# 運行並映射卷到主機
docker run -p 3306:3306 --name mysql -v "$(pwd)"/docker_v/mysql/conf:/etc/mysql/conf.d mysql

docker rm

# 刪除容器
docker rm [OPTIONS] CONTAINER [CONTAINER...]

常用選項:
 -f, --force  強制刪除正在運行的容器(使用SIGKILL)
 -l ,--link  刪除指定的鏈接
 -v,--volumes   刪除與容器關聯的匿名卷

示例:
# 刪除指定容器 不能刪除正在運行的容器,如果強制刪除 rm -f
docker rm 容器id
# 刪除所有容器
docker rm -f $(docker ps -aq)
# 刪除所有容器
docker ps -a -q|xargs docker rm

docker logs

# 查看容器日誌
docker logs [OPTIONS] CONTAINER

常用選項::
    --details 顯示詳細資訊
  -f,--follow 跟隨日誌輸出
    --since string 顯示自時間戳
    --tail string 顯示行數
  -t,--timestamps顯示時間戳

例子:
docker logs
docker logs -f -t --tail 10 容器名或id

docker exec

# 連接容器終端(進入容器)
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

# 也可以用 docker attach 進入容器終端

常用選項:
-d,--detach 在後台運行命令
-e,-env 環境變數
-i,--interactive 即使未連接STDIN仍保持打開狀態(互動式操作)
-t,--tty分配偽TTY(終端)

# 同上面的run中操作一樣,這一步可以在運行後進入到容器中,如:
docker exec -it uuu /bin/bash

# 區別
# docker exec 進入容器後開啟一個新的終端,可以在裡面操作(常用)
# docker attach 進入容器正在執行的終端,不會啟動新的進程

docker cp

# 拷貝容器中的文件
docker cp 容器名/id:容器內路徑 主機文件路徑

示例:
#拷貝容器數據到主機
docker cp 容器名:/home/file /home

docker update

#更新基礎設置
docker update [OPTIONS] CONTAINER [CONTAINER...]

常用選項:
-c cpu權重
-m 記憶體限額
--restart  重啟策略

示例:
# 更新某個容器的重啟策略,使其重啟自動啟動
docker update --restart=always <CONTAINER ID>

其他操作

docker volume create

# 創建卷
docker volume create [OPTIONS] [VOLUME]

選項:
-d , --driver 默認local   指定卷驅動程式名稱
  --label  設置卷的元數據
  --name  指定卷名
-o , --opt  設置驅動程式特定選項

示例:
# 創建一個卷
docker volume create hello

# 使用這個卷
docker run -d -v hello:/world busybox ls /world  

掛載卷說明

容器數據卷

# 將容器內的目錄,掛載到宿主機上或其他容器內,實現同步和共享,並且刪除日期後掛載到本地的文件也不會消失

# 指定目錄掛載:
dokcer run -it -v 主機內目錄:容器內目錄 鏡像名/id

# 匿名掛載:
docker run -d -v 容器內目錄 鏡像名/id

# 具名掛載
docker run -d -v 卷名:容器內目錄 鏡像名/id

# 查看所有掛載的卷:
docker volume ls

# 查看卷資訊
docker volume inspect 卷名

# 所有docker容器內的卷,在未指定主機內目錄時,都會創建在:/var/lib/docker/volumes/卷名/_data 下

示例:
# minio文件伺服器,指定目錄掛載
docker run -p 9000:9000 --name minio -d \
-e "MINIO_ACCESS_KEY=admin" \
-e "MINIO_SECRET_KEY=admin123456" \
-v /home/cc/minio/data:/data \
-v /home/cc/minio/config:/root/.minio minio/minio server /data

# 數據卷容器(多個容器共享一個卷)
docker run -it --name 容器02 --volumes from 容器01 鏡像名/id

docker network create

# 創建一個網路
docker network create [OPTIONS] NETWORK

常用選項:
-d , --driver  驅動程式,默認bridge,可選overlay或第三方或自定義
--config-from  從中複製配置的網路
--ipv6  啟用IPv6網路
--label  在網路上設置元數據

network創建參數挺多的,這裡不贅述,感興趣可以看下官網文檔

示例:
# 創建一個overlay 模式的網路
docker network create -d overlay my-network

# 容器連接至該網路
docker run -itd --network=my-network busybox

網路模式說明

# 查看IP
$ ip addr 
# 查看docker0
$ ip addr show docker0

ip addr
bridge 模式

bridge模式bridge模式

# 當Docker進程啟動時,會在主機上創建一個名為docker0的虛擬網橋
# 這個docker0 也作為容器的默認網關,主機也可以ping通容器,但是容器之間是隔離的
# 不寫–net參數,默認就是bridge模式。使用docker run -p時,docker 實際是在iptables做了DNAT規則,實現埠轉發功能。可以使用iptables -t nat -vnL查看。

# 新建一個網路
$ docker network create -d bridge my-net

# 運行一個容器並連接到新建的 my-net 網路
$ docker run -it --rm --name busybox1 --network my-net busybox sh

# 加入系統網路的應用,可以互相ping通,如我可以在其他加入了my-net的容器里:
$ ping busybox
> PING busybox (172.19.0.2): 56 data bytes
> 64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.064 ms
> 64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.143 ms

# 如果你有多個容器之間需要互相連接,推薦使用Docker Compose。

Host 模式

Host 模式

# 如果啟動容器的時候使用host模式,那麼這個容器將不會獲得一個獨立的Network Namespace,而是和宿主機共用一個 Network Namespace

示例:
$ docker run -tid --net=host --name docker_host1 ubuntu-base:v3

Container 模式

Container 模式

# 這個模式指定新創建的容器和已經存在的一個容器共享一個 Network Namespace,而不是和宿主機共享
# 示例,獨立的 docker_bri1 網路:
$ docker run -tid --net=container:docker_bri1 \
       --name docker_con1 ubuntu-base:v3

None 模式

None 模式

None 模式

# Docker 容器擁有自己的 Network Namespace,但是,並不為 Docker 容器進行任何網路配置(如有需要,自己手動配置)

肆.常用安裝


Portainer

# 可視化管理介面
# 其他類似的還有:Rancher、cAdvisor

安裝示例:

$ docker volume create portainer_data

$ docker run -d --name portainer --restart unless-stopped -p 9000:9000 \
-v ~/docker_v/portainer/data:/data \
-v /var/run/docker.sock:/var/run/docker.sock \
portainer/portainer-ce:latest

安裝後能很方便的管理 docker:

Portainer介面

Mysql

# MySQL(5.7.19)的默認配置文件是 /etc/mysql/my.cnf 文件。
# 如果想要自定義配置,建議向 /etc/mysql/conf.d 目錄中創建 .cnf 文件。

具體操作:

# 這裡已經把配置文件my.cnf放到了~/docker_v/mysql/conf:
# 然後運行命令:
$ docker run -p 3306:3306 --name mysql \
-v ~/docker_v/mysql/conf:/etc/mysql/conf.d \
-v ~/docker_v/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-itd mysql:5.7.29

Nginx

$ docker run -d -p 80:80 --name nginx \
-v /root/nginxFile/html:/usr/share/nginx/html \
-v /root/nginxFile/conf:/etc/nginx \
-v /root/nginxFile/log:/var/log/nginx \
nginx

# 如果想拷下原版的配置出來改的話:
# 新建個臨時容器
$ docker run -d -p 127.0.0.1:8080:80 --rm --name mynginx -v "$PWD/html":/usr/share/nginx/html nginx

# 把容器中的nginx配置拷出來
$ docker cp mynginx:/etc/nginx .
$ docker stop mynginx

# 然後重新跑下上面 Nginx 的 docker run

Registry

# 私有倉庫安裝示例

【本地版:

$ docker run -d \
  -p 5000:5000 \
  --name registry
  --restart=always
  -v /opt/data/registry:/var/lib/registry \
  registry

# 用curl查看倉庫中的鏡像
$ curl -XGET 127.0.0.1:5000/v2/_catalog
# 查看鏡像列表
$ curl -XGET 127.0.0.1:5000/v2/image_name/tags/list

【許可權認證版:  

# 創建保存帳號密碼的文件
$ mkdir  /opt/data/auth
# 創建帳號和密碼
$ docker run --entrypoint htpasswd registry -Bbn username userpasswd > auth/htpasswd

$ docker run -d -p 5000:5000 --restart=always --name registry \
    -v /opt/data/registry:/var/lib/registry \
    -v /opt/data/auth:/auth \
    -e "REGISTRY_AUTH=htpasswd" \
    -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
    -e  REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
    registry

# 登錄&退出
$ docker login -u username -p userpasswd 127.0.0.1:5000
$ docker logout 127.0.0.1:5000


【外網訪問-白名單版(前面2版之一的基礎上):

# 如果不想用127.0.0.1:5000作為倉庫地址,而是用區域網或者外網IP訪問,會有錯誤。
# 這是因為 Docker 默認不允許非 HTTPS 方式推送鏡像。我們可以通過 Docker 的配置選項來取消這個限制

# Ubuntu 14.04, Debian 7 Wheezy:
# 對於使用 upstart 的系統而言,編輯/etc/default/docker文件,在其中的DOCKER_OPTS中增加如下內容:
DOCKER_OPTS="--insecure-registries=192.168.199.100:5000"

# Ubuntu 16.04+, Debian 8+, centos 7
# 對於使用 systemd 的系統,在/etc/docker/daemon.json中增加如下內容
{
  "insecure-registries": [
    "192.168.199.100:5000"
  ]
}

# 對於 Docker for Windows、Docker for Mac 在設置中編輯daemon.json增加和上邊一樣的字元串即可。

# 重新啟動服務:
$ sudo service docker restart


【外網訪問-https版(前面2版之一的基礎上):

# 創建證書目錄
$ mkdir -p certs
# 生成證書的操作這裡不贅述,將你生成的或者已有的.crt和.key文件直接拷貝到certs路徑

# 如果使用的是intermediate證書:
  # 若是.crt和.pem文件:
  $ cat domain.crt intermediate-certificates.pem > certs/domain.crt
  # 若是.crt和IntermediateCA.crt文件
  $ cat ssl_certificate.crt IntermediateCA.crt > certs/domain.crt

# 運行容器時加以下參數:
-v `pwd`/certs:/certs \
-e REGISTRY_HTTP_ADDR=0.0.0.0:80 \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \

伍.其他構建類操作


推送鏡像

docker commit

# 提交容器成為一個新鏡像
docker commit -m="描述資訊" -a="作者" 容器id 目標鏡像名:[tag] 

docker tag

# 給某個鏡像創建一個標籤(標記版本號)
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

示例:

docker tag id或名字 fedora/httpd:version1.0
docker tag httpd:test fedora/httpd:version1.0.test

# 要推送至私有註冊表時需要加上私有地址和埠:
docker tag 0e5574283393 myregistryhost:5000/fedora/httpd:version1.0

docker push

docker push [OPTIONS] NAME[:TAG]

常用選項:
 -a ,--all-tags   將所有標記的影像推送到存儲庫中

示例:

# 推送至私有註冊表
docker image push registry-host:5000/用戶名/rhel-httpd:latest
# 推送至中央註冊表(需先docker login)
docker image push 用戶名/rhel-httpd:latest
# 推送全部tag版本
docker image push --all-tags registry-host:5000/用戶名/rhel-httpd

構建鏡像

dockerFile

# 新建一個dockerFile,從頭構建一個屬於自己的鏡像。

dockerFile命令:

FROM  基礎鏡像:Centos/Ubuntu
MAINTAINER  鏡像作者+郵箱
RUN  鏡像構建的時候需要運行的命令
ADD  為鏡像添加內容(壓縮包)
WORKDIR  鏡像工作目錄(進入容器時的目錄)
VOLUME  掛載的目錄
EXPOSE  暴露埠配置
CMD/ENTRYPOINT  指定這個容器啟動時要運行的命令(CMD替代先前命令,ENTRYPOINT在先前命令後追加)
COPY  類似於ADD,將文件拷貝到鏡像中
ENV  構建時設置環境變數

# 每個保留關鍵字(指令)都必須是大寫字母
# 從上到下順序執行
# "#" 表示注釋
# 每一個指令都會創建提交一個新的鏡像層並提交

docker build

# 從Dockerfile構建映像
docker build [OPTIONS] PATH | URL | -

常用選項:

--add-host  添加自定義主機到IP的映射(host:ip)
--build-arg  設置構建時變數
--compress  使用gzip壓縮構建上下文
--file , -f Dockerfile的名稱(默認為「 PATH / Dockerfile」)
--label 設置影像的元數據
-m, --memory 記憶體限制
--rmtrue  成功構建後刪除中間容器
-t , --tag  格式的標籤
--target  設置要構建的目標構建階段。
--ulimitUlimit  選項

整體流程:
# 構建鏡像(文件名為 Dockerfile 時 -f 可省略,並且最後的.不要忽略)
docker build -f 文件路徑 -t 標籤 . 
# 運行鏡像
docker run  
# 發布鏡像
docker push  

實戰例子(基於GDAL環境部署):

dockerFile:
# 基於我編譯好的一個鏡像
FROM nibbbbbbbb/gdal-ubuntu-full:v1 
MAINTAINER chenbihao 
USER root 
# 更換中國鏡像源 
RUN sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list 
# 進入目錄 
WORKDIR /usr/local/ 
# 創建項目文件夾,並將外部文件夾內容添加進去 
RUN mkdir demo ADD ./demo ./demo 
# 設置編碼 (gdal鏡像默認編碼是POSIX) 
ENV LANG C.UTF-8 
# 開放埠 
EXPOSE 8080 
# 啟動命令 
CMD ["java","-Dfile.encoding=utf-8","-jar","/usr/local/demo/demo.jar","--spring.profiles.active=dev"]

構建docker鏡像:
$ docker build -t nibbbbbbbb/gdal-ubuntu-full:v1-app .

完成!

多階段構建

# 多階段構建可以在一個 Dockerfile 中使用多個 FROM 語句。
# 每個 FROM 指令都可以使用不同的基礎鏡像,並表示開始一個新的構建階段。
# 你可以很方便的將一個階段的文件複製到另外一個階段,在最終的鏡像中保留下你需要的內容即可。

比如,以下是同一個 dockerFile:

FROM golang AS build-env
ADD . /go/src/app
WORKDIR /go/src/app
RUN go get -u -v github.com/kardianos/govendor
RUN govendor sync
RUN GOOS=linux GOARCH=386 go build -v -o /go/src/app/app-server

FROM alpine
RUN apk add -U tzdata
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
COPY --from=build-env /go/src/app/app-server /usr/local/bin/app-server
EXPOSE 8080
CMD [ "app-server" ]

# 然後build
docker build -t cnych/docker-multi-stage-demo:latest .

# 這樣實現了先在 go 環境中編譯,編譯完後複製到新的 alpine 鏡像中(因為 alpine 只有5MB)

陸.容器編排


限於篇幅原因這裡不細講了,僅大致介紹。

Compose、Machine 和 Swarm 集群是 Docker 官方容器編排三劍客。

Kubernetes(k8s)是 google 開源的一個擁有強大生態的容器編排平台。

Compose

# Compose 是用於定義和運行多容器 Docker 應用程式的工具。
# 通過 Compose,你可以使用 YAML 文件來配置應用程式的服務。然後,使用一個命令,就可以從配置中創建並啟動所有服務。
# Compose 可在所有環境中工作:生產,開發,測試以及CI工作流。
# 使用 Compose 基本上是一個三步過程:

# 使用定義您的應用環境,Dockerfile 以便可以在任何地方複製它。
# 定義組成應用程式的服務,docker-compose.yml 以便它們可以在隔離的環境中一起運行。
# 運行 docker compose up,然後 Docker compose 命令啟動並運行您的整個應用程式。

一個docker-compose.yml看起來像這樣:

version: "3.9" # optional since v1.27.0
services:
 web:
  build: .
  ports:
   - "5000:5000"
  volumes:
   - .:/code
   - logvolume01:/var/log
  links:
   - redis
 redis:
  image: redis
volumes:
 logvolume01: {}

# Compose具有用於管理應用程式整個生命周期的命令:

# 啟動,停止和重建服務
# 查看正在運行的服務的狀態
# 流運行服務的日誌輸出
# 在服務上運行一次性命令

Machine

# Docker Machine是 Docker 官方提供的一個工具,它可以幫助我們在遠程的機器上安裝 Docker,或者在虛擬機 host 上直接安裝虛擬機並在虛擬機中安裝 Docker。
# 我們還可以通過 docker-machine 命令來管理這些虛擬機和 Docker。
# Docker Machine 支援多種後端驅動,包括虛擬機、本地主機和雲平台等。

Swarm集群

# Swarm 是使用 SwarmKit 構建的 Docker 引擎內置(原生)的集群管理和編排工具。
# Docker Swarm是 Docker 官方三劍客項目之一,提供 Docker 容器集群服務,是 Docker 官方對容器雲生態進行支援的核心方案。
# 使用它,用戶可以將多個 Docker 主機封裝為單個大型的虛擬 Docker 主機,快速打造一套容器雲平台。
# Swarm mode 內置 kv 存儲功能,提供了眾多的新特性,比如:具有容錯能力的去中心化設計、內置服務發現、負載均衡、路由網格、動態伸縮、滾動更新、安全傳輸等。使得 Docker 原生的 Swarm 集群具備與Mesos、Kubernetes競爭的實力。

Kubernetes

# Kubernetes 縮寫是 k8s(k+8個字母+s)
# Google 在 2014 年開源了 Kubernetes 項目。
# Kubernetes 是一個可移植的、可擴展的開源平台,用於管理容器化的工作負載和服務,可促進聲明式配置和自動化。 Kubernetes 擁有一個龐大且快速增長的生態系統。Kubernetes 的服務、支援和工具廣泛可用。

# 容器是打包和運行應用程式的好方式。在生產環境中,你需要管理運行應用程式的容器,並確保不會停機。 例如,如果一個容器發生故障,則需要啟動另一個容器。如果系統處理此行為,會不會更容易?
# 這就是 Kubernetes 來解決這些問題的方法! Kubernetes 為你提供了一個可彈性運行分散式系統的框架。 Kubernetes 會滿足你的擴展要求、故障轉移、部署模式等。 例如,Kubernetes 可以輕鬆管理系統的 Canary 部署。

# Kubernetes 提供:

- 服務發現和負載均衡
Kubernetes 可以使用 DNS 名稱或自己的 IP 地址公開容器,如果進入容器的流量很大, Kubernetes 可以負載均衡並分配網路流量,從而使部署穩定。
- 存儲編排
Kubernetes 允許你自動掛載你選擇的存儲系統,例如本地存儲、公共雲提供商等。
- 自動部署和回滾
你可以使用 Kubernetes 描述已部署容器的所需狀態,它可以以受控的速率將實際狀態 更改為期望狀態。例如,你可以自動化 Kubernetes 來為你的部署創建新容器, 刪除現有容器並將它們的所有資源用於新容器。
- 自動完成裝箱計算
Kubernetes 允許你指定每個容器所需 CPU 和記憶體(RAM)。 當容器指定了資源請求時,Kubernetes 可以做出更好的決策來管理容器的資源。
- 自我修復
Kubernetes 重新啟動失敗的容器、替換容器、殺死不響應用戶定義的 運行狀況檢查的容器,並且在準備好服務之前不將其通告給客戶端。
- 密鑰與配置管理
Kubernetes 允許你存儲和管理敏感資訊,例如密碼、OAuth 令牌和 ssh 密鑰。 你可以在不重建容器鏡像的情況下部署和更新密鑰和應用程式配置,也無需在堆棧配置中暴露密鑰。

導圖

Tags: