Docker小記

Docker概覽

運(yùn)維視角

Docker安裝:

  1. 先刪除以前安裝的docker:
yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
  1. 添加yum相關(guān)工具:
yum install -y yum-utils
  1. 添加阿里yum庫:
yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  1. 安裝:
yum install docker-ce docker-ce-cli containerd.io
  1. 啟動(dòng):systemctl start docker
  2. 設(shè)置開機(jī)啟動(dòng):systemcetl enable docker
  3. 添加國內(nèi)鏡像庫服務(wù),修改配置文件(沒有的話新建)/etc/docker/daemon.json,然后重啟docker:
{
    "registry-mirrors": ["https://xxxxx.mirror.aliyuncs.com"]
}

在安裝docker時(shí),會(huì)涉及兩個(gè)主要組件:docker客戶端和docker daemon(docker引擎或docker服務(wù)端)。默認(rèn)情況下,客戶端與daemon通過本地套接字通信(/var/run/docker.sock),或者網(wǎng)絡(luò)通信,docker daemon默認(rèn)會(huì)監(jiān)聽2375或2376端口(TLS)。由于docker命令需要root權(quán)限,所以可以將用戶添加到安裝docker時(shí)自動(dòng)創(chuàng)建的docker組里:sudo usermod -aG docker [username]。

鏡像

可以將docker鏡像粗略理解為一個(gè)包含os文件系統(tǒng)和應(yīng)用的對(duì)象。
查看鏡像:docker image ls
拉取鏡像:docker pull ubuntu:latest
啟動(dòng)容器:docker run -it ubuntu:latest /bin/bash,-it表示開啟容器的交互模式,將當(dāng)前Shell連接到容器終端。/bin/bash表示用戶想在docker里運(yùn)行bash進(jìn)程,實(shí)際上就是后文要講的runc組件啟動(dòng)的程序,也是容器里當(dāng)前唯一的進(jìn)程(大部分容器只會(huì)運(yùn)行一個(gè)進(jìn)程)。容器隨其中運(yùn)行的應(yīng)用關(guān)閉而終止,在這里就是bash退出后容器就停止了。容器相關(guān)命令還有:docker container start|stop|rm [container name|container ID]。
ctrl-PQ組合鍵可以在退出容器的同時(shí)還保持容器的運(yùn)行,再執(zhí)行docker container exec -it [container ID] /bin/bash會(huì)讓容器再運(yùn)行一個(gè)bash并連接上,此時(shí)再用exit退出容器里的bash并不會(huì)停止容器,因?yàn)槿萜骼镞€有一個(gè)bash。
查看運(yùn)行中的容器:docker container ls
查看所有容器,包括已停止的:docker container ls -a
連接到運(yùn)行中的容器:docker container exec -it mycontainer /bin/bash

開發(fā)視角

從開發(fā)者的視角來看,運(yùn)行的容器就是應(yīng)用進(jìn)程,換句話說就是容器化的進(jìn)程,一個(gè)屬于特殊命名空間的應(yīng)用進(jìn)程。

構(gòu)建鏡像

將應(yīng)用容器化,應(yīng)用文件目錄如下:


應(yīng)用文件.PNG

可以看出在項(xiàng)目文件目錄里有一個(gè)Dockerfile的文件,內(nèi)容是:

FROM alpine
LABEL maintainer="nigelpoulton@hotmail.com"
RUN apk add --update nodejs nodejs-npm
COPY . /src
WORKDIR /src
RUN npm install
EXPOSE 8080
ENTRYPOINT ["node", "./app.js"]

跳轉(zhuǎn)到項(xiàng)目目錄里,然后根據(jù)Dockerfile構(gòu)建名為test:latest的鏡像:docker image build -t test:latest .
啟動(dòng)容器:docker container run -d --name web1 --publish 8080:8080 test:latest

Docker引擎

Docker引擎采用的是模塊化設(shè)計(jì),其組件是可以替換的。


Docker引擎架構(gòu).PNG

daemon的功能主要有鏡像管理、鏡像構(gòu)建、與Docker client的交互、身份驗(yàn)證、安全特性、卷、核心網(wǎng)絡(luò)以及編排。
runc是一個(gè)命令行工具,它只有一個(gè)作用:創(chuàng)建容器。
shim是一個(gè)實(shí)現(xiàn)容器與daemon解耦的工具,containerd每啟動(dòng)一個(gè)容器都會(huì)fork一個(gè)runc,不過一旦容器啟動(dòng)完畢,runc就會(huì)退出,一旦runc退出,對(duì)應(yīng)的shim進(jìn)程就會(huì)成為容器的父進(jìn)程,其主要職責(zé)是保持STDIN和STDOUT流是開啟狀態(tài),避免daemon重啟時(shí)導(dǎo)致容器關(guān)閉,以及將容器的退出狀態(tài)返回給daemon。
containerd是一個(gè)單獨(dú)的守護(hù)進(jìn)程,它的主要任務(wù)是容器的生命周期的管理——start|stop|pause|rm...
containerd還可完成一些諸如push和pull鏡像的操作,但這些操作都是模塊化可選的。
上面的daemon、containerd、shim、runc在Linux系統(tǒng)中均是以二進(jìn)制文件形式存在,在宿主機(jī)通過ps命令均可以查看到對(duì)應(yīng)的進(jìn)程。


容器的啟動(dòng)過程.PNG
容器啟動(dòng)流程圖.PNG

Docker鏡像

鏡像其實(shí)就是多個(gè)只讀層文件的疊加。而容器則是在此基礎(chǔ)上增加了一個(gè)讀寫層,并且在容器運(yùn)行時(shí),會(huì)映射出一個(gè)完整的疊加后的文件目錄在對(duì)應(yīng)容器的merged目錄下。因?yàn)槿萜鞯倪\(yùn)行依賴它下面的只讀層,所以刪除鏡像前必須先刪除以此鏡像為基礎(chǔ)的容器(哪怕是已經(jīng)停止的容器),否則無法刪除該鏡像。刪除鏡像命令:docker image rm [image ID]|[image tag],刪除全部鏡像:docker image rm $(docker image ls -q) -f。鏡像文件通常位于/var/lib/docker/overlay2/。
鏡像通常都比較小,鏡像里并不包含內(nèi)核——容器都是共用宿主機(jī)的內(nèi)核。所以說容器僅包含必要的操作系統(tǒng)(通常指的是操作系統(tǒng)文件和文件系統(tǒng)對(duì)象)
拉取鏡像:docker image pull ubuntu:latest
鏡像倉庫服務(wù):

鏡像倉庫服務(wù).PNG

docker客戶端連接的鏡像倉庫服務(wù)是可配置的,默認(rèn)值Docker Hub。在Docker Hub里還分官方倉庫和第三方倉庫。


從Docker Hub拉取官方鏡像.PNG
從Docker Hub拉取非官方鏡像.PNG
拉取其它鏡像倉庫服務(wù)里的鏡像.PNG

一個(gè)鏡像可以擁有多個(gè)標(biāo)簽。 docker image ls --filter dangling=false 可用于過濾沒有標(biāo)簽的鏡像(如果新鏡像的標(biāo)簽和舊鏡像的標(biāo)簽沖突,則會(huì)移除舊鏡像的標(biāo)簽)。docker image prune可用于移除全部的懸虛(沒有標(biāo)簽)鏡像,如果再帶上-a則還會(huì)移除所有沒有被任何容器使用的鏡像。

Docker支持的鏡像過濾.PNG

docker search [NAME]用于搜索鏡像。NAME字段可以是倉庫名、你的Docker ID或者非官方倉庫的組織名稱。docker search [NAME] --filter "is-official=true"可以只返回官方倉庫。默認(rèn)情況下docker search只返回25行結(jié)果,可以通過--limit來指定返回行數(shù),最多100行。
查看鏡像分層:docker image inspect ubuntu:latest
所有的Docker鏡像都始于一個(gè)基礎(chǔ)鏡像,當(dāng)增加內(nèi)容時(shí),就會(huì)在當(dāng)前鏡像的基礎(chǔ)上新增一層鏡像。

新增文件增加鏡像層.PNG

更新文件增加鏡像層.PNG
鏡像層合并.PNG

容器運(yùn)行時(shí),鏡像層會(huì)合并在對(duì)應(yīng)容器的merged目錄下,容器停止后,merged目錄會(huì)消失,但新增或修改的內(nèi)容會(huì)存在diff目錄下。
不同鏡像還會(huì)共享可讀鏡像層。
拉取指定摘要的鏡像:

docker image pull nginx@sha256:aeade65e99e5d5e7ce162833636f692354c227ff438556e5f3ed0335b7cc2f1b

顯示鏡像的摘要:docker image ls --digests nginx

鏡像和鏡像層.PNG

多架構(gòu)鏡像.PNG

Docker容器

Docker容器重啟策略:
除非運(yùn)行中的容器被明確要求停止(如docker container stop),否則一直嘗試重啟:docker container run --name neverdie -it --restart always ubuntu /bin/bash。不過always策略會(huì)使停止的容器在daemon重啟時(shí)被啟動(dòng),而unless-stoped策略正好相反。on-failure策略會(huì)在容器退出但返回不是0的情況下重啟,daemon重啟時(shí),這種策略下的停止容器也會(huì)重啟。
刪除所有容器:docker container rm $(docker container ls -aq) -f
docker container inspect [container name|container ID]可以顯示容器的配置細(xì)節(jié)和運(yùn)行時(shí)信息。

應(yīng)用容器化

應(yīng)用容器化步驟.PNG

接下來詳細(xì)說明下應(yīng)用容器化的流程,項(xiàng)目的目錄結(jié)構(gòu)如下,這是一個(gè)簡單的node.js應(yīng)用:


項(xiàng)目目錄.PNG

對(duì)于Docker來說,項(xiàng)目目錄通常稱為構(gòu)建上下文,而Dockfile文件一般放在項(xiàng)目的根目錄下。

項(xiàng)目目錄里有個(gè)Dockfile文件,里面的內(nèi)容如下:

FROM alpine
LABEL maintainer="nigelpoulton@hotmail.com"
RUN apk add --update nodejs nodejs-npm
COPY . /src
WORKDIR /src
RUN npm install
EXPOSE 8080
ENTRYPOINT ["node", "./app.js"]

Dockerfile文件主要有這樣幾個(gè)主要任務(wù):配置應(yīng)用運(yùn)行所需的環(huán)境、將應(yīng)用代碼拷入鏡像中、配置應(yīng)用啟動(dòng)方式,最后指導(dǎo)Docker將這些信息進(jìn)行容器化,也就是生成一個(gè)完整鏡像。接下來逐行分析Dockfile文件里的每行命令:

  • FROM alpine:表示以alpine作為基礎(chǔ)鏡像,后續(xù)命令若有新增或修改內(nèi)容則會(huì)新增鏡像在基礎(chǔ)鏡像之上。
  • LABEL maintainer="nigelpoulton@hotmail.com":為鏡像添加一個(gè)鍵值對(duì)元數(shù)據(jù)(鏡像本身是一個(gè)配置對(duì)象),不會(huì)增加新的鏡像層。
  • RUN apk add --update nodejs nodejs-npm:運(yùn)行alpine系統(tǒng)里的包管理器來安裝nodejs和npm,并在基礎(chǔ)鏡像層之上新建一個(gè)鏡像層來存儲(chǔ)這些程序。實(shí)際上在這里會(huì)先將基礎(chǔ)鏡像層運(yùn)行起來,然后在運(yùn)行的容器里使用apk來安裝nodejs和npm,最后commit生成一個(gè)新鏡像層并刪除臨時(shí)容器。
  • COPY . /src:生成一個(gè)新鏡像,將當(dāng)前目錄下的構(gòu)建上下文拷貝到alpine系統(tǒng)里的/src目錄下。
  • WORKDIR /src:將alpine里的/src目錄作為Dockfile文件里后續(xù)還未執(zhí)行的命令的工作目錄,這不會(huì)新增鏡像層。
  • RUN npm install:在當(dāng)前工作目錄運(yùn)行npm install命令,并新增鏡像層。
  • EXPOSE 8080:僅表示要暴露的端口,無其它作用,作為元數(shù)據(jù)存在鏡像配置里,不會(huì)新增鏡像層。
  • ENTRYPOINT ["node", "./app.js"]:指定容器啟動(dòng)時(shí)默認(rèn)啟動(dòng)的程序,同樣作為元數(shù)據(jù),不會(huì)新增鏡像層。

最后的鏡像層組成如下:


鏡像層組成.PNG

最后進(jìn)行應(yīng)用容器化(生成鏡像):docker image build -t web:latest .

推送鏡像到鏡像倉庫服務(wù)

在推送鏡像前,Docker需要3個(gè)關(guān)于鏡像的信息,分別是鏡像倉庫服務(wù)、鏡像倉庫、鏡像標(biāo)簽:


目的倉庫.PNG

鏡像倉庫服務(wù)和鏡像標(biāo)簽有默認(rèn)值,可以不用指定。但由于我們沒有官方倉庫的訪問權(quán)限,所以往往我們需要推送到以自己Docker ID命名的二級(jí)命名空間下,所以在推送前要給鏡像添加一個(gè)新倉庫名:docker image tag web:latest mydockerid/web:latest。然后再推送:docker image push mydockerid/web:latest。
docker image history命令可以用來查看構(gòu)建該鏡像執(zhí)行了哪些命令。

多階段構(gòu)建

多階段構(gòu)建.PNG

多階段構(gòu)建,簡單來講就是在一個(gè)Dockfile文件里有多個(gè)構(gòu)建階段,每個(gè)階段都會(huì)構(gòu)建自己的鏡像,然后在構(gòu)建最后一個(gè)階段時(shí),會(huì)直接從前面已構(gòu)建好的鏡像里拷貝所需文件,從而避免在最后的應(yīng)用鏡像里有過多不必要的文件,如包依賴等。


多階段構(gòu)建生成的鏡像.PNG

利用構(gòu)建緩存:


利用構(gòu)建緩存.PNG

合并鏡像:
docker image build --squash
合并鏡像層不好的一點(diǎn)是它里面的鏡像層不能再分享,并且在push或pull時(shí)操作的鏡像體積更大。但如果鏡像層太多,合并還是一個(gè)不錯(cuò)的選擇。

合并鏡像.PNG

Docker Compose

安裝Docker Compose:

  1. 下載二進(jìn)制文件:
curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
  1. 添加可執(zhí)行權(quán)限:
chmod +x /usr/local/bin/docker-compose

Docker Compose可以用來管理和部署一個(gè)多服務(wù)(容器)應(yīng)用。Docker Compose使用YAML文件來定義多服務(wù)應(yīng)用,也可以使用JSON。Docker Compose默認(rèn)使用文件名docker-compose.yml。
下面是一個(gè)簡單的Compose文件示例,它定義了一個(gè)包含兩個(gè)服務(wù)(web-fe和redis)的小型Flask應(yīng)用。這是一個(gè)能夠?qū)υL問者進(jìn)行計(jì)數(shù)并將其保存到Redis的簡單的Web應(yīng)用:

#必須以此開頭,它指定了該Compose文件的版本格式
version: "3.5"
#若干服務(wù)
services:
    #定義名叫web-fe的服務(wù)
    web-fe:
        #指定構(gòu)建鏡像的上下文路徑,在這里就是指引Docker基于當(dāng)前目錄下的上下文和Dockfile來構(gòu)建一個(gè)鏡像
        build: .
        #指定容器運(yùn)行時(shí)要運(yùn)行的程序,其實(shí)也可以不在這里指定
        command: python app.py
        #指定端口映射,target是容器內(nèi)端口,published是主機(jī)端口
        ports:
            - target: 5000
              published: 5000
        #指定連接的網(wǎng)絡(luò)
        networks:
            - counter-net
        #將counter-vol卷掛載到容器內(nèi)的/code目錄下
        volumes:
            - type: volume
              source: counter-vol
              target: /code
    #定義名叫redis的服務(wù)
    redis:
        #讓Docker基于鏡像redis:alpine啟動(dòng)一個(gè)容器
        image: "redis:alpine"
        #讓redis容器連接到counter-net網(wǎng)絡(luò)
        networks:
            counter-net:
#指引Docker創(chuàng)建新的網(wǎng)絡(luò),默認(rèn)情況下會(huì)創(chuàng)建bridge網(wǎng)絡(luò)。也可以常見其它網(wǎng)絡(luò):
#                           networks:
#                               other-net:
#                                   driver: overlay
#                                   attachable: true
networks:
    counte-net:
#指引Docker創(chuàng)建新的卷
volumes:
    counter-vol:

然后跳轉(zhuǎn)到Compose服務(wù)的項(xiàng)目目錄下,在這個(gè)例子中就是web-fe項(xiàng)目目錄下,假設(shè)目錄名為counter-app,開始部署:docker-compose up -d,這個(gè)命令會(huì)先創(chuàng)建網(wǎng)絡(luò)和卷,然后構(gòu)建所需鏡像,并啟動(dòng)容器。-d表示后臺(tái)運(yùn)行compose。還有這個(gè)命令會(huì)默認(rèn)在當(dāng)前目錄查找docker-compose.yml文件,你也可以用-f命令指定文件。
需要一提的是,在docker compose為services里的每個(gè)服務(wù)部署容器時(shí),還會(huì)使用對(duì)應(yīng)的key作為容器名字的一部分,例如:

docker compose容器命名.PNG

實(shí)際上,Docker Compose會(huì)將項(xiàng)目名(counter-app)作為compose文件里所有資源名的前綴。


docker compose資源命名.PNG

Docker Compose管理應(yīng)用

docker-compose down命令會(huì)先關(guān)閉應(yīng)用和相關(guān)容器并刪除容器,然后刪除網(wǎng)絡(luò)。但docker-compose up過程中拉取和構(gòu)建的鏡像不會(huì)刪除,卷也不會(huì)刪除。
docker-compose ps可以查看應(yīng)用相關(guān)服務(wù)的狀態(tài)。
docker-compose top

docker-compose top.PNG

docker-compose stop會(huì)停止應(yīng)用,但不會(huì)刪除資源。對(duì)于已停止的應(yīng)用,可以用docker-compose rm來刪除容器和網(wǎng)絡(luò),也不會(huì)刪除鏡像和卷。
docker-compose restart用于重啟,如果用戶在停止應(yīng)用后對(duì)compose文件進(jìn)行了修改,那么重啟不會(huì)使這些修改生效,只能重新部署。
docker volume inspect [volume name] | grep Mount可用于查看卷在Docker主機(jī)的什么位置,改變這里的內(nèi)容會(huì)實(shí)時(shí)反應(yīng)在運(yùn)行中的容器里。

Docker Swarm

Docker Swarm主要包含兩個(gè)方面:一個(gè)是企業(yè)級(jí)Docker安全集群,Swarm可以將一個(gè)或多個(gè)Docker節(jié)點(diǎn)(docker daemon)組織起來,使得用戶能夠以集群方式管理它們,用戶可以自如地添加或刪除節(jié)點(diǎn);另一個(gè)是微服務(wù)應(yīng)用的編排,Swarm提供了一套豐富的API用來部署和管理微服務(wù)應(yīng)用,通過將應(yīng)用定義在聲明式配置文件中,就可以使用原生的Docker命令完成部署,還支持滾動(dòng)升級(jí)、回滾以及擴(kuò)容操作。
從集群的交讀來說,一個(gè)Swarm由一個(gè)或多個(gè)Docker節(jié)點(diǎn)組成,節(jié)點(diǎn)會(huì)被配置為管理節(jié)點(diǎn)和工作節(jié)點(diǎn)。Swarm的配置和狀態(tài)信息保存在etcd里,它作為Swarm的一部分被安裝。同時(shí),在集群里Swarm使用TLS進(jìn)行通信加密、節(jié)點(diǎn)認(rèn)證和角色授權(quán)以及自動(dòng)密鑰輪換。
對(duì)于應(yīng)用編排,Swarm中的最小調(diào)度單位是服務(wù),是一個(gè)基于容器的更高層次的概念,當(dāng)容器被封裝在一個(gè)服務(wù)中時(shí),我們稱之為一個(gè)任務(wù)或一個(gè)副本,一個(gè)服務(wù)也具有擴(kuò)縮容、滾動(dòng)升級(jí)以及簡單回滾等特性。


Swarm概括.PNG

Swarm集群示例:
Swarm集群里的節(jié)點(diǎn)情況如下:

Swarm集群.PNG

每個(gè)節(jié)點(diǎn)都需要安裝Docker,并且能夠與Swarm的其它節(jié)點(diǎn)通信。不包含在任何Swarm中的Docker節(jié)點(diǎn)稱為運(yùn)行于單引擎模式,而一旦被加入Swarm集群,則稱為Swarm模式。在安裝Docker時(shí),需要在路由器和防火墻中開放如下端口:


Docker節(jié)點(diǎn)開放端口.PNG

滿足以上前提后,就可以著手開始搭建Swarm集群了:
在單引擎模式下的Docker主機(jī)上運(yùn)行docker swarm init會(huì)將其切換到Swarm模式,并創(chuàng)建一個(gè)新的Swarm,將自身設(shè)置為Swarm的第一個(gè)管理節(jié)點(diǎn)。其它節(jié)點(diǎn)則可以作為管理節(jié)點(diǎn)或工作節(jié)點(diǎn)加入進(jìn)來,這一操作也會(huì)將新加入的節(jié)點(diǎn)切換為Swarm模式。

  1. 登錄到mgr1并初始化一個(gè)新的Swarm。
docker swarm init --advertise-addr 10.0.0.1:2377 --listen-addr 10.0.0.1:2377

--advertise-addr指定其它節(jié)點(diǎn)用來連接到當(dāng)前節(jié)點(diǎn)的IP和端口,如果你的機(jī)器只有一個(gè) IP 地址,可以省略,docker 會(huì)自動(dòng)選擇正確的 IP。當(dāng)節(jié)點(diǎn)上有多個(gè)IP時(shí),可以用于指定使用哪個(gè)IP。此外,還可以指定一個(gè)節(jié)點(diǎn)上沒有的IP,比如一個(gè)負(fù)載均衡的IP。
--listen-addr指定用于承載Swarm流量的IP和端口。其設(shè)置通常與--advertise-addr相匹配,但是當(dāng)節(jié)點(diǎn)上有多個(gè)IP的時(shí)候,可用于指定具體某個(gè)IP。并且,如果--advertise-addr設(shè)置了一個(gè)遠(yuǎn)程IP地址(如負(fù)載均衡的IP地址),該屬性也是需要設(shè)置的。


Swarm常用端口.PNG
  1. 查看Swarm當(dāng)前節(jié)點(diǎn)。


    Swarm第一個(gè)節(jié)點(diǎn).PNG
  2. 在mgr1上執(zhí)行docker swarm join-token命令來獲取添加新的工作節(jié)點(diǎn)和管理節(jié)點(diǎn)到Swarm的命令和Token。

    加入Swarm.PNG

  3. 登錄wrk1,并使用包含工作節(jié)點(diǎn)接入Token的docker swarm join命令將其接入Swarm。

    加入一個(gè)工作節(jié)點(diǎn).PNG

  4. 在wrk2和wrk3上重復(fù)上一步驟來將這兩個(gè)節(jié)點(diǎn)作為工作節(jié)點(diǎn)加入Swarm。

  5. 在mgr2作為管理節(jié)點(diǎn)接入Swarm。


    管理節(jié)點(diǎn)接入.PNG
  6. 在mgr3重復(fù)上一個(gè)操作。

  7. 在任意一個(gè)管理節(jié)點(diǎn)上執(zhí)行docker node ls命令列出Swarm節(jié)點(diǎn)。

    查看Swarm節(jié)點(diǎn).PNG

管理節(jié)點(diǎn)HA:

管理節(jié)點(diǎn)HA.PNG

內(nèi)置的Swarm安全機(jī)制:
Swarm集群內(nèi)置有繁多的安全機(jī)制,并提供了開箱即用的合理默認(rèn)配置——如CA設(shè)置、接入Token、公用TLS、加密集群存儲(chǔ)、加密網(wǎng)絡(luò)、加密節(jié)點(diǎn)ID等。
鎖定Swarm:

鎖定Swarm.PNG

重啟節(jié)點(diǎn)加入Swarm.PNG

Swarm服務(wù)

例如我們要部署有5個(gè)實(shí)例的某web應(yīng)用,先登錄到主管理節(jié)點(diǎn),然后使用命令docker service create

創(chuàng)建Swarm服務(wù).PNG

上圖可以看出,其參數(shù)與docker container run有很多相同的。使用該命令后,主管理節(jié)點(diǎn)會(huì)在Swarm集群中實(shí)例化5個(gè)副本——請(qǐng)注意管理節(jié)點(diǎn)也會(huì)作為工作節(jié)點(diǎn)運(yùn)行。相關(guān)各工作節(jié)點(diǎn)或管理節(jié)點(diǎn)會(huì)拉取鏡像,然后啟動(dòng)相應(yīng)容器。
docker service ls用于查看Swarm中所有運(yùn)行中的服務(wù)。docker service ps [service name|service ID]用于查看服務(wù)副本列表及各副本的狀態(tài)。
docker service inspect --pretty [service name|service ID]用于查看更詳細(xì)的信息。
副本模式和全局模式:
副本模式會(huì)部署期望數(shù)量的服務(wù)副本,并盡可能均勻地將各個(gè)副本分布在整個(gè)集群中。而全局模式下每個(gè)節(jié)點(diǎn)上僅運(yùn)行一個(gè)副本。默認(rèn)是副本模式,可以通過給docker service create命令傳--mode global參數(shù)來部署一個(gè)全局服務(wù)。
服務(wù)的擴(kuò)縮容:
docker service scale用于對(duì)服務(wù)進(jìn)行擴(kuò)縮容。

擴(kuò)縮容.PNG

刪除服務(wù):
docker service rm [service name|service ID]

滾動(dòng)升級(jí):
登錄主管理節(jié)點(diǎn),執(zhí)行docker network create -d overlay uber-net,該命令會(huì)創(chuàng)建一個(gè)名為uber-net的覆蓋網(wǎng)絡(luò)。再執(zhí)行docker service create --name uber-svc --network uber-net -p 80:80 --replicas 12 nigelpoulton/tu-demo:v1該命令會(huì)創(chuàng)建一個(gè)新的服務(wù),使用v1鏡像,并將其接入uber-net網(wǎng)絡(luò)。
對(duì)與Swarm的網(wǎng)絡(luò),默認(rèn)是入站模式,該模式下即使節(jié)點(diǎn)上沒有服務(wù)的副本也會(huì)開放對(duì)應(yīng)端口;此外還有主機(jī)模式,僅在運(yùn)行有容器副本的節(jié)點(diǎn)上開放端口。下面的命令是以主機(jī)模式創(chuàng)建服務(wù):docker service create --name uber-svc --network uber-net --publish published=80,target=80,mode=host --replicas 12 nigelpoulton/tu-demo:v1。在入站模式下,即使某個(gè)節(jié)點(diǎn)上并沒有運(yùn)行服務(wù)的副本,依然可以進(jìn)行訪問——所有節(jié)點(diǎn)都配置有映射,因此會(huì)將請(qǐng)求轉(zhuǎn)發(fā)給運(yùn)行有服務(wù)副本的節(jié)點(diǎn)
docker service update --image nigelpoulton/tu-demo:v2 --update-parallelism 2 --update-delay 20s uber-svc該命令會(huì)對(duì)uber-svc進(jìn)行升級(jí),每次更新兩個(gè)副本,并且間隔20s,使用新鏡像v2。
查看日志:
docker service logs [service name|service ID]

Docker網(wǎng)絡(luò)

Docker的網(wǎng)絡(luò)的部分都是由Libnetwork實(shí)現(xiàn),它是一個(gè)獨(dú)立于docker daemon的庫,是CNM設(shè)計(jì)規(guī)范的實(shí)現(xiàn)。


CNM設(shè)計(jì).PNG

單機(jī)橋接網(wǎng)絡(luò):
docker network create -d bridge會(huì)調(diào)用Libnetwork內(nèi)置的網(wǎng)橋驅(qū)動(dòng)去創(chuàng)建一個(gè)虛擬網(wǎng)橋(Docker有個(gè)默認(rèn)網(wǎng)橋,映射在主機(jī)上的docker0),當(dāng)Docker運(yùn)行一個(gè)容器時(shí),會(huì)調(diào)用Libnetwork去創(chuàng)建一對(duì)veth虛擬網(wǎng)卡,然后將這對(duì)虛擬網(wǎng)卡的一個(gè)放在容器里(也就是對(duì)應(yīng)的網(wǎng)絡(luò)命名空間),一個(gè)放在虛擬網(wǎng)橋上。以上這些是我的分析,可能不正確。
Linux上默認(rèn)的Bridge網(wǎng)絡(luò)是不支持通過Docker DNS服務(wù)進(jìn)行域名解析的,而自定義橋接網(wǎng)絡(luò)可以。

macvlan:

macvlan.PNG

查看daemon日志:

查看daemon日志.PNG

修改daemon日志級(jí)別.PNG

查看容器日志:

容器日志.PNG

服務(wù)發(fā)現(xiàn):

docker DNS.PNG

Ingress網(wǎng)絡(luò):

Swarm發(fā)布模式.PNG

Docker網(wǎng)絡(luò)命令總結(jié):

Docker網(wǎng)絡(luò)命令.PNG

Docker覆蓋網(wǎng)絡(luò)

創(chuàng)建一個(gè)覆蓋網(wǎng)絡(luò)十分容易:

  1. 創(chuàng)建一個(gè)Swarm集群;
  2. 登錄主管理節(jié)點(diǎn),然后創(chuàng)建一個(gè)overlay網(wǎng)絡(luò),此時(shí)其它節(jié)點(diǎn)是看不到這個(gè)網(wǎng)絡(luò)的,并且網(wǎng)絡(luò)的控制層已是加密,帶上-o encrypted還可以對(duì)數(shù)據(jù)層加密;
  3. 創(chuàng)建一個(gè)服務(wù),此時(shí)所有節(jié)點(diǎn)都會(huì)自動(dòng)連接到這個(gè)overlay網(wǎng)絡(luò),并可以通過容器名或ip地址相互ping通。

Docker卷

Docker卷.PNG

docker container run --mount source=[volume name],target=/vol [image name]創(chuàng)建一個(gè)容器,并掛在一個(gè)卷(沒有的話自動(dòng)新建)到容器里的/vol目錄下。Swarm模式下創(chuàng)建服務(wù)時(shí)也可以帶上--mount。

Docker卷命令.PNG

捕獲.PNG

Docker Stack

用Docker Stack來部署總體來說比較容易,簡單來說就是用Compose(也稱Stack文件)文件定義應(yīng)用,然后通過docker stack deploy命令完成部署管理。
下面以一個(gè)簡單的應(yīng)用舉例說明:


Docker Stack應(yīng)用.PNG

最重要的就是項(xiàng)目里的Stack文件,這里先簡單寫下這個(gè)文件:

version: "3.2"
services:
    reverse_proxy:
        image: dockersamples/atseasampleshopapp_reverse_proxy
        ports:
            - "80:80"
            - "443:443"
        secrets:
            - source: revprox_cert
              target: revprox_cert
            - source: revprox_key
              target: revprox_key
        networks:
            - front-tier
    database:
        image: dockersamples/atsea_db
        environment:
            POSTGRES_USER: gordonuser
            POSTGRES_DB_PASSWORD_FILE: /run/secrets/postgres_password
            POSTGRES_DB: atsea
        networks:
            - back-tier
        secrets:
            - postgres_password
        deploy:
            placement:
                constraints:
                    - 'node.role == worker'
    appserver:
        image: dockersample/atsea_app
        networks:
            - fron-tier
            - back-tier
            - payment
        deploy:
            replicas: 2
            update_config:
                parallelism: 2
                failure_action: rollback
            placement:
                constraints:
                - 'node.role == worker'
            restart_policy:
                condition: on-failure
                delay: 5s
                max_attempts: 3
                window: 120s
            secrets:
                - postgres_password
    visualizer:
        image: dockersample/visualizer:stable
        ports:
            - "8001:8080"
        stop_grace_period: 1m30s
        volumes:
            - "var/run/docker.sock:/var/run/docker/sock"
        deploy:
            update_config:
                failure_action: rollback
            placement:
                constraints:
                    - 'node.role == manager'
    payment_gateway:
        image: dockersamples/atseasampleshopapp_payment_gateway
        secrets:
            - source: staging_token
              target: payment_token
         networks:
             - payment
         deploy:
             update_config:
                 failure_action: rollback
             placement:
                 constraints:
                     - 'node.role == worker'
                     - 'node.labels.pcidss == yes'
networks:
    front-tier:
    back-tier:
    payment:
        driver: overlay
        driver_opts:
            encrypted: 'yes'
secrets:
    postgres_password:
        external: true
    staging_token:
        external: true
    revprox_key:
        external: true
    revprox_cert:
        external: true

可以看出上面的Stack文件有4個(gè)頂級(jí)key,接下來詳細(xì)分析每個(gè)頂級(jí)key:
networks
可以看出上面定義了3個(gè)網(wǎng)絡(luò),默認(rèn)情況下,這些網(wǎng)絡(luò)都會(huì)采用overlay驅(qū)動(dòng)。payment網(wǎng)絡(luò)較為特殊,它增加了數(shù)據(jù)層加密的功能,也可以在docker network create命令中指定-o encrypted參數(shù)來實(shí)現(xiàn)數(shù)據(jù)層加密。
secrets
注意到4個(gè)密鑰都被定義為external,這意味著在Stack部署之前,這些密鑰必須存在。
services
image關(guān)鍵字是服務(wù)里唯一必選項(xiàng),Docker Stack和Docker Compose的一個(gè)區(qū)別是Stack不支持構(gòu)建,這意味著在部署Stack之前,所有鏡像必須是提前構(gòu)建好的。倉庫服務(wù)名是可選的,默認(rèn)會(huì)從Docker Hub拉取。
默認(rèn)情況下,所有端口映射都采用Ingress模式,這意味著Swarm集群中每個(gè)節(jié)點(diǎn)的對(duì)應(yīng)端口都會(huì)映射并且是可訪問的,即使是那些沒有運(yùn)行副本的節(jié)點(diǎn)。另一種方式是Host模式,端口只映射到運(yùn)行副本的Starm節(jié)點(diǎn),但是Host模式需要使用完整的配置:

ports:
    - target: 80
      published: 80
      mode: host

secrets關(guān)鍵字表面這個(gè)服務(wù)用來兩個(gè)密鑰,這兩個(gè)密鑰必須在頂級(jí)關(guān)鍵字secrets下定義了,并且必須在系統(tǒng)上已經(jīng)存在。部署后,密鑰以普通文件的形式被掛載到服務(wù)副本當(dāng)中,文件的名稱就是Stack文件中定義的target屬性的值,其在Linux下的路徑為/run/secrets,例如/run/secrets/revprox_cert和/run/secrets/revprox_key。還可以通過docker service create --sercret [secret name]暴露某個(gè)secret給某個(gè)服務(wù)。
networks關(guān)鍵字確保服務(wù)的所有副本都會(huì)連接到front-tier網(wǎng)絡(luò),網(wǎng)絡(luò)相關(guān)定義必須位于頂級(jí)關(guān)鍵字networks之下,如果定義的網(wǎng)絡(luò)不存在,Docker會(huì)以O(shè)verlay網(wǎng)絡(luò)方式新建一個(gè)網(wǎng)絡(luò)。
deploy關(guān)鍵字保證了當(dāng)前服務(wù)只會(huì)運(yùn)行在Swarm集群的worker節(jié)點(diǎn)之上。Swarm還支持以下約束:

部署約束.PNG

在appserver里,replicas關(guān)鍵字設(shè)置期望服務(wù)的副本數(shù)量為2,默認(rèn)值為1。update_config定義了Docker在服務(wù)滾動(dòng)升級(jí)的時(shí)候具體如何操作,在這個(gè)例子里,Docker每次會(huì)更新兩個(gè)副本。failure_action規(guī)定了升級(jí)失敗后自動(dòng)回滾,failure_action的默認(rèn)操作是pause,會(huì)在服務(wù)升級(jí)失敗后阻止其它副本的升級(jí),還支持continue操作。
restart-policy定義了Swarm針對(duì)容器異常退出的重啟策略。在這個(gè)例子中,如果某個(gè)副本以非0返回值退出(conditon: onfailure),會(huì)立即重啟當(dāng)前副本,重啟最多重試3次,每次都會(huì)等待至多120s來檢測(cè)是否啟動(dòng)成功,每次重啟的間隔是5s。
當(dāng)docker要停止某個(gè)容器時(shí),會(huì)給容器內(nèi)部PID為1的進(jìn)程發(fā)送SIGTERM信號(hào),容器內(nèi)PID為1的進(jìn)程會(huì)有10s的時(shí)間來執(zhí)行一些清理操作,如果進(jìn)程沒有處理該信號(hào),那么10s后就會(huì)被SIGKILL信號(hào)強(qiáng)制結(jié)束。而stop_grace_period關(guān)鍵字可以修改這個(gè)10s時(shí)間。volumes關(guān)鍵字用于掛載提前創(chuàng)建的卷或者主機(jī)目錄到某個(gè)服務(wù)副本當(dāng)中,在本例中,會(huì)掛載Docker主機(jī)的/var/run/docker.sock目錄到每個(gè)服務(wù)副本的/var/run/docker.sock路徑,這意味著在服務(wù)副本中任何對(duì)/var/run/docker.sock的讀寫操作都會(huì)指向Docker主機(jī)的對(duì)應(yīng)目錄中。
/var/run/docker/docker.sock恰巧是Docker提供的IPC套接字,Docker daemon通過該套接字對(duì)其它進(jìn)程暴露其API,這意味著給予了容器查詢和管理daemon的能力。
在payment_gateway服務(wù)里多了個(gè)node.label約束,這是一個(gè)標(biāo)簽約束,可以通過docker node update命令來自定義標(biāo)簽,并添加到Swarm集群的指定節(jié)點(diǎn),node.label配置只適用于Swarm集群中的節(jié)點(diǎn),不能用于單獨(dú)的容器。

部署Stack應(yīng)用

在進(jìn)行部署之前,有幾個(gè)前置處理需要完成:

  • Swarm模式:應(yīng)用將采用Docker Stack部署,而Stack依賴Swarm模式。
  • 標(biāo)簽:某個(gè)Swarm worker節(jié)點(diǎn)需要自定義標(biāo)簽
  • 密鑰:應(yīng)用所需的密鑰需要在部署前創(chuàng)建完成


    示例環(huán)境.PNG

上圖中給wrk-1節(jié)點(diǎn)添加標(biāo)簽可以在管理節(jié)點(diǎn)上執(zhí)行一下命令:
docker node update --label-add key=value wrk-1
應(yīng)用定義了4個(gè)密鑰,這些都要在部署前創(chuàng)建好。在管理節(jié)點(diǎn)上運(yùn)行下面的命令:
openssl req -newkey rsa:4096 -nodes -sha256 -keyout domain.key -x509 -days 365 -out domain.crt這個(gè)命令會(huì)創(chuàng)建一個(gè)證書和對(duì)應(yīng)的私鑰。
下面分別創(chuàng)建revprox_cert、revprox_key、postgree_password、stage_token:

docker secret create revprox_cert domain.crt
docker secret create revprox_key domain.key
docker secret create postgres_password domain.key
echo staging | docker secret create staging_token -

開始部署:
docker stack deploy -c docker-stack.yml seastack

Docker Stack部署.PNG

如果想查看具體某個(gè)服務(wù)的詳細(xì)信息,可以使用docker service logs命令,需要將服務(wù)名稱/ID或者副本ID作為參數(shù)傳入。如果傳入服務(wù)名稱或ID,可以看到所有服務(wù)副本的日志信息,如果傳入的是副本ID,只會(huì)看到對(duì)應(yīng)副本的日志信息。

docker stack管理應(yīng)用

雖然可以通過docker service scale命令來擴(kuò)充某個(gè)服務(wù)的副本數(shù),但這不是推薦的方式,最好是將Stack文件作為配置的唯一聲明,然后重新執(zhí)行docker stack deploy -c docker-stack.yml seastack即可,重新部署Stack并不會(huì)影響那些沒有改動(dòng)的服務(wù)。

Docker Stack命令.PNG

Docker安全

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 深入淺出Docker學(xué)習(xí)筆記 Docker引擎 Docker引擎:用來運(yùn)行和管理容器的核心文件模塊化(基于開放容器...
    yuq329閱讀 981評(píng)論 0 4
  • docker概念 鏡像與容器 docker鏡像是一個(gè)統(tǒng)一文件系統(tǒng),由一系列只讀層堆疊而成。容器則是在只讀層堆頂加上...
    羽色云煙閱讀 865評(píng)論 0 0
  • 從Docker 1.11開始,Docker容器運(yùn)行已經(jīng)不是簡單的通過Docker daemon來啟動(dòng),而是集成了c...
    泛輕舟gen閱讀 27,338評(píng)論 4 11
  • containerd是什么 containerd是容器技術(shù)標(biāo)準(zhǔn)化之后的產(chǎn)物,為了能夠兼容OCI標(biāo)準(zhǔn),將容器運(yùn)行時(shí)及...
    裘馬輕狂大帥閱讀 3,778評(píng)論 0 3
  • 特別說明: 本人平時(shí)混跡于 B 站,不咋回復(fù)這里的評(píng)論,有問題可以到 B 站視頻評(píng)論區(qū)留言找我視頻地址: http...
    擼帝閱讀 1,011評(píng)論 1 3

友情鏈接更多精彩內(nèi)容