Docker 基礎

最後更新: 2022-01-28 15:44:22 +0800 +0800
原文以英文撰寫。您正在閱讀AI翻譯版本。

Docker 是仍依賴核心、CPU 指令集架構及其 x86-64 syscall 的容器系統。 在 Docker 容器中執行的應用程式稱為容器化應用程式。

元件概覽 #

Docker Engine:dockerd #

dockerd 是管理本機系統已安裝容器的 CLI 常駐程式。 其品牌名稱為 Docker Engine 或 Docker CE(Community Edition),而且是開放原始碼的免費軟體。

dockerd 常駐程式會在 UNIX 網域通訊端 /var/run/docker.sock 上監聽傳入的用戶端。 執行 Docker 用戶端的使用者必須能夠讀取此通訊端檔案,才能建立通訊端連線(以傳送 HTTP 請求)。 若透過 Linux 發行版的套件管理員安裝 Docker Engine,此通訊端檔案可能只允許 root 或 Docker 專用的特殊使用者群組(例如 docker)讀取。 你可以選擇將自己加入該使用者群組,或在每次使用 docker 用戶端時直接切換為 root。 使用 docker info 檢查 dockerd 是否正在執行,以及用戶端是否具備權限。

dockerd 常駐程式公開管理容器的 HTTP API,任何程式都能使用。 官方用戶端程式是 docker CLI 程式。

Docker Desktop #

Docker Desktop 是專有的 GUI 用戶端程式,會與 dockerd 通訊並執行容器維護作業。 不一定要使用 Docker Desktop 應用程式。

Docker Compose #

https://docs.docker.com/compose/

Docker Compose 是另一個與 dockerd 通訊的 CLI 用戶端,其執行檔為 docker-compose。 它使用 docker-compose.yml 檔案指定容器屬性,無須反覆輸入 docker run 選項。 此方式適合設定經常使用及/或設定複雜的週期性服務。

映像檔 #

Docker 映像檔由多層檔案系統內容組成,每一層都會在上一層加入一些檔案。 若某個映像檔的第一層依賴另一個映像檔的所有層,就稱此前者以後者為基礎。

映像檔具有易讀的名稱 REPOSITORY 與易讀的 TAG(通常是版本號,但並非必要)。 稱為 IMAGE ID 的 SHA256 雜湊值可唯一識別映像檔。

若要建置自己的映像檔,請建立 Dockerfile,以簡單語法定義建立映像檔所需的步驟。 Dockerfile 中的每項指令都會在映像檔中建立一層。 修改 Dockerfile 並需要重新建置映像檔時,只會重新建置已變更的層。

例如,esolang/vim:latest 映像檔包含 10 層。

sh
# $ Docker Pull Esolang/vim
Using default tag: latest
latest: Pulling from esolang/vim
4abcf2066143: Downloading  2.951MB/3.409MB
e7609a7fad9e: Download complete
a891a2921638: Download complete
6ea6322cdcb0: Download complete
729f825b6ae6: Download complete
e6cb43f5f474: Downloading  2.618MB/31.24MB
c12ed1c2e19b: Download complete
6928286dd6f6: Download complete
05de04103836: Download complete
b5a8264627eb: Download complete

Docker 不會將 Dockerfile 儲存在建置完成的映像檔中,因此要檢查映像檔的建置方式會稍微困難。

原因在於,也可以透過執行容器、進行修改,再提交結果來建立映像檔。 事實上,可以將 Dockerfile 視為將「執行、修改、提交」流程自動化的指令碼。

最小映像檔 #

建置一個沒有基礎映像檔,也不含任何檔案系統內容(除了一個最小的 hello world 執行檔)的最小 Docker 映像檔:

asm
; linux_syscall call_no, arg0, arg1, arg2, arg3, arg4, arg5
%macro linux_syscall 1-7 0,0,0,0,0,0

    mov rax, %1
    mov rdi, %2
    mov rsi, %3
    mov rdx, %4
    mov r10, %5
    mov r8, %6
    mov r9, %7
    syscall

%endmacro



SECTION .data
msg:    db `hello world\n`
msglen: equ $-msg

GLOBAL main

SECTION .text
main:
    ; write to stdout a string
    linux_syscall 1,1,msg,msglen

    ; exit the process with code 42
    linux_syscall 0x3c, 42

使用 make 建置執行檔:

Makefile
main: main.o
	# -N: don't align data segment on a new memory page, thus makes the executable as small as possible
	ld -N -e manbaout -omain main.o

main.o: main.asm
	nasm -f elf64 -o main.o main.asm

clean:
	rm *.o main

使用下列 Dockerfile 建置映像檔:

Dockerfile
FROM    scratch
ADD     main    /
sh
docker build -t foo .

在我的電腦上,這會產生僅 904 位元組的 Docker 映像檔(由 docker image ls 回報)。從該映像檔執行容器:

sh
docker run foo ./main

容器 #

容器是映像檔的執行中執行個體。容器的生命週期從 docker container create <image> 命令開始,接著執行 docker start <container>。docker run <image> 是同時執行兩者的簡寫;若本機不存在 <image>,它還會從設定的登錄檔(預設為 Docker Hub)下載映像檔。docker run 一律會從指定映像檔建立全新容器,然後啟動該容器。

若要使用既有但未啟用(已退出或暫停)的容器,請再次使用 docker start。

在任一特定時間點,Docker 容器會處於下列 6 種可能狀態之一。

  1. created:完整;容器建立後從未啟動。
  2. running:ENTRYPOINT 程序正在執行(精確而言,對它執行 wait(2) 會阻塞)。
  3. Restarting:
  4. Exited(num):ENTRYPOINT 程序以 num 退出。
  5. Paused:
  6. Dead:

Dockerfile #

Dockerfile 僅定義了 17 項指令:

名稱
ADD加入本機或遠端檔案與目錄。
ARG使用建置階段變數。
CMD指定預設命令。
COPY複製檔案與目錄。
ENTRYPOINT指定預設執行檔。
ENV設定環境變數。
EXPOSE說明應用程式監聽的連接埠。
FROM從基礎映像檔建立新的建置階段。
HEALTHCHECK在啟動時檢查容器的健康狀態。
LABEL為映像檔加入中繼資料。
MAINTAINER指定映像檔作者。
ONBUILD指定映像檔用於建置時所執行的指令。
RUN執行建置命令。
SHELL設定映像檔的預設 shell。
STOPSIGNAL指定退出容器所用的系統呼叫訊號。
USER設定使用者與群組 ID。
VOLUME建立磁碟區掛載。
WORKDIR變更工作目錄。

只有 RUN、COPY 與 ADD 指令會建立並保留在結果映像檔中的層。

多數指令會指示 docker image build 命令如何在結果的靜態映像檔中加入新的一層。

  • RUN 命令是例外,它會在建置時立即執行外部命令。

務必區分在 docker image build 執行時立即執行的指令,以及指示 Docker 在從所建立映像檔實例化容器後應如何運作的指令。

CLI 速查表 #

sh
# Show Active Container
docker container ls
# Show All Container Includes Dead One
docker container ls -a
# Stop Certain Containers
docker stop <cid1> <cid2> ...
# Stop All Active Containers
docker stop $(docker container ls –aq)

評論

在 GitHub 上閱讀或評論(發表評論需要登入)