《Docker從入門(mén)到實(shí)踐》閱讀筆記

《Docker從入門(mén)到實(shí)踐》閱讀筆記

原書(shū)地址: https://yeasy.gitbooks.io/docker_practice/content/introduction/what.html

[TOC]

1. Docker簡(jiǎn)介

1.1 什么是Docker

1.2 為什么要用Docker

2. 基本概念

2.1 鏡像

  • Docker 鏡像是一個(gè)特殊的文件系統(tǒng),除了提供容器運(yùn)行時(shí)所需的程序、庫(kù)、資源、配置等文件外,還包含了一些為運(yùn)行時(shí)準(zhǔn)備的一些配置參數(shù)(如匿名卷、環(huán)境變量、用戶等)。鏡像不包含任何動(dòng)態(tài)數(shù)據(jù),其內(nèi)容在構(gòu)建之后也不會(huì)被改變。
  • 分層存儲(chǔ):由多層文件系統(tǒng)聯(lián)合組成。

2.2 容器

  • 鏡像(Image)和容器(Container)的關(guān)系,就像是面向?qū)ο蟪绦蛟O(shè)計(jì)中的類(lèi)和實(shí)例 一樣,鏡像是靜態(tài)的定義,容器是鏡像運(yùn)行時(shí)的實(shí)體。
  • 容器的實(shí)質(zhì)是進(jìn)程,但與直接在宿主執(zhí)行的進(jìn)程不同,容器進(jìn)程運(yùn)行于屬于自己的獨(dú)立的 命名空間。因此容器可以擁有自己的 root 文件系統(tǒng)、自己的網(wǎng)絡(luò)配置、自己的進(jìn)程空間,甚至自己的用戶 ID 空間。容器內(nèi)的進(jìn)程是運(yùn)行在一個(gè)隔離的環(huán)境里,使用起來(lái),就好像是在一個(gè)獨(dú)立于宿主的系統(tǒng)下操作一樣。這種特性使得容器封裝的應(yīng)用比直接在宿主運(yùn)行更加安全。也因?yàn)檫@種隔離的特性,很多人初學(xué) Docker 時(shí)常常會(huì)混淆容器和虛擬機(jī)。
  • 前面講過(guò)鏡像使用的是分層存儲(chǔ),容器也是如此。每一個(gè)容器運(yùn)行時(shí),是以鏡像為基礎(chǔ)層,在其上創(chuàng)建一個(gè)當(dāng)前容器的存儲(chǔ)層,我們可以稱(chēng)這個(gè)為容器運(yùn)行時(shí)讀寫(xiě)而準(zhǔn)備的存儲(chǔ)層為容器存儲(chǔ)層。
  • 容器存儲(chǔ)層的生存周期和容器一樣,容器消亡時(shí),容器存儲(chǔ)層也隨之消亡。因此,任何保存于容器存儲(chǔ)層的信息都會(huì)隨容器刪除而丟失。
  • 按照 Docker 最佳實(shí)踐的要求,容器不應(yīng)該向其存儲(chǔ)層內(nèi)寫(xiě)入任何數(shù)據(jù),容器存儲(chǔ)層要保持無(wú)狀態(tài)化。所有的文件寫(xiě)入操作,都應(yīng)該使用 數(shù)據(jù)卷(Volume)、或者綁定宿主目錄,在這些位置的讀寫(xiě)會(huì)跳過(guò)容器存儲(chǔ)層,直接對(duì)宿主(或網(wǎng)絡(luò)存儲(chǔ))發(fā)生讀寫(xiě),其性能和穩(wěn)定性更高。
  • 數(shù)據(jù)卷的生存周期獨(dú)立于容器,容器消亡,數(shù)據(jù)卷不會(huì)消亡。因此,使用數(shù)據(jù)卷后,容器刪除或者重新運(yùn)行之后,數(shù)據(jù)卻不會(huì)丟失。

2.3 倉(cāng)庫(kù)

2.3.1 Docker Registry

  • Docker倉(cāng)庫(kù)是一個(gè)集中的存儲(chǔ)、分發(fā)鏡像的服務(wù)。
  • 一個(gè)Docker Registry中可以包含多個(gè)倉(cāng)庫(kù)(Repository);每個(gè)倉(cāng)庫(kù)可以包含多個(gè)標(biāo)簽(Tag);每個(gè)標(biāo)簽對(duì)應(yīng)一個(gè)鏡像。
  • 通常,一個(gè)倉(cāng)庫(kù)會(huì)包含同一個(gè)軟件不同版本的鏡像,而標(biāo)簽就常用于對(duì)應(yīng)該軟件的各個(gè)版本。我們可以通過(guò) <倉(cāng)庫(kù)名>:<標(biāo)簽>的格式來(lái)指定具體是這個(gè)軟件哪個(gè)版本的鏡像。如果不給出標(biāo)簽,將以 latest 作為默認(rèn)標(biāo)簽。
  • 倉(cāng)庫(kù)名經(jīng)常以 兩段式路徑 形式出現(xiàn),比如jwilder/nginx-proxy前者往往意味著Docker Registry多用戶環(huán)境下的用戶名,后者則往往是對(duì)應(yīng)的軟件名。但這并非絕對(duì),取決于所使用的具體Docker Registry的軟件或服務(wù)。

2.3.2 Docker Registry 公開(kāi)服務(wù)

  • Docker Registry 公開(kāi)服務(wù)是開(kāi)放給用戶使用、允許用戶管理鏡像的 Registry 服務(wù)。一般這類(lèi)公開(kāi)服務(wù)允許用戶免費(fèi)上傳、下載公開(kāi)的鏡像,并可能提供收費(fèi)服務(wù)供用戶管理私有鏡像。最常使用的 Registry 公開(kāi)服務(wù)是官方的Docker Hub。
  • 由于某些原因,在國(guó)內(nèi)訪問(wèn)這些服務(wù)可能會(huì)比較慢。國(guó)內(nèi)的一些云服務(wù)商提供了針對(duì) Docker Hub 的鏡像服務(wù)(Registry Mirror),這些鏡像服務(wù)被稱(chēng)為加速器。常見(jiàn)的有 阿里云加速器DaoCloud 加速器 等。使用加速器會(huì)直接從國(guó)內(nèi)的地址下載 Docker Hub 的鏡像,比直接從 Docker Hub 下載速度會(huì)提高很多。在 3. 安裝 Docker 一節(jié)中有詳細(xì)的配置方法。
  • 國(guó)內(nèi)也有一些云服務(wù)商提供類(lèi)似于 Docker Hub 的公開(kāi)服務(wù)。比如 時(shí)速云鏡像倉(cāng)庫(kù)、網(wǎng)易云鏡像服務(wù)、DaoCloud 鏡像市場(chǎng)阿里云鏡像庫(kù) 等。

2.3.3 私有 Docker Registry

  • 除了使用公開(kāi)服務(wù)外,用戶還可以在本地搭建私有 Docker Registry。Docker 官方提供了 Docker Registry 鏡像,可以直接使用做為私有 Registry 服務(wù)。在 私有倉(cāng)庫(kù) 一節(jié)中,會(huì)有進(jìn)一步的搭建私有 Registry 服務(wù)的講解。

3. 安裝Docker {#install}

  • 版本命名規(guī)則:
    項(xiàng)目|說(shuō)明
    -|-
    版本格式|YY.MM
    Stable版本|每季度發(fā)行
    Edge版本|每月發(fā)行
  • 同時(shí) Docker 劃分為 CE 和 EE。CE,即社區(qū)版(免費(fèi),支持周期三個(gè)月);EE, 即企業(yè)版,強(qiáng)調(diào)安全,付費(fèi)使用。

3.1 Ubuntu

3.1.1 卸載舊版本

$sudo apt-get remove docker docker-engine docker.io

3.1.2 安裝可選內(nèi)核模塊

$ sudo apt-get update
$ sudo apt-get install linux-image-extra-$(uname -r) \ 
> linux-image-extra-virtual

3.1.3 使用APT安裝

$ sudo apt-get update

$ sudo apt-get install \
>    apt-transport-https \
>    ca-certificates \
>    curl \
>    software-properties-common

鑒于國(guó)內(nèi)網(wǎng)絡(luò)問(wèn)題,強(qiáng)烈建議使用國(guó)內(nèi)源,官方源請(qǐng)?jiān)谧⑨屩胁榭础?/p>

為了確認(rèn)所下載軟件包的合法性,需要添加軟件源的 GPG 密鑰。

$ curl -fsSL \
> https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg \ 
> | sudo apt-key add -

然后,我們需要向source.list 中添加 Docker 軟件源

$ sudo add-apt-repository "deb \
> [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu \
> $(lsb_release -cs) stable"

3.1.4 安裝Docker CE

$ sudo apt-get update
$ sudo apt-get install docker-ce

3.1.5 使用腳本自動(dòng)安裝

$ curl -fsSL get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh --mirror Aliyun

3.1.6 啟動(dòng)Docker CE

$ sudo systemctl enable docker
$ sudo systemctl start docker

3.1.7 建立docker用戶組

  • 建立Docker組:
$ sudo groupadd docker
  • 將當(dāng)前用戶加入docker組:
$ sudo usermod -aG docker $USER

退出當(dāng)前終端并重新登錄,進(jìn)行如下測(cè)試。

3.1.8 測(cè)試Docker是否安裝正確

若出現(xiàn)如下信息,說(shuō)明安裝成功:

$ docker run hello-world

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
ca4f61b1923c: Pull complete
Digest: sha256:be0cd392e45be79ffeffa6b05338b98ebb16c87b255f48e297ec7f98e123905c
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://cloud.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/engine/userguide/

3.2 Debian

3.3 CentOS

3.4 Raspberry Pi

3.5 macOS

3.6 Windows PC

3.7 鏡像加速器

國(guó)內(nèi)從 Docker Hub 拉取鏡像有時(shí)會(huì)遇到困難,此時(shí)可以配置鏡像加速器。Docker 官方和國(guó)內(nèi)很多云服務(wù)商都提供了國(guó)內(nèi)加速器服務(wù),例如:

Ubuntu 16.04+、Debian 8+、CentOS 7
對(duì)于使用 systemd 的系統(tǒng),請(qǐng)?jiān)?/etc/docker/daemon.json 中寫(xiě)入如下內(nèi)容(如果文件不存在請(qǐng)新建該文件)

{
  "registry-mirrors": [
    "https://registry.docker-cn.com"
  ]
}

之后重啟服務(wù)

$ sudo systemctl daemon-reload
$ sudo systemctl restart docker

檢查是否生效:
??配置加速器之后,如果拉取鏡像仍然十分緩慢,請(qǐng)手動(dòng)檢查加速器配置是否生效,在命令行執(zhí)行docker info,如果從結(jié)果中看到了如下內(nèi)容,說(shuō)明配置成功。

Registry Mirrors:
 https://registry.docker-cn.com/

4. 使用Docker鏡像

Docker的三大組件:鏡像、容器和倉(cāng)庫(kù)

4.1 獲取鏡像

docker pull [選項(xiàng)] [Docker Registry 地址[:端口號(hào)]/]倉(cāng)庫(kù)名[:標(biāo)簽]
  • Docker 鏡像倉(cāng)庫(kù)地址:地址的格式一般是 <域名/IP>[:端口號(hào)]。默認(rèn)地址是 Docker Hub。
  • 倉(cāng)庫(kù)名:如之前所說(shuō),這里的倉(cāng)庫(kù)名是兩段式名稱(chēng),即 <用戶名>/<軟件名>。對(duì)于 Docker Hub,如果不給出用戶名,則默認(rèn)為 library,也就是官方鏡像。
  • 比如:
$ docker pull ubuntu:16.04
16.04: Pulling from library/ubuntu
bf5d46315322: Pull complete
9f13e0ac480c: Pull complete
e8988b5b3097: Pull complete
40af181810e7: Pull complete
e6f7c7e5c03e: Pull complete
Digest: sha256:147913621d9cdea08853f6ba9116c2e27a3ceffecf3b492983ae97c3d643fbbe
Status: Downloaded newer image for ubuntu:16.04

??上面的命令中沒(méi)有給出 Docker 鏡像倉(cāng)庫(kù)地址,因此將會(huì)從 Docker Hub 獲取鏡像。而鏡像名稱(chēng)是 ubuntu:16.04,因此將會(huì)獲取官方鏡像 library/ubuntu 倉(cāng)庫(kù)中標(biāo)簽為 16.04 的鏡像。
??下載過(guò)程中給出了每一層的 ID 的前 12 位。并且下載結(jié)束后,給出該鏡像完整的 sha256 的摘要,以確保下載一致性。

運(yùn)行:
??有了鏡像后,我們就能夠以這個(gè)鏡像為基礎(chǔ)啟動(dòng)并運(yùn)行一個(gè)容器。以上面的 ubuntu:16.04 為例,如果我們打算啟動(dòng)里面的 bash 并且進(jìn)行交互式操作的話,可以執(zhí)行下面的命令。

$ docker run -it --rm ubuntu:16.04 bash

root@a1765e7e0b4b:/# cat /etc/os-release
NAME="Ubuntu"
VERSION="16.04.3 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.3 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial

參數(shù)介紹:

  • -it:這是兩個(gè)參數(shù),一個(gè)是 -i:交互式操作,一個(gè)是 -t 終端。我們這里打算進(jìn)入 bash 執(zhí)行一些命令并查看返回結(jié)果,因此我們需要交互式終端。
  • --rm:這個(gè)參數(shù)是說(shuō)容器退出后隨之將其刪除。默認(rèn)情況下,為了排障需求,退出的容器并不會(huì)立即刪除,除非手動(dòng) docker rm。我們這里只是隨便執(zhí)行個(gè)命令,看看結(jié)果,不需要排障和保留結(jié)果,因此使用 --rm 可以避免浪費(fèi)空間。
  • ubuntu:16.04:這是指用 ubuntu:16.04 鏡像為基礎(chǔ)來(lái)啟動(dòng)容器。
  • bash:放在鏡像名后的是命令,這里我們希望有個(gè)交互式 Shell,因此用的是 bash。

??進(jìn)入容器后,我們可以在 Shell 下操作,執(zhí)行任何所需的命令。這里,我們執(zhí)行了 cat /etc/os-release,這是 Linux 常用的查看當(dāng)前系統(tǒng)版本的命令,從返回的結(jié)果可以看到容器內(nèi)是 Ubuntu 16.04.4 LTS 系統(tǒng)。最后我們通過(guò) exit 退出了這個(gè)容器。

4.2 列出鏡像

要想列出已經(jīng)下載下來(lái)的鏡像,可以使用 docker image ls 命令。

$ docker image ls
REPOSITORY    TAG    IMAGE ID        CREATED        SIZE
ubuntu        16.04  0458a4468cbc    3 days ago     112MB
hello-world   latest f2a91732366c    2 months ago   1.85kB

鏡像 ID 則是鏡像的唯一標(biāo)識(shí),一個(gè)鏡像可以對(duì)應(yīng)多個(gè)標(biāo)簽。

鏡像體積
??如果仔細(xì)觀察,會(huì)注意到,這里標(biāo)識(shí)的所占用空間和在 Docker Hub 上看到的鏡像大小不同。比如,ubuntu:16.04 鏡像大小,在這里是 127 MB,但是在 Docker Hub 顯示的卻是 50 MB。這是因?yàn)?Docker Hub 中顯示的體積是壓縮后的體積。在鏡像下載和上傳過(guò)程中鏡像是保持著壓縮狀態(tài)的,因此 Docker Hub 所顯示的大小是網(wǎng)絡(luò)傳輸中更關(guān)心的流量大小。而 docker image ls 顯示的是鏡像下載到本地后,展開(kāi)的大小。

虛懸鏡像(dangling image)
??有些鏡像既沒(méi)有倉(cāng)庫(kù)名,也沒(méi)有標(biāo)簽,均為<none>。這個(gè)鏡像原本是有鏡像名和標(biāo)簽的,隨著官方鏡像維護(hù),發(fā)布了新版本后,重新 docker pull 時(shí),舊的鏡像名被轉(zhuǎn)移到了新下載的鏡像身上,而舊的鏡像上的這個(gè)名稱(chēng)則被取消,從而成為了 <none>。除了 docker pull 可能導(dǎo)致這種情況,docker build 也同樣可以導(dǎo)致這種現(xiàn)象。由于新舊鏡像同名,舊鏡像名稱(chēng)被取消,從而出現(xiàn)倉(cāng)庫(kù)名、標(biāo)簽均為 <none> 的鏡像。可以用下面的命令專(zhuān)門(mén)顯示這類(lèi)鏡像:

$ docker image ls -f dangling=true

一般來(lái)說(shuō),虛懸鏡像已經(jīng)失去了存在的價(jià)值,可以隨意刪除,可以用下面的命令刪除。

$ docker image prune

中間層鏡像
??為了加速鏡像構(gòu)建、重復(fù)利用資源,Docker 會(huì)利用中間層鏡像。所以在使用一段時(shí)間后,可能會(huì)看到一些依賴(lài)的中間層鏡像。默認(rèn)的 docker image ls 列表中只會(huì)顯示頂層鏡像,如果希望顯示包括中間層鏡像在內(nèi)的所有鏡像的話,需要加 -a 參數(shù)。

$ docker image ls -a

??這樣會(huì)看到很多無(wú)標(biāo)簽的鏡像,與之前的虛懸鏡像不同,這些無(wú)標(biāo)簽的鏡像很多都是中間層鏡像,是其它鏡像所依賴(lài)的鏡像。這些無(wú)標(biāo)簽鏡像不應(yīng)該刪除,否則會(huì)導(dǎo)致上層鏡像因?yàn)橐蕾?lài)丟失而出錯(cuò)。實(shí)際上,這些鏡像也沒(méi)必要?jiǎng)h除,因?yàn)橹罢f(shuō)過(guò),相同的層只會(huì)存一遍,而這些鏡像是別的鏡像的依賴(lài),因此并不會(huì)因?yàn)樗鼈儽涣谐鰜?lái)而多存了一份,無(wú)論如何你也會(huì)需要它們。只要?jiǎng)h除那些依賴(lài)它們的鏡像后,這些依賴(lài)的中間層鏡像也會(huì)被連帶刪除。

列出部分鏡像
??不加任何參數(shù)的情況下,docker image ls 會(huì)列出所有頂級(jí)鏡像,但是有時(shí)候我們只希望列出部分鏡像。docker image ls 有好幾個(gè)參數(shù)可以幫助做到這個(gè)事情。

  • 根據(jù)倉(cāng)庫(kù)名列出鏡像
$ docker image ls ubuntu
  • 列出特定的某個(gè)鏡像,也就是說(shuō)指定倉(cāng)庫(kù)名和標(biāo)簽
$ docker image ls ubuntu:16.04
  • docker image ls 還支持強(qiáng)大的過(guò)濾器參數(shù) --filter,或者簡(jiǎn)寫(xiě) -f。之前我們已經(jīng)看到了使用過(guò)濾器來(lái)列出虛懸鏡像的用法,它還有更多的用法。比如,我們希望看到在 mongo:3.2 之后(查看'之前',將since改為before)建立的鏡像,可以用下面的命令:
$ docker image ls -f since=mongo:3.2

以特定格式顯示
??默認(rèn)情況下,docker image ls 會(huì)輸出一個(gè)完整的表格,但是我們并非所有時(shí)候都會(huì)需要這些內(nèi)容。比如,剛才刪除虛懸鏡像的時(shí)候,我們需要利用 docker image ls 把所有的虛懸鏡像的 ID 列出來(lái),然后才可以交給 docker image rm 命令作為參數(shù)來(lái)刪除指定的這些鏡像,這個(gè)時(shí)候就用到了 -q 參數(shù)。

$ docker image ls -q
5f515359c7f8
05a60462f8ba
fe9198c04d62
00285df0df87
f753707788c5
f753707788c5
1e0c3dd64ccd

??自定義格式返回(可將輸出結(jié)果直接作為下一條命令的輸入),如下面的命令會(huì)直接列出鏡像結(jié)果,并且只包含鏡像ID和倉(cāng)庫(kù)名:

$ docker image ls --format "{{.ID}}: {{.Repository}}"
5f515359c7f8: redis
05a60462f8ba: nginx
fe9198c04d62: mongo
00285df0df87: <none>
f753707788c5: ubuntu
f753707788c5: ubuntu
1e0c3dd64ccd: ubuntu

或者打算以表格等距顯示,并且有標(biāo)題行,和默認(rèn)一樣,不過(guò)自己定義列:

$ docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"
IMAGE ID            REPOSITORY          TAG
5f515359c7f8        redis               latest
05a60462f8ba        nginx               latest
fe9198c04d62        mongo               3.2
00285df0df87        <none>              <none>
f753707788c5        ubuntu              16.04
f753707788c5        ubuntu              latest
1e0c3dd64ccd        ubuntu              14.04

4.3 刪除鏡像

如果要?jiǎng)h除本地的鏡像,可以使用 docker image rm 命令,其格式為:

$ docker image rm [選項(xiàng)] <鏡像1> [<鏡像2> ...]

其中,<鏡像> 可以是 鏡像短 ID鏡像長(zhǎng) ID、鏡像名 或者 鏡像摘要。
比如我們有這么一些鏡像:

$ docker image ls
REPOSITORY      TAG     IMAGE ID        CREATED     SIZE
centos          latest  0584b3d2cf6d    3 weeks ago 196.5 MB
redis           alpine  501ad78535f0    3 weeks ago 21.03 MB
docker          latest  cf693ec9b5c7    3 weeks ago 105.1 MB
nginx           latest  e43d811ce2f4    5 weeks ago 181.5 MB

我們可以用鏡像的完整 ID,也稱(chēng)為 長(zhǎng) ID,來(lái)刪除鏡像。使用腳本的時(shí)候可能會(huì)用長(zhǎng) ID,但是人工輸入就太累了,所以更多的時(shí)候是用 短 ID 來(lái)刪除鏡像。 docker image ls 默認(rèn)列出的就已經(jīng)是短 ID 了,一般取前3個(gè)字符以上,只要足夠區(qū)分于別的鏡像就可以了。
比如這里,如果我們要?jiǎng)h除 redis:alpine 鏡像,可以執(zhí)行:

$ docker image rm 501
Untagged: redis:alpine
Untagged: redis@sha256:f1ed3708f538b537eb9c2a7dd50dc90a706f7debd7e1196c9264edeea521a86d
Deleted: sha256:501ad78535f015d88872e13fa87a828425117e3d28075d0c117932b05bf189b7
Deleted: sha256:96167737e29ca8e9d74982ef2a0dda76ed7b430da55e321c071f0dbff8c2899b
Deleted: sha256:32770d1dcf835f192cafd6b9263b7b597a1778a403a109e2cc2ee866f74adf23
Deleted: sha256:127227698ad74a5846ff5153475e03439d96d4b1c7f2a449c7a826ef74a2d2fa
Deleted: sha256:1333ecc582459bac54e1437335c0816bc17634e131ea0cc48daa27d32c75eab3
Deleted: sha256:4fc455b921edf9c4aea207c51ab39b10b06540c8b4825ba57b3feed1668fa7c7

我們也可以用鏡像名,也就是 <倉(cāng)庫(kù)名>:<標(biāo)簽>,來(lái)刪除鏡像。

$ docker image rm centos
Untagged: centos:latest
Untagged: centos@sha256:b2f9d1c0ff5f87a4743104d099a3d561002ac500db1b9bfa02a783a46e0d366c
Deleted: sha256:0584b3d2cf6d235ee310cf14b54667d889887b838d3f3d3033acd70fc3c48b8a
Deleted: sha256:97ca462ad9eeae25941546209454496e1d66749d53dfa2ee32bf1faabd239d38

當(dāng)然,更精確的是使用 鏡像摘要 刪除鏡像。

$ docker image ls --digests
REPOSITORY  TAG     DIGEST      IMAGE ID        CREATED     SIZE
node        slim    sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228   6e0c4c8e3913        3 weeks ago         214 MB

$ docker image rm node@sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228
Untagged: node@sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228

Untagged和Delete

  • 刪除行為分為UntaggedDelete兩類(lèi):
  • 我們使用上面命令刪除鏡像的時(shí)候,是在取消某個(gè)鏡像的標(biāo)簽,即 Untagged。
  • 一個(gè)鏡像可以對(duì)應(yīng)多個(gè)標(biāo)簽,只有某個(gè)鏡像的所有標(biāo)簽都被取消,該鏡像才可能會(huì)被Delete(為什么是可能下文解釋?zhuān)?/li>
  • 由于鏡像的多層結(jié)構(gòu),有可能某個(gè)其它鏡像或容器正依賴(lài)于當(dāng)前鏡像的某一層。在這樣的情況下,該鏡像所有標(biāo)簽都被取消該鏡像也不會(huì)被刪除。



docker image ls命令配合使用
比如,我們需要?jiǎng)h除所有倉(cāng)庫(kù)名為 redis 的鏡像:

$ docker image rm $(docker image ls -q redis)

或者刪除所有在 mongo:3.2 之前的鏡像:

$ docker image rm $(docker image ls -q -f before=mongo:3.2)

4.4利用 commit 理解鏡像構(gòu)成

// 構(gòu)建鏡像,其中90表示綁定服務(wù)器的端口,80表示鏡像端口,瀏覽器訪問(wèn)90端口正常
$ docker run --name webserver -d -p 90:80 nginx 

// 更改Web服務(wù)器內(nèi)容
$ docker exec -it webserver bash
root@3729b97e8226:# echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
root@3729b97e8226:/# exit
exit

// 用commit能夠定制自己的鏡像,不過(guò)使用Dockerfile更好,因此不細(xì)說(shuō)commit

4.5 使用Dockerfile定制鏡像

??Dockerfile 是一個(gè)文本文件,其內(nèi)包含了一條條的指令(Instruction),每一條指令構(gòu)建一層,因此每一條指令的內(nèi)容,就是描述該層應(yīng)當(dāng)如何構(gòu)建。

// 修改服務(wù)器內(nèi)容
$ mkdir mynginx
$ cd mynginx
$ touch Dockerfile

// 內(nèi)容
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
  • FROM指定基礎(chǔ)鏡像,FROM scratch表示以空白鏡像為基礎(chǔ)
  • RUN有兩種格式,第一種更常見(jiàn):
  • RUN <命令>
  • RUN ["可執(zhí)行文件", "參數(shù)1", "參數(shù)2"]

注:每使用一個(gè)RUN就會(huì)加一層鏡像,所以對(duì)于沒(méi)必要記錄的命令可以使用如下形式

FROM debian:jessie

RUN buildDeps='gcc libc6-dev make' \
    && apt-get update \
    && apt-get install -y $buildDeps \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \
    && mkdir -p /usr/src/redis \
    && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
    && make -C /usr/src/redis \
    && make -C /usr/src/redis install \
    && rm -rf /var/lib/apt/lists/* \
    && rm redis.tar.gz \
    && rm -r /usr/src/redis \
    && apt-get purge -y --auto-remove $buildDeps

//注意:最后一句刪除非常重要

構(gòu)建鏡像

// 在Dockerfile目錄下,執(zhí)行以下命令,
// 格式為docker build [選項(xiàng)] <上下文路徑/URL/->
// 執(zhí)行結(jié)束后,即可像上文運(yùn)行nginx一樣運(yùn)行nginx:v3
$ docker build -t nginx:v3 .

??docker是C/S結(jié)構(gòu),并非所有命令都是在本地執(zhí)行,如docker build在Docker引擎(即服務(wù)器端)執(zhí)行,因此我們?cè)趫?zhí)行該命令時(shí)需要給出上下文。如Dockerfile中的命令COPY ./package.json /app/就是復(fù)制給出的上下文下的package.json。
??在給出上下文后,該目錄下的內(nèi)容會(huì)被發(fā)送到服務(wù)器,可以使用.dockerignore文件制定不需要發(fā)送的文件。

4.6 Dockerfile指令詳解

// COPY <源路徑>... <目標(biāo)路徑>,支持正則匹配
COPY hom* /mydir/
COPY hom?.txt /mydir/

// ADD和COPY類(lèi)似,能夠自動(dòng)將gzip, bzip2 以及 xz壓縮格式自動(dòng)解壓,
// 無(wú)需自動(dòng)解壓時(shí),使用COPY
ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /

// CMD 容器啟動(dòng)命令,用于指定默認(rèn)的容器主進(jìn)程的啟動(dòng)命令,類(lèi)似RUN
// 使用該格式'CMD ["可執(zhí)行文件", "參數(shù)1", "參數(shù)2"...]'
// 注:CMD是注進(jìn)程,退出后整個(gè)容器退出,因此不能后臺(tái)執(zhí)行
CMD service nginx start //后臺(tái)執(zhí)行nginx,執(zhí)行完立刻退出
CMD ["nginx", "-g", "daemon off;"] //前臺(tái)執(zhí)行,正確

// ENTRYPOINT和CMD類(lèi)似,不過(guò)可以繼續(xù)加參數(shù)(如docker run myip -i)
// 或者執(zhí)行腳本
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]
ENTRYPOINT ["docker-entrypoint.sh"]

// ENV <key> <value>
ENV NODE_VERSION 7.2.0
RUN curl -SLO https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz

// VOLUME 定義匿名卷
// '/data'目錄就會(huì)在運(yùn)行時(shí)自動(dòng)掛載為匿名卷,任何向'/data'中寫(xiě)入的信息都不會(huì)記錄進(jìn)容器存儲(chǔ)層,從而保證了容器存儲(chǔ)層的無(wú)狀態(tài)化。
VOLUME /data

// WORKDIR 指定工作目錄
WORKDIR <工作目錄路徑>

// USER 指定當(dāng)前用戶
USER <用戶名>

// ONBUILD 當(dāng)內(nèi)容與該項(xiàng)目相關(guān)時(shí),前面加上ONBUILD即可重用
FROM node:slim
RUN mkdir /app
WORKDIR /app
ONBUILD COPY ./package.json /app
ONBUILD RUN [ "npm", "install" ]
ONBUILD COPY . /app/
CMD [ "npm", "start" ]

5. 操作容器

容器是獨(dú)立運(yùn)行的應(yīng)用和他們的環(huán)境。

5.1 啟動(dòng)

??啟動(dòng)分為:新建容器并啟動(dòng)、啟動(dòng)終止?fàn)顟B(tài)的容器;由于docker容器非常輕量級(jí),用戶選擇隨時(shí)新建刪除。

新建并啟動(dòng)
命令為docker run,來(lái)看下面的例子:

$ docker run ubuntu:14.04 /bin/echo 'Hello world'
Hello world
$ docker run -t -i ubuntu:14.04 /bin/bash
root@af8bae53bdd3:/#
//-t 讓Docker分配一個(gè)偽終端(pseudo-tty)并綁定到容器的標(biāo)準(zhǔn)輸入上
//-i 則讓容器的標(biāo)準(zhǔn)輸入保持打開(kāi)。

當(dāng)利用 docker run 來(lái)創(chuàng)建容器時(shí),Docker 在后臺(tái)運(yùn)行的標(biāo)準(zhǔn)操作包括:

  • 檢查本地是否存在指定的鏡像,不存在就從公有倉(cāng)庫(kù)下載
  • 利用鏡像創(chuàng)建并啟動(dòng)一個(gè)容器
  • 分配一個(gè)文件系統(tǒng),并在只讀的鏡像層外面掛載一層可讀寫(xiě)層
  • 從宿主主機(jī)配置的網(wǎng)橋接口中橋接一個(gè)虛擬接口到容器中去
  • 從地址池配置一個(gè) ip 地址給容器
  • 執(zhí)行用戶指定的應(yīng)用程序
  • 執(zhí)行完畢后容器被終止

啟動(dòng)已終止容器
首先利用docker ps查看已終止容器,再利用docker container start <id>命令啟動(dòng)

5.2 守護(hù)態(tài)運(yùn)行

看下下面例子:

//直接運(yùn)行
$ docker run ubuntu:17.10 /bin/sh -c "while true; do echo hello world; sleep 1; done"
hello world
hello world
hello world
hello world
//使用-d使容器在后臺(tái)運(yùn)行,獲取id,具體輸出在log中查看
$ docker run -d ubuntu:17.10 /bin/sh -c "while true; do echo hello world; sleep 1; done"
77b2dc01fe0f3f1265df143181e7b9af5e05279a884f4776ee75350ea9d8017a
//使用啟動(dòng)時(shí)返回的id,也可以通過(guò)docker container ls命令來(lái)查看容器信息。
$ docker container logs [container ID or NAMES]
hello world
hello world
hello world

5.3 終止容器

  • 使用docker container stop終止容器;容器中的應(yīng)用結(jié)束,容器也將終止
  • 終止?fàn)顟B(tài)的容器可以用docker container ls -a命令看到。
  • 處于終止?fàn)顟B(tài)的容器,可以通過(guò)docker container start命令來(lái)重新啟動(dòng)。
  • docker container restart可以重啟容器

5.4 進(jìn)入容器

??使用-d后,容器進(jìn)入后臺(tái)運(yùn)行,有時(shí)候需要進(jìn)入容器進(jìn)行操作,可以使用docker attachdocker exec,推薦使用docker exec。

  • attach命令
$ docker run -dit ubuntu
243c32535da7d142fb0e6df616a3c3ada0b8ab417937c853a9e1c251f499f550

$ docker container ls
CONTAINER ID ……
243c32535da7 ……

$ docker attach 243c
root@243c32535da7:/#

//注:如果從這個(gè) stdin 中 exit,會(huì)導(dǎo)致容器的停止。
  • exec命令
    ??該命令可以使用-i-t參數(shù);相對(duì)attach命令,如果從這個(gè) stdin 中 exit,不會(huì)導(dǎo)致容器的停止??聪旅胬樱?/li>
$ docker run -dit ubuntu
69d137adef7a8a689cbcb059e94da5489d3cddd240ff675c640c8d96e84fe1f6

$ docker container ls
CONTAINER ID ……
69d137adef7a ……

$ docker exec -i 69d1 bash
ls
bin
boot
dev
...

$ docker exec -it 69d1 bash
root@69d137adef7a:/#

5.5 導(dǎo)出和導(dǎo)入容器

  • 導(dǎo)出容器
$ docker container ls -a
CONTAINER ID ……
7691a814370e ……

$ docker export 7691a814370e > ubuntu.tar
  • 導(dǎo)入容器
    將容器導(dǎo)入為鏡像
$ cat ubuntu.tar | docker import - test/ubuntu:v1.0
$ docker image ls
REPOSITORY    TAG   IMAGE ID        CREATED     VIRTUAL SIZE
test/ubuntu   v1.0  9d37a6082e97    20s ago     171.3 MB

//也可以通過(guò)指定 URL 或者某個(gè)目錄來(lái)導(dǎo)入
$ docker import http://ex.com/eximage.tgz ex/imagerepo

5.6 刪除容器

  • 使用docker container rm來(lái)刪除一個(gè)處于終止?fàn)顟B(tài)的容器。如果要?jiǎng)h除一個(gè)運(yùn)行中的容器,可以添加 -f 參數(shù)。
  • docker container prune命令可以清理掉所有處于終止?fàn)顟B(tài)的容器。

6. 訪問(wèn)倉(cāng)庫(kù)

7. 數(shù)據(jù)管理

7.1 數(shù)據(jù)卷

數(shù)據(jù)卷時(shí)用來(lái)存放容器共享數(shù)據(jù)的目錄。

10. Docker三劍客之Compose項(xiàng)目

10.1 安裝

$ sudo curl -L https://github.com/docker/compose/releases/download/1.17.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose

10.2 命令補(bǔ)全

$ sudo sh -c 'curl -L https://raw.githubusercontent.com/docker/compose/1.8.0/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose'

10.3 使用

  • 服務(wù) (service):一個(gè)應(yīng)用容器,實(shí)際上可以運(yùn)行多個(gè)相同鏡像的實(shí)例。
  • 項(xiàng)目 (project):由一組關(guān)聯(lián)的應(yīng)用容器組成的一個(gè)完整業(yè)務(wù)單元。

命令說(shuō)明

-f, --file FILE 指定使用的 Compose 模板文件,默認(rèn)為 docker-compose.yml,可以多次指定。

-p, --project-name NAME 指定項(xiàng)目名稱(chēng),默認(rèn)將使用所在目錄名稱(chēng)作為項(xiàng)目名。

--x-networking 使用 Docker 的可拔插網(wǎng)絡(luò)后端特性

--x-network-driver DRIVER 指定網(wǎng)絡(luò)后端的驅(qū)動(dòng),默認(rèn)為 bridge

--verbose 輸出更多調(diào)試信息。

-v, --version 打印版本并退出。

命令使用說(shuō)明

build

格式為 docker-compose build [options] [SERVICE...]。

構(gòu)建(重新構(gòu)建)項(xiàng)目中的服務(wù)容器。

服務(wù)容器一旦構(gòu)建后,將會(huì)帶上一個(gè)標(biāo)記名,例如對(duì)于 web 項(xiàng)目中的一個(gè) db 容器,可能是 web_db。

可以隨時(shí)在項(xiàng)目目錄下運(yùn)行 docker-compose build 來(lái)重新構(gòu)建服務(wù)。

選項(xiàng)包括:

--force-rm 刪除構(gòu)建過(guò)程中的臨時(shí)容器。

--no-cache 構(gòu)建鏡像過(guò)程中不使用 cache(這將加長(zhǎng)構(gòu)建過(guò)程)。

--pull 始終嘗試通過(guò) pull 來(lái)獲取更新版本的鏡像。

config

驗(yàn)證 Compose 文件格式是否正確,若正確則顯示配置,若格式錯(cuò)誤顯示錯(cuò)誤原因。

down

此命令將會(huì)停止 up 命令所啟動(dòng)的容器,并移除網(wǎng)絡(luò)

exec

進(jìn)入指定的容器

help

獲得一個(gè)命令的幫助

images

列出 Compose 文件中包含的鏡像

kill

格式為 docker-compose kill [options] [SERVICE...]。

通過(guò)發(fā)送 SIGKILL 信號(hào)來(lái)強(qiáng)制停止服務(wù)容器。

支持通過(guò) -s 參數(shù)來(lái)指定發(fā)送的信號(hào),例如通過(guò)如下指令發(fā)送 SIGINT 信號(hào)。

$ docker-compose kill -s SIGINT

logs

格式為 docker-compose logs [options] [SERVICE...]。

查看服務(wù)容器的輸出。默認(rèn)情況下,docker-compose 將對(duì)不同的服務(wù)輸出使用不同的顏色來(lái)區(qū)分??梢酝ㄟ^(guò) --no-color 來(lái)關(guān)閉顏色。

該命令在調(diào)試問(wèn)題的時(shí)候十分有用。

pause

格式為 docker-compose pause [SERVICE...]。

暫停一個(gè)服務(wù)容器。

port

格式為 docker-compose port [options] SERVICE PRIVATE_PORT。

打印某個(gè)容器端口所映射的公共端口。

選項(xiàng):

--protocol=proto 指定端口協(xié)議,tcp(默認(rèn)值)或者 udp。

--index=index 如果同一服務(wù)存在多個(gè)容器,指定命令對(duì)象容器的序號(hào)(默認(rèn)為 1)。

ps

格式為 docker-compose ps [options] [SERVICE...]。

列出項(xiàng)目中目前的所有容器。

選項(xiàng):

-q 只打印容器的 ID 信息。

pull

格式為 docker-compose pull [options] [SERVICE...]。

拉取服務(wù)依賴(lài)的鏡像。

選項(xiàng):

--ignore-pull-failures 忽略拉取鏡像過(guò)程中的錯(cuò)誤。

push

推送服務(wù)依賴(lài)的鏡像到 Docker 鏡像倉(cāng)庫(kù)。

restart

格式為 docker-compose restart [options] [SERVICE...]。

重啟項(xiàng)目中的服務(wù)。

選項(xiàng):

-t, --timeout TIMEOUT 指定重啟前停止容器的超時(shí)(默認(rèn)為 10 秒)。

rm

格式為 docker-compose rm [options] [SERVICE...]。

刪除所有(停止?fàn)顟B(tài)的)服務(wù)容器。推薦先執(zhí)行 docker-compose stop 命令來(lái)停止容器。

選項(xiàng):

-f, --force 強(qiáng)制直接刪除,包括非停止?fàn)顟B(tài)的容器。一般盡量不要使用該選項(xiàng)。

-v 刪除容器所掛載的數(shù)據(jù)卷。

run

格式為 docker-compose run [options] [-p PORT...] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...]。

在指定服務(wù)上執(zhí)行一個(gè)命令。

例如:

$ docker-compose run ubuntu ping docker.com
將會(huì)啟動(dòng)一個(gè) ubuntu 服務(wù)容器,并執(zhí)行 ping docker.com 命令。

默認(rèn)情況下,如果存在關(guān)聯(lián),則所有關(guān)聯(lián)的服務(wù)將會(huì)自動(dòng)被啟動(dòng),除非這些服務(wù)已經(jīng)在運(yùn)行中。

該命令類(lèi)似啟動(dòng)容器后運(yùn)行指定的命令,相關(guān)卷、鏈接等等都將會(huì)按照配置自動(dòng)創(chuàng)建。

兩個(gè)不同點(diǎn):

給定命令將會(huì)覆蓋原有的自動(dòng)運(yùn)行命令;

不會(huì)自動(dòng)創(chuàng)建端口,以避免沖突。

如果不希望自動(dòng)啟動(dòng)關(guān)聯(lián)的容器,可以使用 --no-deps 選項(xiàng),例如

$ docker-compose run --no-deps web python manage.py shell
將不會(huì)啟動(dòng) web 容器所關(guān)聯(lián)的其它容器。

選項(xiàng):

-d 后臺(tái)運(yùn)行容器。

--name NAME 為容器指定一個(gè)名字。

--entrypoint CMD 覆蓋默認(rèn)的容器啟動(dòng)指令。

-e KEY=VAL 設(shè)置環(huán)境變量值,可多次使用選項(xiàng)來(lái)設(shè)置多個(gè)環(huán)境變量。

-u, --user="" 指定運(yùn)行容器的用戶名或者 uid。

--no-deps 不自動(dòng)啟動(dòng)關(guān)聯(lián)的服務(wù)容器。

--rm 運(yùn)行命令后自動(dòng)刪除容器,d 模式下將忽略。

-p, --publish=[] 映射容器端口到本地主機(jī)。

--service-ports 配置服務(wù)端口并映射到本地主機(jī)。

-T 不分配偽 tty,意味著依賴(lài) tty 的指令將無(wú)法運(yùn)行。

scale

格式為 docker-compose scale [options] [SERVICE=NUM...]。

設(shè)置指定服務(wù)運(yùn)行的容器個(gè)數(shù)。

通過(guò) service=num 的參數(shù)來(lái)設(shè)置數(shù)量。例如:

$ docker-compose scale web=3 db=2
將啟動(dòng) 3 個(gè)容器運(yùn)行 web 服務(wù),2 個(gè)容器運(yùn)行 db 服務(wù)。

一般的,當(dāng)指定數(shù)目多于該服務(wù)當(dāng)前實(shí)際運(yùn)行容器,將新創(chuàng)建并啟動(dòng)容器;反之,將停止容器。

選項(xiàng):

-t, --timeout TIMEOUT 停止容器時(shí)候的超時(shí)(默認(rèn)為 10 秒)。

start

格式為 docker-compose start [SERVICE...]。

啟動(dòng)已經(jīng)存在的服務(wù)容器。

stop

格式為 docker-compose stop [options] [SERVICE...]。

停止已經(jīng)處于運(yùn)行狀態(tài)的容器,但不刪除它。通過(guò) docker-compose start 可以再次啟動(dòng)這些容器。

選項(xiàng):

-t, --timeout TIMEOUT 停止容器時(shí)候的超時(shí)(默認(rèn)為 10 秒)。

top

查看各個(gè)服務(wù)容器內(nèi)運(yùn)行的進(jìn)程。

unpause

格式為 docker-compose unpause [SERVICE...]。

恢復(fù)處于暫停狀態(tài)中的服務(wù)。

up
格式為 docker-compose up [options] [SERVICE...]。

該命令十分強(qiáng)大,它將嘗試自動(dòng)完成包括構(gòu)建鏡像,(重新)創(chuàng)建服務(wù),啟動(dòng)服務(wù),并關(guān)聯(lián)服務(wù)相關(guān)容器的一系列操作。

鏈接的服務(wù)都將會(huì)被自動(dòng)啟動(dòng),除非已經(jīng)處于運(yùn)行狀態(tài)。

可以說(shuō),大部分時(shí)候都可以直接通過(guò)該命令來(lái)啟動(dòng)一個(gè)項(xiàng)目。

默認(rèn)情況,docker-compose up 啟動(dòng)的容器都在前臺(tái),控制臺(tái)將會(huì)同時(shí)打印所有容器的輸出信息,可以很方便進(jìn)行調(diào)試。

當(dāng)通過(guò) Ctrl-C 停止命令時(shí),所有容器將會(huì)停止。

如果使用 docker-compose up -d,將會(huì)在后臺(tái)啟動(dòng)并運(yùn)行所有的容器。一般推薦生產(chǎn)環(huán)境下使用該選項(xiàng)。

默認(rèn)情況,如果服務(wù)容器已經(jīng)存在,docker-compose up 將會(huì)嘗試停止容器,然后重新創(chuàng)建(保持使用 volumes-from 掛載的卷),以保證新啟動(dòng)的服務(wù)匹配 docker-compose.yml 文件的最新內(nèi)容。如果用戶不希望容器被停止并重新創(chuàng)建,可以使用 docker-compose up --no-recreate。這樣將只會(huì)啟動(dòng)處于停止?fàn)顟B(tài)的容器,而忽略已經(jīng)運(yùn)行的服務(wù)。如果用戶只想重新部署某個(gè)服務(wù),可以使用 docker-compose up --no-deps -d <SERVICE_NAME> 來(lái)重新創(chuàng)建服務(wù)并后臺(tái)停止舊服務(wù),啟動(dòng)新服務(wù),并不會(huì)影響到其所依賴(lài)的服務(wù)。

選項(xiàng):

-d 在后臺(tái)運(yùn)行服務(wù)容器。

--no-color 不使用顏色來(lái)區(qū)分不同的服務(wù)的控制臺(tái)輸出。

--no-deps 不啟動(dòng)服務(wù)所鏈接的容器。

--force-recreate 強(qiáng)制重新創(chuàng)建容器,不能與 --no-recreate 同時(shí)使用。

--no-recreate 如果容器已經(jīng)存在了,則不重新創(chuàng)建,不能與 --force-recreate 同時(shí)使用。

--no-build 不自動(dòng)構(gòu)建缺失的服務(wù)鏡像。

-t, --timeout TIMEOUT 停止容器時(shí)候的超時(shí)(默認(rèn)為 10 秒)。

version

格式為 docker-compose version。

打印版本信息。

10.4 compose模板文件

默認(rèn)的模板文件名稱(chēng)為 docker-compose.yml

version: '3' //表示模板文件版本,不同版本支持的docker引擎不同

services:
  app1:
    image: examples/web //表示基礎(chǔ)鏡像
  app2:
    build: ./dir //指定Dockerfile所在目錄,通過(guò)Dockerfile構(gòu)建鏡像
  app3:
    build:
      context: ./dir //指定Dockerfile所在目錄
      dockerfile: Dockerfile-alternate //指定Dockerfile文件名
      args:
        buildno: 1 //指定參數(shù)
  app4:
      build:
          context: .
          cache_from: //指定緩存
            - alpine:latest
            - corp/web_app:3.14

cap_add, cap_drop
指定容器的內(nèi)核能力(capacity)分配。

例如,讓容器擁有所有能力可以指定為:

cap_add:
  - ALL

去掉 NET_ADMIN 能力可以指定為:

cap_drop:
  - NET_ADMIN

command
覆蓋容器啟動(dòng)后默認(rèn)執(zhí)行的命令。
command: echo "hello world"

configs
僅用于 Swarm mode,詳細(xì)內(nèi)容請(qǐng)查看 Swarm mode 一節(jié)。

cgroup_parent
指定父 cgroup 組,意味著將繼承該組的資源限制。

例如,創(chuàng)建了一個(gè) cgroup 組名稱(chēng)為 cgroups_1。

cgroup_parent: cgroups_1
container_name

指定容器名稱(chēng)。默認(rèn)將會(huì)使用 項(xiàng)目名稱(chēng)服務(wù)名稱(chēng)序號(hào) 這樣的格式。

container_name: docker-web-container

注意: 指定容器名稱(chēng)后,該服務(wù)將無(wú)法進(jìn)行擴(kuò)展(scale),因?yàn)?Docker 不允許多個(gè)容器具有相同的名稱(chēng)。

deploy
僅用于 Swarm mode,詳細(xì)內(nèi)容請(qǐng)查看 Swarm mode 一節(jié)

devices
指定設(shè)備映射關(guān)系。

devices:
  - "/dev/ttyUSB1:/dev/ttyUSB0"
depends_on

解決容器的依賴(lài)、啟動(dòng)先后的問(wèn)題。以下例子中會(huì)先啟動(dòng) redis db 再啟動(dòng) web

version: '3'

services:
  web:
    build: .
    depends_on:
      - db
      - redis

  redis:
    image: redis

  db:
    image: postgres
注意:web 服務(wù)不會(huì)等待 redis db 「完全啟動(dòng)」之后才啟動(dòng)。

dns
自定義 DNS 服務(wù)器??梢允且粋€(gè)值,也可以是一個(gè)列表。

dns: 8.8.8.8

dns:
  - 8.8.8.8
  - 114.114.114.114

dns_search
配置 DNS 搜索域??梢允且粋€(gè)值,也可以是一個(gè)列表。

dns_search: example.com

dns_search:
  - domain1.example.com
  - domain2.example.com

tmpfs
掛載一個(gè) tmpfs 文件系統(tǒng)到容器。

tmpfs: /run
tmpfs:
  - /run
  - /tmp

env_file
從文件中獲取環(huán)境變量,可以為單獨(dú)的文件路徑或列表。

如果通過(guò) docker-compose -f FILE 方式來(lái)指定 Compose 模板文件,則 env_file 中變量的路徑會(huì)基于模板文件路徑。

如果有變量名稱(chēng)與 environment 指令沖突,則按照慣例,以后者為準(zhǔn)。

env_file: .env

env_file:
  - ./common.env
  - ./apps/web.env
  - /opt/secrets.env

環(huán)境變量文件中每一行必須符合格式,支持 # 開(kāi)頭的注釋行。

# common.env: Set development environment
PROG_ENV=development

environment
設(shè)置環(huán)境變量。你可以使用數(shù)組或字典兩種格式。

只給定名稱(chēng)的變量會(huì)自動(dòng)獲取運(yùn)行 Compose 主機(jī)上對(duì)應(yīng)變量的值,可以用來(lái)防止泄露不必要的數(shù)據(jù)。

environment:
  RACK_ENV: development
  SESSION_SECRET:

environment:
  - RACK_ENV=development
  - SESSION_SECRET

如果變量名稱(chēng)或者值中用到 true|false,yes|no 等表達(dá) 布爾 含義的詞匯,最好放到引號(hào)里,避免 YAML 自動(dòng)解析某些內(nèi)容為對(duì)應(yīng)的布爾語(yǔ)義。這些特定詞匯,包括

y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF

expose
暴露端口,但不映射到宿主機(jī),只被連接的服務(wù)訪問(wèn)。

僅可以指定內(nèi)部端口為參數(shù)

expose:
 - "3000"
 - "8000"
external_links

注意:不建議使用該指令。

鏈接到 docker-compose.yml 外部的容器,甚至并非 Compose 管理的外部容器。

external_links:
 - redis_1
 - project_db_1:mysql
 - project_db_1:postgresql
extra_hosts

類(lèi)似 Docker 中的 --add-host 參數(shù),指定額外的 host 名稱(chēng)映射信息。

extra_hosts:
 - "googledns:8.8.8.8"
 - "dockerhub:52.1.157.61"

會(huì)在啟動(dòng)后的服務(wù)容器中 /etc/hosts 文件中添加如下兩條條目。

8.8.8.8 googledns
52.1.157.61 dockerhub

healthcheck
通過(guò)命令檢查容器是否健康運(yùn)行。

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost"]
  interval: 1m30s
  timeout: 10s
  retries: 3

image
指定為鏡像名稱(chēng)或鏡像 ID。如果鏡像在本地不存在,Compose 將會(huì)嘗試?yán)ミ@個(gè)鏡像。

image: ubuntu
image: orchardup/postgresql
image: a4bc65fd
labels

為容器添加 Docker 元數(shù)據(jù)(metadata)信息。例如可以為容器添加輔助說(shuō)明信息。

labels:
  com.startupteam.description: "webapp for a startup team"
  com.startupteam.department: "devops department"
  com.startupteam.release: "rc3 for v1.0"

links
注意:不推薦使用該指令。

logging
配置日志選項(xiàng)。

logging:
  driver: syslog
  options:
    syslog-address: "tcp://192.168.0.42:123"

目前支持三種日志驅(qū)動(dòng)類(lèi)型。

driver: "json-file"
driver: "syslog"
driver: "none"

options 配置日志驅(qū)動(dòng)的相關(guān)參數(shù)。

options:
  max-size: "200k"
  max-file: "10"

network_mode
設(shè)置網(wǎng)絡(luò)模式。使用和 docker run 的 --network 參數(shù)一樣的值。

network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"
networks

配置容器連接的網(wǎng)絡(luò)。

version: "3"
services:

  some-service:
    networks:
     - some-network
     - other-network

networks:
  some-network:
  other-network:

pid
跟主機(jī)系統(tǒng)共享進(jìn)程命名空間。打開(kāi)該選項(xiàng)的容器之間,以及容器和宿主機(jī)系統(tǒng)之間可以通過(guò)進(jìn)程 ID 來(lái)相互訪問(wèn)和操作。

pid: "host"

ports
暴露端口信息。

使用宿主端口:容器端口 (HOST:CONTAINER) 格式,或者僅僅指定容器的端口(宿主將會(huì)隨機(jī)選擇端口)都可以。

ports:
 - "3000"
 - "8000:8000"
 - "49100:22"
 - "127.0.0.1:8001:8001"

注意:當(dāng)使用 HOST:CONTAINER 格式來(lái)映射端口時(shí),如果你使用的容器端口小于 60 并且沒(méi)放到引號(hào)里,可能會(huì)得到錯(cuò)誤結(jié)果,因?yàn)?YAML 會(huì)自動(dòng)解析 xx:yy 這種數(shù)字格式為 60 進(jìn)制。為避免出現(xiàn)這種問(wèn)題,建議數(shù)字串都采用引號(hào)包括起來(lái)的字符串格式。

secrets
存儲(chǔ)敏感數(shù)據(jù),例如 mysql 服務(wù)密碼。

version: "3"
services:

mysql:
  image: mysql
  environment:
    MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
  secrets:
    - db_root_password
    - my_other_secret

secrets:
  my_secret:
    file: ./my_secret.txt
  my_other_secret:
    external: true

security_opt
指定容器模板標(biāo)簽(label)機(jī)制的默認(rèn)屬性(用戶、角色、類(lèi)型、級(jí)別等)。例如配置標(biāo)簽的用戶名和角色名。

security_opt:
    - label:user:USER
    - label:role:ROLE

stop_signal
設(shè)置另一個(gè)信號(hào)來(lái)停止容器。在默認(rèn)情況下使用的是 SIGTERM 停止容器。

stop_signal: SIGUSR1

sysctls
配置容器內(nèi)核參數(shù)。

sysctls:
  net.core.somaxconn: 1024
  net.ipv4.tcp_syncookies: 0

sysctls:
  - net.core.somaxconn=1024
  - net.ipv4.tcp_syncookies=0

ulimits
指定容器的 ulimits 限制值。

例如,指定最大進(jìn)程數(shù)為 65535,指定文件句柄數(shù)為 20000(軟限制,應(yīng)用可以隨時(shí)修改,不能超過(guò)硬限制) 和 40000(系統(tǒng)硬限制,只能 root 用戶提高)。

  ulimits:
    nproc: 65535
    nofile:
      soft: 20000
      hard: 40000

volumes
數(shù)據(jù)卷所掛載路徑設(shè)置。可以設(shè)置宿主機(jī)路徑 (HOST:CONTAINER) 或加上訪問(wèn)模式 (HOST:CONTAINER:ro)。

該指令中路徑支持相對(duì)路徑。

volumes:
 - /var/lib/mysql
 - cache/:/tmp/cache
 - ~/configs:/etc/configs/:ro

其它指令
此外,還有包括 domainname, entrypoint, hostname, ipc, mac_address, privileged, read_only, shm_size, restart, stdin_open, tty, user, working_dir 等指令,基本跟 docker run 中對(duì)應(yīng)參數(shù)的功能一致。

指定服務(wù)容器啟動(dòng)后執(zhí)行的入口文件。

entrypoint: /code/entrypoint.sh
指定容器中運(yùn)行應(yīng)用的用戶名。

user: nginx
指定容器中工作目錄。

working_dir: /code
指定容器中搜索域名、主機(jī)名、mac 地址等。

domainname: your_website.com
hostname: test
mac_address: 08-00-27-00-0C-0A

允許容器中運(yùn)行一些特權(quán)命令。

privileged: true
指定容器退出后的重啟策略為始終重啟。該命令對(duì)保持服務(wù)始終運(yùn)行十分有效,在生產(chǎn)環(huán)境中推薦配置為 always 或者 unless-stopped。

restart: always
以只讀模式掛載容器的 root 文件系統(tǒng),意味著不能對(duì)容器內(nèi)容進(jìn)行修改。

read_only: true
打開(kāi)標(biāo)準(zhǔn)輸入,可以接受外部輸入。

stdin_open: true
模擬一個(gè)偽終端。

tty: true
讀取變量
Compose 模板文件支持動(dòng)態(tài)讀取主機(jī)的系統(tǒng)環(huán)境變量和當(dāng)前目錄下的 .env 文件中的變量。

例如,下面的 Compose 文件將從運(yùn)行它的環(huán)境中讀取變量 ${MONGO_VERSION} 的值,并寫(xiě)入執(zhí)行的指令中。

version: "3"
services:

db:
  image: "mongo:${MONGO_VERSION}"

如果執(zhí)行 MONGO_VERSION=3.2 docker-compose up 則會(huì)啟動(dòng)一個(gè) mongo:3.2 鏡像的容器;如果執(zhí)行 MONGO_VERSION=2.8 docker-compose up 則會(huì)啟動(dòng)一個(gè) mongo:2.8 鏡像的容器。

若當(dāng)前目錄存在 .env 文件,執(zhí)行 docker-compose 命令時(shí)將從該文件中讀取變量。

在當(dāng)前目錄新建 .env 文件并寫(xiě)入以下內(nèi)容。

# 支持 # 號(hào)注釋
MONGO_VERSION=3.6
執(zhí)行 docker-compose up 則會(huì)啟動(dòng)一個(gè) mongo:3.6 鏡像的容器。

?著作權(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),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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