Docker

2020-08-10 17:59:01

什麼是 Docker

Docker 是一個開源專案,誕生於 2013 年初,最初是 dotCloud 公司內部的一個業餘專案。它基於 Google 公司推出的 Go 語言實現。 專案後來加入了 Linux 基金會,遵從了 Apache 2.0 協定,專案程式碼在 GitHub 上進行維護。Docker 自開源後受到廣泛的關注和討論,以至於 dotCloud 公司後來都改名爲 Docker Inc。

Docker 可以讓開發者打包他們的應用以及依賴包到一個輕量級、可移植的容器中,然後發佈到任何流行的 Linux 機器上,也可以實現虛擬化。

容器是完全使用沙箱機制 機製,相互之間不會有任何介面(類似 iPhone 的 app),更重要的是容器效能開銷極低。

Docker 從 17.03 版本之後分爲 CE(Community Edition: 社羣版) 和 EE(Enterprise Edition: 企業版),我們用社羣版就可以了。

Docker安裝指南

官方網站上有各種環境下的 安裝指南

Docker的基本概念

Docker 包括三個基本概念

  • 映象(Image)
  • 容器(Container)
  • 倉庫(Repository)

Docker映象

Docker 映象就是一個只讀的模板。

例如:一個映象可以包含一個完整的 ubuntu 操作系統環境,裏面僅安裝了 Apache 或使用者需要的其它應用程式。

映象可以用來建立 Docker 容器。

Docker 提供了一個很簡單的機制 機製來建立映象或者更新現有的映象,使用者甚至可以直接從其他人那裏下載一個已經做好的映象來直接使用。

Docker 執行容器前需要本地存在對應的映象,如果映象不存在本地,Docker 會從映象倉庫下載(預設是 Docker Hub 公共註冊伺服器中的倉庫)。

docker預設的映象倉庫地址是https://hub.docker.com/,但國內的下載速度太過緩慢,爲此,我們可以給Docker設定國內的加速地址。網上評論,DaoCloud阿裡雲的映象加速還不錯,另外還有網易的蜂巢,選一個就行了。

在powershell或cmd中通過 【docker-machine ssh default】命令登錄虛擬機器(或使用設定好的XShell連線),執行如下命令:

sudo sed -i "s|EXTRA_ARGS='|EXTRA_ARGS='--registry-mirror=加速地址 |g" /var/lib/boot2docker/profile

然後重新啓動default

docker-machine restart default
獲取映象

docker pull 命令來從倉庫獲取所需要的映象。

下面 下麪的例子將從 Docker Hub 倉庫下載一個 Ubuntu 12.04 操作系統的映象。

$ sudo docker pull ubuntu:12.04

該命令實際上相當於 $ sudo docker pull registry.hub.docker.com/ubuntu:12.04 命令,即從註冊伺服器 registry.hub.docker.com 中的 ubuntu 倉庫來下載標記爲 12.04 的映象。

有時候官方倉庫註冊伺服器下載較慢,可以從其他倉庫下載。 從其它倉庫下載時需要指定完整的倉庫註冊伺服器地址。例如:

$ sudo docker pull dl.dockerpool.com:5000/ubuntu:12.04
列出鏡像

docker images 顯示本地已有的映象。

建立映象

建立映象有很多方法,使用者可以從 Docker Hub 獲取已有映象並更新,也可以利用本地檔案系統建立一個。

  1. 修改已有映象
    docker commit 命令來提交更新後的副本。
  2. 利用 Dockerfile 來建立映象
    docker build 來建立一個新的映象。爲此,首先需要建立一個 Dockerfile,包含一些如何建立映象的指令。具體方法後面介紹。
    還可以用 docker tag 命令來修改映象的標籤。
  3. 從本地檔案系統匯入
    要從本地檔案系統匯入一個映象,可以使用 openvz(容器虛擬化的先鋒技術)的模板來建立: openvz 的模板下載地址爲 templates 。比如,先下載了一個 ubuntu-14.04 的映象,之後使用以下命令匯入:
sudo cat ubuntu-14.04-x86_64-minimal.tar.gz  |docker import - ubuntu:14.04
  1. 上傳映象
    使用者可以通過 docker push 命令,把自己建立的映象上傳到倉庫中來共用。例如,使用者在 Docker Hub 上完成註冊後,可以推播自己的映象到倉庫中。
$ sudo docker push ouruser/sinatra
存出和載入映象

存出鏡像

如果要導出映象到本地檔案,可以使用 docker save 命令。

$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu              14.04               c4ff7513909d        5 weeks ago         225.4 MB
...
$ sudo docker save -o ubuntu_14.04.tar ubuntu:14.04

載入映象

可以使用 docker load 從導出的本地檔案中再匯入到本地映象庫,例如

$ sudo docker load --input ubuntu_14.04.tar

$ sudo docker load < ubuntu_14.04.tar

這將匯入映象以及其相關的元數據資訊(包括標籤等)。

移除映象

如果要移除原生的映象,可以使用 docker rmi 命令。注意 docker rm 命令是移除容器。

$ sudo docker rmi training/sinatra
Untagged: training/sinatra:latest
Deleted: 5bc342fa0b91cabf65246837015197eecfa24b2213ed6a51a8974ae250fedd8d
Deleted: ed0fffdcdae5eb2c3a55549857a8be7fc8bc4241fb19ad714364cbfd7a56b22f
Deleted: 5c58979d73ae448df5af1d8142436d81116187a7633082650549c52c3a2418f0

注意:在刪除映象之前要先用 docker rm 刪掉依賴於這個映象的所有容器。

Docker容器

Docker 利用容器來執行應用。

容器是從映象建立的執行範例。它可以被啓動、開始、停止、刪除。每個容器都是相互隔離的、保證安全的平臺。

可以把容器看做是一個簡易版的 Linux 環境(包括root使用者許可權、進程空間、使用者空間和網路空間等)和執行在其中的應用程式。

注:映象是隻讀的,容器在啓動的時候建立一層可寫層作爲最上層。

進入Docker容器

在使用 -d 參數時,容器啓動後會進入後臺。 某些時候需要進入容器進行操作,有很多種方法,包括使用 docker attach 命令或 nsenter 工具等。

attach 命令
docker attach 是Docker自帶的命令。下面 下麪範例如何使用該命令。

$ sudo docker attach nostalgic_hypatia

但是使用 attach 命令有時候並不方便。當多個視窗同時 attach 到同一個容器的時候,所有視窗都會同步顯示。當某個視窗因命令阻塞時,其他視窗也無法執行操作了。

nsenter 命令
安裝
nsenter 工具在 util-linux 包2.23版本後包含。 如果系統中 util-linux 包沒有該命令,可以從原始碼安裝。

導出和匯入Docker容器

導出容器

如果要導出本地某個容器,可以使用 docker export 命令。

$ sudo docker export 7691a814370e > ubuntu.tar

這樣將導出容器快照到本地檔案。

匯入容器快照

可以使用 docker import 從容器快照檔案中再匯入爲映象,例如

$ cat ubuntu.tar | sudo docker import - test/ubuntu:v1.0

此外,也可以通過指定 URL 或者某個目錄來匯入,例如

$ sudo docker import http://example.com/exampleimage.tgz example/imagerepo

注:使用者既可以使用 docker load 來匯入映象儲存檔案到本地映象庫,也可以使用 docker import 來匯入一個容器快照到本地映象庫。這兩者的區別在於容器快照檔案將丟棄所有的歷史記錄和元數據資訊(即僅儲存容器當時的快照狀態),而映象儲存檔案將儲存完整記錄,體積也要大。此外,從容器快照檔案匯入時可以重新指定標籤等元數據資訊。

刪除容器

可以使用 docker rm 來刪除一個處於終止狀態的容器。 例如

$ sudo docker rm  trusting_newton
trusting_newton

如果要刪除一個執行中的容器,可以新增 -f 參數。Docker 會發送 SIGKILL 信號給容器。

啓動Docker容器

啓動容器有兩種方式,一種是基於映象新建一個容器並啓動,另外一個是將在終止狀態(stopped)的容器重新啓動。

因爲 Docker 的容器實在太輕量級了,很多時候使用者都是隨時刪除和新建立容器。

新建並啓動

所需要的命令主要爲 docker run

例如,下面 下麪的命令輸出一個 「Hello World」,之後終止容器。

$ sudo docker run ubuntu:14.04 /bin/echo 'Hello world'
Hello world

啓動已終止容器

可以利用 docker start 命令,直接將一個已經終止的容器啓動執行。

守護態執行Docker容器

更多的時候,需要讓 Docker 容器在後台以守護態(Daemonized)形式執行。此時,可以通過新增 -d 參數來實現。

例如下面 下麪的命令會在後台執行容器。

$ sudo docker run -d ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
1e5535038e285177d5214659a068137486f96ee5c2e85a4ac52dc83f2ebe4147

容器啓動後會返回一個唯一的 id,也可以通過 docker ps 命令來檢視容器資訊。

$ sudo docker ps

要獲取容器的輸出資訊,可以通過 docker logs 命令。

$ sudo docker logs insane_babbage
終止Docker容器

可以使用 docker stop 來終止一個執行中的容器。

此外,當Docker容器中指定的應用終結時,容器也自動終止。 例如對於上一章節中只啓動了一個終端的容器,使用者通過 exit 命令或 Ctrl+d 來退出終端時,所建立的容器立刻終止。

終止狀態的容器可以用 docker ps -a 命令看到。例如

sudo docker ps -a

處於終止狀態的容器,可以通過 docker start 命令來重新啓動。

此外,docker restart 命令會將一個執行態的容器終止,然後再重新啓動它。

Docker倉庫

倉庫是集中存放映象檔案的場所。有時候會把倉庫和倉庫註冊伺服器(Registry)混爲一談,並不嚴格區分。實際上,倉庫註冊伺服器上往往存放着多個倉庫,每個倉庫中又包含了多個映象,每個映象有不同的標籤(tag)。

倉庫分爲公開倉庫(Public)和私有倉庫(Private)兩種形式。

最大的公開倉庫是 Docker Hub,存放了數量龐大的映象供使用者下載。 國內的公開倉庫包括 Docker Pool 等,可以提供大陸使用者更穩定快速的存取。

當然,使用者也可以在本地網路內建立一個私有倉庫。

當使用者建立了自己的映象之後就可以使用 push 命令將它上傳到公有或者私有倉庫,這樣下次在另外一臺機器上使用這個映象時候,只需要從倉庫上 pull 下來就可以了。

注:Docker 倉庫的概念跟 Git 類似,註冊伺服器可以理解爲 GitHub 這樣的託管服務。

Docker Hub
Docker的私有倉庫
Docker組態檔

Dockerfile

什麼是 Dockerfile

Dockerfile 是一個用來構建映象的文字檔案,文字內容包含了一條條構建映象所需的指令和說明。

使用 Dockerfile 定製映象

這裏僅講解如何執行 Dockerfile 檔案來定製一個映象,具體 Dockerfile 檔案內指令詳解,將在下一節中介紹,這裏你只要知道構建的流程即可。

1、下面 下麪以定製一個 nginx 映象(構建好的映象內會有一個 /usr/share/nginx/html/index.html 檔案)

在一個空目錄下,新建一個名爲 Dockerfile 檔案,並在檔案內新增以下內容:

FROM nginx
RUN echo '這是一個本地構建的nginx映象' > /usr/share/nginx/html/index.html

2、FROM 和 RUN 指令的作用

FROM:定製的映象都是基於 FROM 的映象,這裏的 nginx 就是定製需要的基礎映象。後續的操作都是基於 nginx。

RUN:用於執行後面跟着的命令列命令。有以下倆種格式:

shell 格式:

RUN <命令列命令>
# <命令列命令> 等同於,在終端操作的 shell 命令。

exec 格式:

RUN ["可執行檔案", "參數1", "參數2"]
# 例如:
# RUN ["./test.php", "dev", "offline"] 等價於 RUN ./test.php dev offline

注意:Dockerfile 的指令每執行一次都會在 docker 上新建一層。所以過多無意義的層,會造成映象膨脹過大。例如:

FROM centos
RUN yum install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz

以上執行會建立 3 層映象。可簡化爲以下格式:

FROM centos
RUN yum install wget \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && tar -xvf redis.tar.gz

如上,以 && 符號連線命令,這樣執行後,只會建立 1 層映象。

開始構建映象

在 Dockerfile 檔案的存放目錄下,執行構建動作。

以下範例,通過目錄下的 Dockerfile 構建一個 nginx:test(映象名稱:映象標籤)。

注:最後的 . 代表本次執行的上下文路徑,下一節會介紹。

$ docker build -t nginx:test .

上下文路徑

上一節中,有提到指令最後一個 . 是上下文路徑,那麼什麼是上下文路徑呢?

$ docker build -t nginx:test .

上下文路徑,是指 docker 在構建映象,有時候想要使用到本機的檔案(比如複製),docker build 命令得知這個路徑後,會將路徑下的所有內容打包。

解析:由於 docker 的執行模式是 C/S。我們本機是 C,docker 引擎是 S。實際的構建過程是在 docker 引擎下完成的,所以這個時候無法用到我們本機的檔案。這就需要把我們本機的指定目錄下的檔案一起打包提供給 docker 引擎使用。

如果未說明最後一個參數,那麼預設上下文路徑就是 Dockerfile 所在的位置。

注意:上下文路徑下不要放無用的檔案,因爲會一起打包發送給 docker 引擎,如果檔案過多會造成過程緩慢。

指令詳解

COPY

複製指令,從上下文目錄中複製檔案或者目錄到容器裡指定路徑。

格式:

COPY [--chown=<user>:<group>] <源路徑1>...  <目標路徑>
COPY [--chown=<user>:<group>] ["<源路徑1>",...  "<目標路徑>"]

[–chown=:]:可選參數,使用者改變複製到容器內檔案的擁有者和屬組。

<源路徑>:原始檔或者源目錄,這裏可以是萬用字元表達式,其萬用字元規則要滿足 Go 的 filepath.Match 規則。例如:

COPY hom* /mydir/
COPY hom?.txt /mydir/

<目標路徑>:容器內的指定路徑,該路徑不用事先建好,路徑不存在的話,會自動建立。

ADD

ADD 指令和 COPY 的使用格式一致(同樣需求下,官方推薦使用 COPY)。功能也類似,不同之處如下:

ADD 的優點:在執行 <原始檔> 爲 tar 壓縮檔案的話,壓縮格式爲 gzip, bzip2 以及 xz 的情況下,會自動複製並解壓到 <目標路徑>。
ADD 的缺點:在不解壓的前提下,無法複製 tar 壓縮檔案。會令映象構建快取失效,從而可能會令映象構建變得比較緩慢。具體是否使用,可以根據是否需要自動解壓來決定。

CMD

類似於 RUN 指令,用於執行程式,但二者執行的時間點不同:

CMD 在docker run 時執行。
RUN 是在 docker build。
作用:爲啓動的容器指定預設要執行的程式,程式執行結束,容器也就結束。CMD 指令指定的程式可被 docker run 命令列參數中指定要執行的程式所覆蓋。

注意:如果 Dockerfile 中如果存在多個 CMD 指令,僅最後一個生效。

格式:

CMD <shell 命令> 
CMD ["<可執行檔案或命令>","<param1>","<param2>",...] 
CMD ["<param1>","<param2>",...]  # 該寫法是爲 ENTRYPOINT 指令指定的程式提供預設參數

推薦使用第二種格式,執行過程比較明確。第一種格式實際上在執行的過程中也會自動轉換成第二種格式執行,並且預設可執行檔案是 sh。

ENTRYPOINT

類似於 CMD 指令,但其不會被 docker run 的命令列參數指定的指令所覆蓋,而且這些命令列參數會被當作參數送給 ENTRYPOINT 指令指定的程式。

但是, 如果執行 docker run 時使用了 --entrypoint 選項,此選項的參數可當作要執行的程式覆蓋 ENTRYPOINT 指令指定的程式。

優點:在執行 docker run 的時候可以指定 ENTRYPOINT 執行所需的參數。

注意:如果 Dockerfile 中如果存在多個 ENTRYPOINT 指令,僅最後一個生效。

格式:

ENTRYPOINT ["<executeable>","<param1>","<param2>",...]

可以搭配 CMD 命令使用:一般是變參纔會使用 CMD ,這裏的 CMD 等於是在給 ENTRYPOINT 傳參,以下範例會提到。

範例:

假設已通過 Dockerfile 構建了 nginx:test 映象:

FROM nginx

ENTRYPOINT ["nginx", "-c"] # 定參
CMD ["/etc/nginx/nginx.conf"] # 變參 

1、不傳參執行

$ docker run  nginx:test

容器內會預設執行以下命令,啓動主進程。

nginx -c /etc/nginx/nginx.conf

2、傳參執行

$ docker run  nginx:test -c /etc/nginx/new.conf

容器內會預設執行以下命令,啓動主進程(/etc/nginx/new.conf:假設容器內已有此檔案)

nginx -c /etc/nginx/new.conf
ENV

設定環境變數,定義了環境變數,那麼在後續的指令中,就可以使用這個環境變數。

格式:

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

以下範例設定 NODE_VERSION = 7.2.0 , 在後續的指令中可以通過 $NODE_VERSION 參照:

ENV NODE_VERSION 7.2.0

RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
  && curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"
ARG

構建參數,與 ENV 作用一至。不過作用域不一樣。ARG 設定的環境變數僅對 Dockerfile 內有效,也就是說只有 docker build 的過程中有效,構建好的映象內不存在此環境變數。

構建命令 docker build 中可以用 --build-arg <參數名>=<值> 來覆蓋。

格式:

ARG <參數名>[=<預設值>]
VOLUME

定義匿名數據卷。在啓動容器時忘記掛載數據卷,會自動掛載到匿名卷。

作用:

避免重要的數據,因容器重新啓動而丟失,這是非常致命的。
避免容器不斷變大。
格式:

VOLUME ["<路徑1>", "<路徑2>"...]
VOLUME <路徑>

在啓動容器 docker run 的時候,我們可以通過 -v 參數修改掛載點。

EXPOSE

僅僅只是宣告埠。

作用:

幫助映象使用者理解這個映象服務的守護埠,以方便設定對映。
在執行時使用隨機埠對映時,也就是 docker run -P 時,會自動隨機對映 EXPOSE 的埠。
格式:

EXPOSE <埠1> [<埠2>...]
WORKDIR

指定工作目錄。用 WORKDIR 指定的工作目錄,會在構建映象的每一層中都存在。(WORKDIR 指定的工作目錄,必須是提前建立好的)。

docker build 構建映象過程中的,每一個 RUN 命令都是新建的一層。只有通過 WORKDIR 建立的目錄纔會一直存在。

格式:

WORKDIR <工作目錄路徑>
USER

用於指定執行後續命令的使用者和使用者組,這邊只是切換後續命令執行的使用者(使用者和使用者組必須提前已經存在)。

格式:

USER <使用者名稱>[:<使用者組>]
HEALTHCHECK

用於指定某個程式或者指令來監控 docker 容器服務的執行狀態。

格式:

HEALTHCHECK [選項] CMD <命令>:設定檢查容器健康狀況的命令
HEALTHCHECK NONE:如果基礎映象有健康檢查指令,使用這行可以遮蔽掉其健康檢查指令

HEALTHCHECK [選項] CMD <命令> : 這邊 CMD 後面跟隨的命令使用,可以參考 CMD 的用法。
ONBUILD

用於延遲構建命令的執行。簡單的說,就是 Dockerfile 裡用 ONBUILD 指定的命令,在本次構建映象的過程中不會執行(假設映象爲 test-build)。當有新的 Dockerfile 使用了之前構建的映象 FROM test-build ,這是執行新映象的 Dockerfile 構建時候,會執行 test-build 的 Dockerfile 裡的 ONBUILD 指定的命令。

格式:

ONBUILD <其它指令>

Docker Compose

Docker Machine

Swarm 叢集管理

Docker 命令大全

容器生命週期管理

run
start/stop/restart
kill
rm
pause/unpause
create
exec

容器操作

ps
inspect
top
attach
events
logs
wait
export
port

容器rootfs命令

commit
cp
diff

映象倉庫

login
pull
push
search

本地映象管理

images
rmi
tag
build
history
save
load
import

info|version

info
version

Docker 資源彙總

Docker 資源

  • Docker 官方主頁: https://www.docker.com
  • Docker 官方部落格: https://blog.docker.com/
  • Docker 官方文件: https://docs.docker.com/
  • Docker Store: https://store.docker.com
  • Docker Cloud: https://cloud.docker.com
  • Docker Hub: https://hub.docker.com
  • Docker 的原始碼倉庫: https://github.com/moby/moby
  • Docker 發佈版本歷史: https://docs.docker.com/release-notes/
  • Docker 常見問題: https://docs.docker.com/engine/faq/
  • Docker 遠端應用 API: https://docs.docker.com/develop/sdk/

Docker 國內映象

  • 阿裡雲的加速器:https://help.aliyun.com/document_detail/60750.html
  • 網易加速器:http://hub-mirror.c.163.com
  • 官方中國加速器:https://registry.docker-cn.com
  • ustc 的映象:https://docker.mirrors.ustc.edu.cn
  • daocloud:https://www.daocloud.io/mirror#accelerator-doc(註冊後使用)

資料: https://www.w3cschool.cn/reqsgr/
資料: https://www.runoob.com/docker/docker-tutorial.html