介紹完 Dockerfile
後,來看看 Docker CLI 中和映像檔相關的操作。一般介紹 Docker 的書應該會將常用的指令整理在同一章節中,不過在 Docker 文件中我沒找到專門介紹常用指令的段落,因此找了 CLI 文件中關於 docker image
的部分來作說明,可參考 https://docs.docker.com/engine/reference/commandline/image/。
等同 docker build
,用來從 Dockerfile
建立一個映像檔,格式如下:
docker image build [OPTIONS] PATH | URL | -
注意最後一個參數,前面有說過是指 build context,不是 Dockerfile
,如果要指定 Dockerfile
路徑要使用 -f
旗標。
等於 docker load
,將一個 tar 壓縮檔載入成為映像檔,預設讀取 STDIN
,可用 --input
或 -i
來指定輸入檔案,例如:
docker image load [OPTIONS]
等於 docker save
,是前一個指令的反向,將映像檔存成一個 tar 壓縮檔,預設寫至 STDOUT
,可用 --output
或 -o
來指定輸出檔案,範例如下:
docker image save [OPTIONS] IMAGE [IMAGE...]
在無法透過 docker registry 上傳或下載映像檔時,可以利用 docker image load
/ save
。試驗了一下,用 docker load
所載入的映像檔不會有名稱(用 docker image ls
查看,REPOSITORY
和 TAG
欄位會是 <none>
),可以用 docker tag
加上資訊。
等於 docker push
,用來將映像檔推到 registry,格式如下:
docker image push [OPTIONS] NAME[:TAG]
等於 docker pull
,是前一個指令的反向,用來將映像檔由 registry 拉下,格式如下:
docker image pull [OPTIONS] NAME[:TAG|@DIGEST]
其他動作如 ls
、inspect
、rm
都蠻直覺的,就不多介紹,請查閱文件。
官方文件的指引中似乎沒有專門針對容器說明的部分,但也可以說因為指引是以應用程式開發的角度來編寫,而應用程式運行的生命週期幾乎離不開容器,所以整份指引也幾乎都是在說明和容器相關的概念及操作。
一般介紹 Docker 的書談到容器,應該都會先介紹 CLI 操作容器的指令,這裡也先從指令介紹起,關於 CLI 中 docker container 的說明可參考 [https://docs.docker.com/engine/reference/commandline/container_run/]
(https://docs.docker.com/engine/reference/commandline/container_run/),除了文件的說明,也參考了 Packt
出版的 Mastering Docker, 2/e
中關於容器一節,以決定要介紹那些指令。
用來在一個新的容器中執行命令,等於 docker run
。它應該是 docker container 中最重要的指令,文件中有一頁(應該算是)完整的介紹,請參考 https://docs.docker.com/engine/reference/run/。執行時有一些重要的選項,例如要以分離模式或前景模式運行、CPU 和記憶體資源限制等等。指令格式如下:
docker container run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]
這個在 Get Started
第一部分已經看過,分離模式有點類似以背景執行,以 -d
旗標指定。若是前景模式,則 docker 可以將容器中運行行程的 STDIN
、STDOUT
及 STDERR
附著 (attach) 在終端機上,主要有三個旗標可以使用,-a
可用來指示要 attach STDIN
、STDOUT
、STDERR
,-t
代表要分配一個虛擬的 tty (終端機),-i
表示要持續開啟 STDIN
。在互動模式的行程例如 shell,通常會一起使用 -i
和 -t
旗標,或寫成 -it
,用來分派 tty 給容器程序。看不懂沒有關係,反正記得如果希望容器運作時能提供一個 shell 以連進去進行操作,就在 docker run
時加上 -it
的指令就對了,例如:
$ docker container run -it --rm --name alpine-env alpine
這個容器使用 alpine
映像檔,執行 /bin/sh
並給予一個 tty 進行操作。--rm
表示在主程序 /bin/sh
結束後,例如輸入 exit
退出 shell,容器會被移除,--name
則為給予容器的名稱。
容器運行時的資源限制大概可以分成三類,記憶體、處理器以及 I/O。可以設定的選項有很多,比較常見的應該是 --memory
(-m
) 限制記憶體用量,以及 --cpu-shares
(-c
) 限制 CPU 用量,但不是很瞭解它是怎麼計算的,有看到兩種不同的參數給法,一種是給 512、1024,另一種是給 0、1、2。範例如下:
$ docker container run --cpu-shares 512 --memory 128M nginx
除了剛才介紹的 docker container run
搭配 -it
選項外,還有幾個指令可以用來跟容器互動。跟容器互動這個說法有點模糊,總之先看一下這兩個指令。
文件中說它的用途是 Attach local standard input, output, and error streams to a running container,但感覺起來好像是將運行中容器的行程附著到本機終端機。不知道是英文理解上的問題,還是我對 attach 的「方向」認知有誤。來試驗一下,我們先用 detached 模式來執行一個運行 nginx 服務的容器,指令是
$ docker container run -d -p 8888:80 --name nginx-test --rm nginx
接下來執行 docker container attach nginx-test
,並用瀏覽器訪問 http://localhost:8888,此時會在剛才 attach 的終端機看到訪問 nginx 的記錄檔 (access log)。
它會在容器中產生另一個行程來執行要求的指令。來試驗一下,一樣用 detached 模式執行剛才的 nginx 容器,然後執行下列指令:
$ docker container exec -it nginx-test /bin/sh
它會在 nginx-test
容器中執行 /bin/sh
,-it
旗標會給予一個可供互動的終端機。
用來印出容器的 STDOUT
,範例如下:
$ docker container logs --tail 5 nginx-test
$ docker container logs -f nginx-test
列出容器內執行的行程訊息,範例如下:
$ docker container top nginx-test
PID USER TIME COMMAND
14583 root 0:00 nginx: master process nginx -g daemon off;
14623 101 0:00 nginx: worker process
列出運行中容器的即時資訊,例如 ID、名稱、CPU、記憶體等等。若加上容器名稱,只顯示該容器資訊,否則會顯示所有容器的資訊。
$ docker container stats nginx-test
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
2d28fd25bce0 nginx-test 0.00% 1.914MiB / 1.952GiB 0.10% 858B / 0B 0B / 0B 2
刪除所有在停止狀態的容器,範例如下:
$ docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
dea1c7d02374a1ec427fcd16084166146e06201f8fe52284d81b56dbae9066a0
6502de71db8883d45b077fe494c0b1e47cddd5a9c9a78805af71dea438da2b3f
ea3d9f38020c1520af716146ba39293ab15cff393f89568c96615b496c24aded
Total reclaimed space: 0B
由容器改變後的狀態來建立新的映像檔,例如可能使用 shell 在容器中作了一些設定或檔案的變化,此時就可以使用這個指令,根據容器目前的狀態來建立新的映像檔,不過這不是推薦的方式,最好還是利用 Dockerfile
從基礎映像檔加上其他的指令來創建新的映像檔。可以使用 --change
或 -c
來傳入 Dockerfile
中的指令。範例如下:
$ docker commit --change='CMD ["apachectl", "-DFOREGROUND"]' -c "EXPOSE 80" c3f279d17e0a svendowideit/testimage:version4
c3f279d17e0a
為容器的 ID,svendowideit/testimage:version4
為映像檔的名稱及標籤。
其他關於容器狀態管理的指令,例如 start
、stop
、rm
、kill
等等,也都蠻直覺的,就不再介紹,請查閱文件。
這兩天介紹了映像檔和容器,以及編寫 Dockerfile
時常用的指令,明天會介紹 Docker 網路 (network) 及卷宗 (volume)。