Docker

出自 Arch Linux 中文维基

Docker 是一種打包、傳輸和運行任何程序作為輕量級容器的實用工具.

安裝[編輯 | 編輯原始碼]

要拉取Docker鏡像並運行Docker容器,你需要安裝Docker引擎,其包含包括一個守護進程來管理容器,以及一個docker命令行界面前端。安裝 docker 包 或者,對於開發版本,選擇docker-gitAUR 包. 下一步 啟動 docker.service 或者 docker.socket。兩者的差距在於docker.service將會在開機時啟動,而docker.socket將會在第一次啟動Docker時啟動,使用後者可以減少開機啟動時間。然後驗證操作:

# docker info

注意, 如果你有一個活動的 VPN 連接, 那麼 docker 服務的啟動可能失敗, 因為 VPN 和 Docker 的網橋 IP 衝突以及網絡覆蓋. 如果發生了這種事, 嘗試在啟動 docker 服務之前斷開 VPN 連接. 你可以在之後立刻重連 VPN. 你也可以嘗試手動解決網絡衝突(也可參見[1][2])。

你也可以嘗試驗證是否可以運行容器。以下命令行將會下載一個最新的Arch Linux image,並使用其在這個容器中運行一個Hello World程序:

# docker run -it --rm archlinux bash -c "echo hello world"

如果你想以普通用戶身份運行docker的話,添加你自己到 docker 用戶組,重新登錄並重啟docker.service

警告: 任何加入到 docker 組的用戶都和root用戶等價,因為他們可以通過# docker run --privileged來以root權限啟動容器。 查閱更多信息可訪問 這裏這裏.

Docker Compose[編輯 | 編輯原始碼]

Docker Compose是另一種Docker引擎的CLI前端,它使用docker-compose.ymlYAML文件來指定容器的屬性,這樣就可以不使用附帶指令的docker run腳本了.如果你需要經常設置或者使用具有複雜選項的容器,可能使用docker-compose更為方便.你需要安裝 docker-compose來使用.

Docker Desktop[編輯 | 編輯原始碼]

Docker Desktop是一個專有的桌面應用程式,它在一個Linux虛擬機中運行Docker。它還包括Kubernetes集群以及一個漏洞掃描器。這個應用程式對於在macOS或Windows上進行開發Docker容器的團隊非常友好。Docker Desktop適配的Linux版本相對較新,同時也保持了對Docker CLI的良好兼容[3]

Docker直接為Arch Linux提供了一個實驗性的軟件包(參見其官方文檔手動安裝Docker一節)。需要注意其手動下載的軟件包會與docker-compose以及docker-buildx衝突,你需要在安裝前手動移除這兩個包。如果你想保留現有的軟件包,你也可以從AUR安裝docker-desktopAUR,它將不會與現有軟件包發生衝突。

此外,在運行Docker Desktop之前,你需要確保你已經安裝了所有的在Linux上運行的最小系統要求,包括使用KVM進行虛擬化技術支援。對於Gnome用戶,你還需要安裝gnome-shell-extension-appindicator以顯示托盤圖標。

最後,請注意文件共享功能是通過/etc/subuid/etc/subgid映射用戶和組ID完成的。詳細參見Docker Desktop的Linux文件共享說明

使用[編輯 | 編輯原始碼]

Docker由多個部分組成:

  • Docker守護進程(也稱Docker引擎),這是一個以docker.service形式運行的進程。其提供了Docker API接口並管理Docker容器。
  • docker CLI命令,其允許用戶使用命令行來與Docker API交互,並控制 Docker 守護進程。
  • Docker容器,這是一種命名進程,由Docker守護進程通過Docker API的請求進行管理。

一般來說,用戶通過使用docker命令行來對Docker進行操作,命令行又通過Docker API對Docker守護進程發起請求以執行對容器的相關操作。掌握客戶端 (docker), 服務端(docker.service)和容器之間的關係是很必要的。

請注意,如果Docker守護進程停止/重啟,那麼當前運行的所有Docker容器也會停止/重啟。

你也可以不藉助docker CLI來對Docker API發起請求來控制容器,參見Docker API開發指南

更多使用文檔請參見Docker入門指南

配置[編輯 | 編輯原始碼]

Docker守護進程可以通過修改配置文件/etc/docker/daemon.json或者直接在docker.service中添加命令行標誌來進行配置。根據Docker官方文檔, 推薦使用修改配置文件的方法進行配置。如果你想使用添加命令行標誌的方法進行配置,使用Systemd#附加配置片段覆蓋docker.service中的ExecStart部分。

對於daemon.json中的選項,參見守護進程配置文件參考

存儲驅動程序[編輯 | 編輯原始碼]

存儲驅動程序控制着Docker主機上的鏡像與容器的儲存與管理方式。默認的overlay2驅動在大部分情況下都具有良好的性能。

如果你的文件系統使用的是btrfs或者ZFS,你可以使用對應的btrfs或者zfs驅動,它們可以利用這些文件系統獨有的功能,要使用這些驅動請參見btrfs驅動zfs驅動文檔。

啟用守護進程TCP套接字[編輯 | 編輯原始碼]

本文內容或本節內容已經過期。

默認情況下,Docker守護進程使用位於/var/run/docker.sockUnix套接字來提供Docker API。大部分情況下,這是一個合適的選擇。

你可以將設置守護進程設置為額外監聽TCP套接字,這樣就能使Docker API被遠程訪問了(參見允許遠程訪問Docker API)。如果你在Windows或macOS上使用Arch虛擬機,你可以在完成設置後使用宿主機上直接使用docker命令行訪問虛擬機中允許的Docker守護進程。

警告: Docker API默認情況下既沒有加密也沒有身份驗證。除非你在附加Docker配置中啟用了 使用SSH或TLS進行連接,否則對Docker守護進程的TCP訪問等同於不安全的遠程root訪問。

注意默認的docker.service設置了-H標誌,如果選項同時存在於標誌與/etc/docker/daemon.json文件中,Docker將不會啟動,因此最簡單的更改監聽TCP套接字設置的方法是使用一個附加文件。例如,如果你想在端口2376添加一個TCP套接字:

/etc/systemd/system/docker.service.d/docker.conf
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376

重載systemd守護進程並重啟 docker.service以應用更改。

HTTP代理[編輯 | 編輯原始碼]

要想在Docker中使用HTTP代理,你需要同時對Docker守護進程以及Docker容器進行配置。

Docker守護進程代理設置[編輯 | 編輯原始碼]

參見Docker文檔:配置Docker守護進程使用HTTP代理

Docker容器代理設置[編輯 | 編輯原始碼]

參見Docker文檔:如何配置代理,使用dockerCLI來自動為所有容器配置代理。

配置DNS[編輯 | 編輯原始碼]

參見Docker中網絡配置了解Docker容器內部的DNS行為以及如何自定義Docker的DNS配置信息。一般來說,主機上的配置也會直接配置到容器中。

大部分託管在127.0.0.0/8上的DNS解析器都是不被支持的(由於容器和主機網絡命名空間之間的衝突)。這些解析器會在容器中的/etc/resolv.conf中刪除。如果這導致了/etc/resolv.conf為空文件,容器將會使用Google DNS。

此外,如果127.0.0.53是唯一的名稱伺服器,在這種特定的情況下Docker會假設解析器是systemd-resolved並使用來自/run/systemd/resolve/resolv.conf的上游DNS解析器。

如果你使用dnsmasq來提供一個本地解析器,考慮為dnsmasq添加一個虛擬接口(使用169.254.0.0/16網段的鏈路本地IP位址來綁定,而不是127.0.0.1)以避免網絡命名空間衝突。

鏡像位置[編輯 | 編輯原始碼]

默認,docker鏡像放置在 /var/lib/docker。他們可以被移動到其他分區,例如你想將鏡像移動到別的磁盤上,在這個例子中,假設我們要將鏡像移動到/mnt/docker

首先, 停止docker.service,注意,這也會停止所有當前運行的容器並卸載任何正在運行的鏡像。

如果你正在運行docker鏡像,你必須確定鏡像被完全解除掛載。一旦這個完成後,你就可以把鏡像從 /var/lib/docker 移動到你的目標地點。在這個例子中使用指令cp -r /var/lib/docker /mnt/docker

/etc/docker/daemon.json中配置data-root:

/etc/docker/daemon.json
{
  "data-root": "/mnt/docker"
}

重啟docker.service以應用更改。

不安全的自建倉庫[編輯 | 編輯原始碼]

如果您使用自簽名證書的倉庫(registries),或該自建倉庫未使用TLS加密(即:http), docker會拒絕它直到你定義你相信它. 例如,要信任託管於myregistry.example.com:8443上的鏡像,在文件/etc/docker/daemon.json中配置insecure-registries的值:

/etc/docker/daemon.json
{	
  "insecure-registries": [
    "my.registry.example.com:8443"
  ]
}

隨後重新加載 docker.service配置。

IPv6[編輯 | 編輯原始碼]

為了開啟Docker中的IPv6支持,參見[4][5]

首先,將/etc/docker/daemon.json中的ipv6設置為啟用並設置一個特定的IPV6子網(即使用私有的fd00::/80子網)。請確保至少使用80位的子網,因為這樣可以使容器的IPv6地址以容器的MAC地址結尾,這有助於解決NDP鄰居緩存失效的問題。

/etc/docker/daemon.json
{
  "ipv6": true,
  "fixed-cidr-v6": "fd00::/80"
}

重啟 docker.service以應用更改。

最後,為了讓容器能夠訪問主機網絡,你需要添加IPv6 NAT以解決使用私有IPv6子網時出現的路由問題:

# ip6tables -t nat -A POSTROUTING -s fd00::/80 ! -o docker0 -j MASQUERADE

現在Docker應該已經開啟了IPv6支持,你可以使用以下指令來進行測試:

# docker run curlimages/curl curl -v -6 archlinux.org

如果你使用firewalld,你還需要添加防火牆規則,例如:

# firewall-cmd --zone=public --add-rich-rule='rule family="ipv6" destination not address="fd00::1/80" source address="fd00::/80" masquerade'

如果你使用ufw,你還需要根據Uncomplicated Firewall#轉發策略創建Ipv6轉發。

首先,你需要編輯/etc/default/ufw並取消以下幾行的註釋:

/etc/ufw/sysctl.conf
net/ipv6/conf/default/forwarding=1
net/ipv6/conf/all/forwarding=1

現在你可以使用以下命令添加iptables規則:

# ip6tables -t nat -A POSTROUTING -s fd00::/80 ! -o docker0 -j MASQUERADE

如果你使用docker-compose來創建的容器,你可能還需要在networks中對應的部分設置enable_ipv6: true。另外,你可能還需要手動指定IPv6子網,參見compose-file中的ipv6地址設置

用戶命名空間隔離[編輯 | 編輯原始碼]

默認情況下,Docker中的進程和dockerd主守護程序運行在同一用戶命名空間中,即容器不會通過用戶命名空間隔離(參見user_namespaces(7))。這將會允許進程根據用戶和用戶組#權限與屬主在主機上來訪問已配置的資源。這樣提升了容器運行的兼容性,但是一旦出現了一個允許容器中進程訪問非預期資源的漏洞,這會帶來很大的安全隱患。(一個這樣的漏洞在2019年2月發佈並修補。)

啟用用戶命名空間隔離可以降低此類漏洞的影響。其將會在單獨的用戶命空間中運行每個容器,並將這個空間中的UIDs/GIDs映射到主機上不同的(通常情況下也是非特權的)UIDs/GIDs。

注意:
  • dockerd守護程序依然是以root身份在主機上運行的,在非root身份下運行docker(rootless mode)是另一個功能。
  • 容器中的進程將會以Dockerfile中定義的USER指令定義的用戶身份啟動。
  • 所有容器都會映射到相同的UID/GID範圍,這是為了讓容器之間的共享卷功能生效。
  • 在一些情況下無法啟用用戶命名空間。
  • 由於 Docker 需要調整這些資源的所有權,因此啟用用戶命名空間隔離會有效屏蔽現有的映像層和容器層,以及 /var/lib/docker/ 中的其他 Docker 對象。上游文檔建議僅在新安裝的Docker上啟用此功能,而不是在現有的Docker上啟用。

/etc/docker/daemon.json中配置userns-remap的值。default是一個特殊值,其會自動創建名為dockremap的用戶與用戶組用於重映射。

/etc/docker/daemon.json
{
  "userns-remap": "default"
}

/etc/subuid/etc/subgid中配置用戶名/組名,UID/GID的範圍。在這個例子中,dockremap用戶/用戶組分配為從165536開始的65536個UIDs/GIDs。

/etc/subuid
dockremap:165536:65536
/etc/subgid
dockremap:165536:65536

重啟docker.service以應用更改。

應用此更改後,默認情況下所有容器都將在隔離的用戶命名空間中運行。你也可以在docker命令中加上添加標誌--userns=host來在特定的容器中禁用用戶命名空間隔離,參見[6]

無根模式運行Docker守護程序(Docker rootless)[編輯 | 編輯原始碼]

注意: 無根模式下運行Docker守護程序(Docker rootless)依賴於非特權用戶命名空間(CONFIG_USER_NS_UNPRIVILEGED)。在linux, linux-lts, 和linux-zen內核中默認啟用這一功能。如果你使用其他版本的內核,你可能需要手動啟用這一功能。這可能帶來一些安全隱患,參見安全#沙盒程序

要將Docker守護程序作為普通用戶運行,安裝 docker-rootless-extrasAUR軟件包。

隨後在/etc/subuid/etc/subgid中配置用戶名/用戶組名,起始 UID/GID 和 UID/GID 範圍大小,以分配重新映射的用戶和組。以下是一個示例:

/etc/subuid
your_username:165536:65536
/etc/subgid
your_username:165536:65536

啟用 docker.socket systemd/用戶單元: 這將會使用systemd的套接字激活來啟動docker。

最後設置docker套接字的環境變量:

$ export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock

啟用本地覆蓋差異引擎(native overlay diff engine)[編輯 | 編輯原始碼]

本文或本章節的事實準確性存在爭議。

原因: 在Arch Linux上可能不需要這樣做,因為儘管Arch Linux內核默認設置metacopy=on redirect_dir=on,但有些人報告稱這些設置在運行時是被禁用的。(在 Talk:Docker#啟用本地覆蓋差異引擎 中討論)


默認情況下Docker無法在Arch Linux上使用本地覆蓋差異引擎(native overlay diff engine),這會導致構建Docker鏡像很慢。如果你經常構建鏡像,請按照以下步驟配置:

/etc/modprobe.d/disable-overlay-redirect-dir.conf
options overlay metacopy=off redirect_dir=off

隨後停止docker.service, 重新加載overlay內核模塊:

# modprobe -r overlay
# modprobe overlay

重載內核模塊後,啟動docker.service

要驗證是否成功啟用,你可以運行docker info檢查Native Overlay Diff值是否為true

鏡像[編輯 | 編輯原始碼]

Arch Linux[編輯 | 編輯原始碼]

下面的命令會拉取 archlinux x86_64 image.這是一個arch內核的剝離版本,沒有網絡等等.

# docker pull archlinux

也可查閱 README.md.

對於完整的arch基礎,可以從下面克隆鏡像並且建立你自己的鏡像.

$ git clone https://gitlab.archlinux.org/archlinux/archlinux-docker.git

請確保devtools, fakechroot以及fakeroot軟件包已被安裝。

編輯包文件讓它只含有 '基礎'. 運行:

# make docker-image

Alpine Linux[編輯 | 編輯原始碼]

Alpine Linux是一個熱門的小型容器鏡像,其比較適合運行靜態二進制形式軟件。使用以下命令來拉取最新的Alpine Linux鏡像:

# docker pull alpine

Alpine Linux使用musl libc實現,這有區別與大部分的Linux發行版使用的glibc libc實現。 由於Arch Linux使用的glibc,因此Arch Linux主機與Alpine Linux容器之間存在有功能差異,這可能會影響軟件性能或正確性。你可以在此處查看存在的差異。

注意,在Arch Linux(或其他沒有使用musl libc實現的發行版)上編譯的動態連結軟件在Alpine Linux (或其他使用musl libc的鏡像)上可能會出現錯誤或性能問題。參見[7], [8][9]

Debian[編輯 | 編輯原始碼]

下面的命令會拉取Debian鏡像 debian x86_64 image.

# docker pull debian

請參閱Docker Hub頁面查看可用標籤的完整列表,包括每個Debian版本的標準版與精簡版。

手動[編輯 | 編輯原始碼]

debootstrap建立Debian鏡像:

# mkdir jessie-chroot
# debootstrap jessie ./jessie-chroot http://http.debian.net/debian/
# cd jessie-chroot
# tar cpf - . | docker import - debian
# docker run -t -i --rm debian /bin/bash

Distroless[編輯 | 編輯原始碼]

Google 維護着distroless鏡像,這是沒有基本作業系統組件(例如shells和包管理器)的最小化鏡像。其最小鏡像gcr.io/distroless/static-debian11僅有2MiB左右,可以用於打包軟件並生成非常小的鏡像。

請參閱GitHub中的README以獲得鏡像列表以及在不同編程語言中的使用方法。

有用的建議[編輯 | 編輯原始碼]

抓取運行容器的IP位址[編輯 | 編輯原始碼]

抓取運行容器的IP位址:

$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container-name OR id> 
172.17.0.37

每個正在運行的容器,它們的名字和相關IP位址都能被列出來在 /etc/hosts裡用:

#!/usr/bin/env sh
for ID in $(docker ps -q | awk '{print $1}'); do
    IP=$(docker inspect --format="{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" "$ID")
    NAME=$(docker ps | grep "$ID" | awk '{print $NF}')
    printf "%s %s\n" "$IP" "$NAME"
done

運行容器中的圖像程序[編輯 | 編輯原始碼]

本節介紹了允許在主機的X伺服器上運行圖形程序(包括依賴於OpenGL或Vulkan的程序)所需的步驟。

首先,需要在容器內安裝與主機圖形硬件兼容的正確驅動程序。如果容器使用的Arch Linux鏡像,請參見OpenGL#安裝Vulkan#安裝 來安裝對應的驅動。

接下來,你需要授予容器訪問主機上X服務的權限。在單用戶環境中,你可以通過在主機中運行Xhost來完成這一操作。該命令將非網絡本地連接添加到訪問控制列表:

$ xhost +local:

最後,你需要在docker run中傳遞以下參數:

  • -e "DISPLAY=$DISPLAY"將環境變量DISPLAY設置為主機顯示器;
  • --mount type=bind,src=/tmp/.X11-unix,dst=/tmp/.X11-unix將主機X伺服器套接字掛載到相同路徑下的容器內;
  • --device=/dev/dri:/dev/dri允許容器直接訪問主機上的直接渲染(DRI) 設備。

為了驗證設置是否生效,請在容器中運行mesa-utils中的glxgears命令(或者vulkan-tools中的vkcube命令)。

開機啟動 Docker Compose 項目[編輯 | 編輯原始碼]

本文或本章節的事實準確性存在爭議。

原因: 沒有必要在compose.yml中啟用restart: always(討論請參見[10])。[11](在 Talk:Docker#"開機啟動 Docker Compose 項目" 是否多餘? 中討論)


首先,創建一個用於Docker Compose的Systemed單元,並通過服務名稱進行參數化(參見systemd.service(5) § SERVICE TEMPLATES):

/etc/systemd/system/docker-compose@.service
[Unit]
Description=%i service with docker compose
Requires=docker.service
After=docker.service

[Service]
WorkingDirectory=/opt/%i
ExecStartPre=-/usr/bin/docker compose pull
ExecStart=/usr/bin/docker compose up --remove-orphans
ExecStop=/usr/bin/docker compose down
ExecReload=/usr/bin/docker compose pull
ExecReload=/usr/bin/docker compose up --remove-orphans

[Install]
WantedBy=multi-user.target

隨後,對於你想運行的每一個服務,在/opt/project_name目錄下新建一個包含Compose文件以及其他所需文件(例如.env文件)[12]

最後, 啟用/啟動 docker-compose@project_name.service

使用buildx進行交叉編譯[編輯 | 編輯原始碼]

buildx CLI 插件使用了新的BuildKit構建工具包安裝docker-buildx,buildx接口支持構建多平台鏡像(包括與主機不同的框架)。

交叉編譯鏡像也需要QEMU。如果你想在Docker中設置靜態版本的QEMU,請參見multiarch/qemu-user-static 鏡像。否則請在主機上設置QEMU與Docker共同使用(參見QEMU#從 x86_64 環境中 Chroot 至 arm/arm64 環境)。無論哪種情況,你的系統都將配置為對客戶端架構進行用戶模式模擬。

$ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS  PLATFORMS
default * docker                  
  default default         running linux/amd64, linux/386, linux/arm64, linux/riscv64, linux/s390x, linux/arm/v7, linux/arm/v6

用NVIDIA GPU運行GPU加速的Docker容器[編輯 | 編輯原始碼]

從19.03版本開始,Docker原生支持NVIDIA GPU作為Docker設備。 推薦使用NVIDIA Container Toolkit來運行需要操作NVIDIA顯卡的容器。 安裝 nvidia-container-toolkit 包並重啟Docker。之後可以用--gpus選項來運行使用NVIDIA顯卡的容器

使用 --gpus 選項(推薦)[編輯 | 編輯原始碼]

# docker run --gpus all nvidia/cuda:12.1.1-runtime-ubuntu22.04 nvidia-smi

指定容器內可使用多少GPU:

# docker run --gpus 2 nvidia/cuda:12.1.1-runtime-ubuntu22.04 nvidia-smi

指定使用哪一個GPU:

# docker run --gpus '"device=1,2"' nvidia/cuda:12.1.1-runtime-ubuntu22.04 nvidia-smi

# docker run --gpus '"device=UUID-ABCDEF,1"' nvidia/cuda:12.1.1-runtime-ubuntu22.04 nvidia-smi

本文或本章節的事實準確性存在爭議。

原因: More information on when the following error happens is needed. It should work, see [13][失效連結 2023-04-23 ⓘ].(在 Talk:Docker#GPU accelerated Docker Nvidia 中討論)


如果在執行指令時收到錯誤Failed to initialize NVML: Unknown Error,你可以嘗試詳細指定GPU來解決這個問題:

# docker run --gpus all --device /dev/nvidiactl:/dev/nvidiactl --device /dev/nvidia-uvm:/dev/nvidia-uvm --device /dev/nvidia0:/dev/nvidia0 nvidia/cuda:12.1.1-runtime-ubuntu22.04 nvidia-smi

指定需要的具體功能(圖像、計算等)

# docker run --gpus all,capabilities=utility nvidia/cuda:12.1.1-runtime-ubuntu22.04 nvidia-smi

參閱 container-toolkit文檔安裝指南

使用 NVIDIA Container Runtime[編輯 | 編輯原始碼]

編輯/etc/docker/daemon.json以註冊NVIDIA運行時環境。

/etc/docker/daemon.json
{
  "runtimes": {
    "nvidia": {
      "path": "/usr/bin/nvidia-container-runtime",
      "runtimeArgs": []
    }
  }
}

之後重啟 Docker。

運行時也可以通過dockerd的一個命令行選項來註冊。

# /usr/bin/dockerd --add-runtime=nvidia=/usr/bin/nvidia-container-runtime

完成後可通過命令啟動GPU加速的容器:

# docker run --runtime=nvidia nvidia/cuda:9.0-base nvidia-smi

或 (要求 Docker 版本19.03或更高)

# docker run --gpus all nvidia/cuda:9.0-base nvidia-smi

參閱 README.md

有CUDA的 Arch Linux 鏡像[編輯 | 編輯原始碼]

可使用以下Dockerfile 構建自定義的有CUDA的 Arch Linux 鏡像。它使用 Dockerfile frontend syntax 1.2 在宿主機上緩存pacman包。請注意,你必須在構建鏡像之前設置環境變量DOCKER_BUILDKIT=1

Dockerfile
# syntax = docker/dockerfile:1.2

FROM archlinux

# 使用更快的镜像 
RUN echo 'Server = https://mirror.pkgbuild.com/$repo/os/$arch' > /etc/pacman.d/mirrorlist

# 安装包
RUN --mount=type=cache,sharing=locked,target=/var/cache/pacman \
    pacman -Syu --noconfirm --needed base base-devel cuda

# 配置 nvidia container runtime
# https://github.com/NVIDIA/nvidia-container-runtime#environment-variables-oci-spec
ENV NVIDIA_VISIBLE_DEVICES all
ENV NVIDIA_DRIVER_CAPABILITIES compute,utility

移除docker和鏡像[編輯 | 編輯原始碼]

如果你想完全移除Docker,你可以通過下面的步驟完成:

注意: 不要僅僅只是複製粘貼下面的命令而不知道你在幹什麼!

檢查正在運行的容器:

# docker ps

列出在主機運行的所有容器,為刪除做準備:

# docker ps -a

停止一個運行的容器:

# docker stop <CONTAINER ID>

殺死還在運行的容器:

# docker kill <CONTAINER ID>

通過ID刪除列出的所有容器:

# docker rm <CONTAINER ID>

列出所有的docker鏡像:

# docker images

通過ID刪除所有鏡像:

# docker rmi <IMAGE ID>

刪除所有與容器沒有關聯的鏡像,容器,卷與網絡(懸空):

# docker system prune

要刪除所有停止的容器和所有未使用的鏡像(而不只是懸空鏡像),添加-a 標誌:

# docker system prune -a

刪除所有docker數據 (清除目錄):

# rm -R /var/lib/docker

故障排除[編輯 | 編輯原始碼]

使用systemd-networkd時,docker0 網橋無法獲取 IP / Internet 到容器[編輯 | 編輯原始碼]

Docker會自己啟用IP轉發,但是默認 systemd-networkd 會覆蓋對應的sysctl設置,在網絡配置文件裡設置 IPForward=yes。查閱 網絡分享#啟用包轉發 獲取細節。

systemd-networkd嘗試管理由Docker創建的網絡時,如果你在Match部分設置了Name=*Type=ether,這可能會導致網絡連接出現問題。請更為具體地配置接口,即儘可能避免使用Name=*Type=ether等通配符來匹配Docker管理的接口。你可以驗證 networkctl list 是否在 Docker 創建的所有網絡的 SETUP 欄中設置為 unmanaged

注意:
  • 你可能需要在每次 重啟 systemd-networkd.service 或者 iptables.service 之後,再手動重啟 docker.service
  • 注意nftables默認情況下可能會禁止Docker的連接,你可以使用命令 nft list ruleset 來檢查規則集。
  • 你可以使用 nft flush chain inet filter forward 來臨時移除所有轉發規則,或者編輯 /etc/nftables.conf 文件使其永久生效。在更改了配置文件,請 重啟 nftables.service 以應用更改。詳細了解Docker的nftables支持請參見 [14]

默認的允許的進程/線程數太少[編輯 | 編輯原始碼]

如果你允許時得到下面的錯誤信息

# e.g. Java
java.lang.OutOfMemoryError: unable to create new native thread
# e.g. C, bash, ...
fork failed: Resource temporarily unavailable

那麼你可能需要調整被systemd允許的進程數, 編輯 並添加下面片段 docker.service :

# systemctl edit docker.service
[Service]
TasksMax=infinity

對於更多參數,例如 DefaultLimitNPROC,請參閱 systemd-system.conf(5) § OPTIONS。對於 TasksMax 請參閱 systemd.resource-control(5) § OPTIONS

初始化顯卡驅動錯誤: devmapper[編輯 | 編輯原始碼]

如果 systemctl 不能開啟docker並提供了以下信息:

Error starting daemon: error initializing graphdriver: devmapper: Device docker-8:2-915035-pool is not a thin pool

那麼嘗試以下步驟來解決錯誤。停止docker服務,備份 /var/lib/docker/ (如果需要的話), 移除/var/lib/docker/的內容, 嘗試重啟docker服務. 查閱 GitHub issue 獲取更多細節.

無法創建到某文件的路徑: 設備沒有多餘的空間了[編輯 | 編輯原始碼]

如果你獲取到的錯誤信息是像這樣的話:

ERROR: Failed to create some/path/to/file: No space left on device

當創建或者運行Docker鏡像時,儘管磁盤還有多餘的空間。所以請確保:

  • Tmpfs 被禁用了並且有足夠的內存分配. Docker可能會嘗試寫入文件到 /tmp 但是失敗了因為內存使用的限制和磁盤空間不足.
  • 如果你在使用 XFS, 你可能得從相關入口移除 noquota 掛載選項在 /etc/fstab裡 (通常是 /tmp 和/或 /var/lib/docker 在的地方). 查閱 Disk quota 獲取更多信息, 特別是你計劃使用和調整 overlay2 Docker 存儲驅動.
  • XFS 的配額掛載選項在文件系統重新掛載時 (uquota, gquota, prjquota, 等等.) 失敗了. 為了為root文件系統啟用配額掛載選項必須作為 內核參數 rootflags=傳遞到initramfs. 之後, 它就不應該在 /etc/fstab中的掛載選項中列出root (/) 文件系統.
注意: XFS配額和標準LinuxDisk quota, [15] 是有區別的。這裏值得一讀.

Docker-machine無法使用virtualbox驅動程序創建虛擬機[編輯 | 編輯原始碼]

如果docker-machine 無法使用 virtualbox 驅動程序創建虛擬機並提供了以下信息:

VBoxManage: error: VBoxNetAdpCtl: Error while adding new interface: failed to open /dev/vboxnetctl: No such file or directory

嘗試在CLI中使用vboxreload重啟virtualbox。

啟動Docker後會破壞KVM的橋接網絡[編輯 | 編輯原始碼]

這是因為啟動Docker的腳本會添加一些iptables規則,其會阻止除自身外的其他接口進行轉發。這是一個已知問題

您可以嘗試以下的解決方案(請將br0替換為您自己的橋接網絡名稱):

  • 最快的解決方案(但是這會關閉所有Docker自動添加的iptables規則):
/etc/docker/daemon.json
{
  "iptables": false
}
  • 如果您已經配置好了用於KVM的橋接網絡,您也可以通過修改Docker的配置文件來解決這個問題,參見[16]將配置文件修改為:
/etc/docker/daemon.json
{
  "bridge": "br0"
}
  • 如果上述方法無效,或者您希望直接通過iptables或者類似於UFW的管理器來解決問題,請添加以下內容:
iptables -I FORWARD -i br0 -o br0 -j ACCEPT

更詳細的解決方案可以參見此處

從Docker Hub拉取的鏡像受到速率限制[編輯 | 編輯原始碼]

從2020年11月1日開始,Docker Hub限制了匿名用戶以及免費賬戶用戶的下載速率,詳細請參見 速率限制文檔

匿名用戶的速率限制通過IP進行跟蹤,免費賬戶用戶的速率限制通過賬戶進行跟蹤。

如果你需要更高的下載速率,你可以 註冊付費計劃 或者將你需要的鏡像拉取到不同的鏡像倉庫。你可以 自建鏡像倉庫 或者使用雲託管的鏡像站點,例如 Amazon ECR, Google Container Registry, Azure Container RegistryQuay Container Registry

使用Docker CLI 中的 pull, tag 以及 push 命令來鏡像一個鏡像。例如,將 Nginx 標籤(tag)為 1.19.3 的鏡像鏡像到託管於 cr.example.com 上的倉庫:

$ docker pull nginx:1.19.3
$ docker tag nginx:1.19.3 cr.example.com/nginx:1.19.3
$ docker push cr.example.com/nginx:1.19.3

隨後你可以從鏡像倉庫中拉取並運行鏡像:

$ docker pull cr.example.com/nginx:1.19.3
$ docker run cr.example.com/nginx:1.19.3

錯誤提示:iptables (舊版): 未知選項 "--dport"[編輯 | 編輯原始碼]

本文或本章節的事實準確性存在爭議。

原因: Nftables#與 Docker 一起工作 建議不要使用 iptables-nft。(在 Talk:Docker 中討論)

如果你在運行容器時收到了這樣的錯誤: iptables (legacy): unknown option "--dport"

安裝 iptables-nft 而不是 iptables (舊版) 然後重啟[17]

注意: 使用iptables-nft可能會導致docker 混合 nftables 和 iptables 規則,詳細參見Nftables#與 Docker 一起工作

運行docker login時提示"密碼以非加密形式儲存"[編輯 | 編輯原始碼]

默認情況下 Docker 會嘗試使用 pass 或者 secretservice 的二進制形式文件來儲存你的註冊表密碼。如未能找到這些文件,註冊表秘密將以明文形式(base64編碼)儲存在 $HOME/.docker/config.json ,並在登錄成功後提示:

$ WARNING! Your password will be stored unencrypted in /home/username/.docker/config.json.

如果你在使用支持 Secret Service Freedesktop DBUS API 的密碼管理器,例如KDE的 kwallet 或着 GNOME的 gnome-keyring,你可以安裝 docker-credential-secretserviceAUR 來讓你的註冊表密碼儲存在密碼管理器中。

"無法在默認選項中找到可用的,不重疊的IPv4地址池進行分配"[編輯 | 編輯原始碼]

如果你在使用大量的 Docker 項目 (例如使用 docker-compose),可能會出現Docker容器的可用IP位址不足的情況:

Could not find an available, non-overlapping IPv4 address pool among the defaults to assign to the network

參見 這個 Docker issue, 默認選項是:

Type Default Size Default Pool
local /16 172.17.0.0/12
local* /20 192.168.0.0/16

你可以在 /etc/docker/daemon.json 文件中修改 default-address-pools ,將其中第一個IP範圍的值從16改為24解決這個問題。為了避免本地網絡發生IP衝突,請不要修改第二個IP範圍的值。

/etc/docker/daemon.json
{
  ...
  "default-address-pools" : [
    {
      "base" : "172.17.0.0/12",
      "size" : 24
    },
    {
      "base" : "192.168.0.0/16",
      "size" : 24
    }
  ]
}

重啟 docker.service 以應用更改。

更多詳細信息和技術解釋請參見文章: Docker默認地址池選項的權威指南

Golang編譯速度過慢[編輯 | 編輯原始碼]

由於ulimit配置的原因,使用makepkg構建docker鏡像以及其依賴時會非常緩慢(會在"Entering fakeroot environment..."處卡住)。

這是因為[18] [19],你可以嘗試將 --ulimit "nofile=1024:524288" 添加到你的docker構建選項中來解決問題:

/etc/docker/daemon.json
{
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Soft": 1024,
      "Hard": 524288
    }
  }
} 

查閱更多[編輯 | 編輯原始碼]