天天看點

26個docker常見問題集錦(幹貨)

作者:辣個男人Devin

鏡像相關

如何批量清理臨時鏡像檔案?

答:可以使用 docker image prune 指令。

如何檢視鏡像支援的環境變量?

答:可以使用 docker run IMAGE env 指令。

本地的鏡像檔案都存放在哪裡?

答:與 Docker 相關的本地資源預設存放在 /var/lib/docker/ 目錄下,以 overlay2 檔案系統為例,其中 containers 目錄存放容器資訊,image 目錄存放鏡像資訊,overlay2 目錄下存放具體的鏡像層檔案。

建構 Docker 鏡像應該遵循哪些原則?

答:整體原則上,盡量保持鏡像功能的明确和内容的精簡,要點包括

  • 盡量選取滿足需求但較小的基礎系統鏡像,例如大部分時候可以選擇 alpine 鏡像,僅有不足六兆大小;
  • 清理編譯生成檔案、安裝包的緩存等臨時檔案;
  • 安裝各個軟體時候要指定準确的版本号,并避免引入不需要的依賴;
  • 從安全角度考慮,應用要盡量使用系統的庫和依賴;
  • 如果安裝應用時候需要配置一些特殊的環境變量,在安裝後要還原不需要保持的變量值;
  • 使用 Dockerfile 建立鏡像時候要添加 .dockerignore 檔案或使用幹淨的工作目錄。

碰到網絡問題,無法 pull 鏡像,指令行指定 http_proxy 無效?

答:在 Docker 配置檔案中添加 export http_proxy="http://<PROXY_HOST>:<PROXY_PORT>",之後重新開機 Docker 服務即可。

容器相關

容器退出後,通過 docker container ls 指令檢視不到,資料會丢失麼?

答:容器退出後會處于終止(exited)狀态,此時可以通過 docker container ls -a 檢視。其中的資料也不會丢失,還可以通過 docker start 指令來啟動它。隻有删除掉容器才會清除所有資料。

如何停止所有正在運作的容器?

答:可以使用 docker stop $(docker container ls -q) 指令。

如何批量清理已經停止的容器?

答:可以使用 docker container prune 指令。

如何擷取某個容器的 PID 資訊?

答:可以使用

docker inspect --format '{{ .State.Pid }}' <CONTAINER ID or NAME>

如何擷取某個容器的 IP 位址?

答:可以使用

docker inspect --format '{{ .NetworkSettings.IPAddress }}' <CONTAINER ID or NAME>

如何給容器指定一個固定 IP 位址,而不是每次重新開機容器 IP 位址都會變?

答:使用以下指令啟動容器可以使容器 IP 固定不變

$ docker network create -d bridge --subnet 172.25.0.0/16 my-net

$ docker run --network=my-net --ip=172.25.3.3 -itd --name=my-container busybox

如何臨時退出一個正在互動的容器的終端,而不終止它?

答:按 Ctrl-p Ctrl-q。如果按 Ctrl-c 往往會讓容器内應用程序終止,進而會終止容器。

使用 docker port指令映射容器的端口時,系統報錯“Error: No public port '80' published for xxx”?

答:

  • 建立鏡像時 Dockerfile 要通過 EXPOSE 指定正确的開放端口;
  • 容器啟動時指定 PublishAllPort = true。

可以在一個容器中同時運作多個應用程序麼?

答:一般并不推薦在同一個容器内運作多個應用程序。如果有類似需求,可以通過一些額外的程序管理機制,比如 supervisord 來管理所運作的程序。可以參考 https://docs.docker.com/config/containers/multi-service_container/ 。

如何控制容器占用系統資源(CPU、記憶體)的份額?

答:在使用 docker create 指令建立容器或使用 docker run 建立并啟動容器的時候,可以使用 -c|--cpu-shares[=0] 參數來調整容器使用 CPU 的權重;使用 -m|--memory[=MEMORY] 參數來調整容器使用記憶體的大小。

倉庫相關

倉庫(Repository)、注冊伺服器(Registry)、注冊索引(Index) 有何關系?

首先,倉庫是存放一組關聯鏡像的集合,比如同一個應用的不同版本的鏡像。

注冊伺服器是存放實際的鏡像檔案的地方。注冊索引則負責維護使用者的賬号、權限、搜尋、标簽等的管理。是以,注冊伺服器利用注冊索引來實作認證等管理。

配置相關

Docker 的配置檔案放在哪裡,如何修改配置?

答:使用 systemd 的系統(如 Ubuntu 16.04、Centos 等)的配置檔案在 /etc/docker/daemon.json。

如何更改 Docker 的預設存儲位置?

答:Docker 的預設存儲位置是 /var/lib/docker,如果希望将 Docker 的本地檔案存儲到其他分區,可以使用 Linux 軟連接配接的方式來完成,或者在啟動 daemon 時通過 -g 參數指定,或者修改配置檔案 /etc/docker/daemon.json 的 "data-root" 項 。可以使用 docker system info | grep "Root Dir" 檢視目前使用的存儲位置。

例如,如下操作将預設存儲位置遷移到 /storage/docker。

[root@s26 ~]# df -h

Filesystem Size Used Avail Use% Mounted on

/dev/mapper/VolGroup-lv_root 50G 5.3G 42G 12% /

tmpfs 48G 228K 48G 1% /dev/shm

/dev/sda1 485M 40M 420M 9% /boot

/dev/mapper/VolGroup-lv_home 222G 188M 210G 1% /home

/dev/sdb2 2.7T 323G 2.3T 13% /storage

[root@s26 ~]# service docker stop

[root@s26 ~]# cd /var/lib/

[root@s26 lib]# mv docker /storage/

[root@s26 lib]# ln -s /storage/docker/ docker

[root@s26 lib]# ls -la docker

lrwxrwxrwx. 1 root root 15 11月 17 13:43 docker -> /storage/docker

[root@s26 lib]# service docker start

使用記憶體和 swap 限制啟動容器時候報警告:"WARNING: Your kernel does not support cgroup swap limit. WARNING: Your kernel does not support swap limit capabilities. Limitation discarded."?

答:這是因為系統預設沒有開啟對記憶體和 swap 使用的統計功能,引入該功能會帶來性能的下降。要開啟該功能,可以采取如下操作:

  • 編輯 /etc/default/grub 檔案(Ubuntu 系統為例),配置 GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"
  • 更新 grub:$ sudo update-grub
  • 重新開機系統,即可。

Docker 與虛拟化

Docker 與 LXC(Linux Container)有何不同?

答:LXC 利用 Linux 上相關技術實作了容器。Docker 則在如下的幾個方面進行了改進:

  • 移植性:通過抽象容器配置,容器可以實作從一個平台移植到另一個平台;
  • 鏡像系統:基于 OverlayFS 的鏡像系統為容器的分發帶來了很多的便利,同時共同的鏡像層隻需要存儲一份,實作高效率的存儲;
  • 版本管理:類似于Git的版本管理理念,使用者可以更友善的建立、管理鏡像檔案;
  • 倉庫系統:倉庫系統大大降低了鏡像的分發和管理的成本;
  • 周邊工具:各種現有工具(配置管理、雲平台)對 Docker 的支援,以及基于 Docker的 PaaS、CI 等系統,讓 Docker 的應用更加友善和多樣化。

Docker 與 Vagrant 有何不同?

答:兩者的定位完全不同。

  • Vagrant 類似 Boot2Docker(一款運作 Docker 的最小核心),是一套虛拟機的管理環境。Vagrant 可以在多種系統上和虛拟機軟體中運作,可以在 Windows,Mac 等非 Linux 平台上為 Docker 提供支援,自身具有較好的包裝性和移植性。
  • 原生的 Docker 自身隻能運作在 Linux 平台上,但啟動和運作的性能都比虛拟機要快,往往更适合快速開發和部署應用的場景。

簡單說:Vagrant 适合用來管理虛拟機,而 Docker 适合用來管理應用環境。

開發環境中 Docker 和 Vagrant 該如何選擇?

答:Docker 不是虛拟機,而是程序隔離,對于資源的消耗很少,但是目前需要 Linux 環境支援。Vagrant 是虛拟機上做的封裝,虛拟機本身會消耗資源。

如果本地使用的 Linux 環境,推薦都使用 Docker。

如果本地使用的是 macOS 或者 Windows 環境,那就需要開虛拟機,單一開發環境下 Vagrant 更簡單;多環境開發下推薦在 Vagrant 裡面再使用 Docker 進行環境隔離。

其它

Docker 能在非 Linux 平台(比如 Windows 或 macOS )上運作麼?

答:完全可以。安裝方法請檢視 安裝 Docker 一節

如何将一台宿主主機的 Docker 環境遷移到另外一台宿主主機?

答:停止 Docker 服務。将整個 Docker 存儲檔案夾複制到另外一台宿主主機,然後調整另外一台宿主主機的配置即可。

如何進入 Docker 容器的網絡命名空間?

答:Docker 在建立容器後,删除了宿主主機上 /var/run/netns 目錄中的相關的網絡命名空間檔案。是以,在宿主主機上是無法看到或通路容器的網絡命名空間的。

使用者可以通過如下方法來手動恢複它。

首先,使用下面的指令檢視容器程序資訊,比如這裡的 1234。

$ docker inspect --format='{{. State.Pid}} ' $container_id

1234

接下來,在 /proc 目錄下,把對應的網絡命名空間檔案連結到 /var/run/netns 目錄。

$ sudo ln -s /proc/1234/ns/net /var/run/netns/

然後,在宿主主機上就可以看到容器的網絡命名空間資訊。例如

$ sudo ip netns show

1234

此時,使用者可以通過正常的系統指令來檢視或操作容器的命名空間了。例如修改容器的 IP 位址資訊為 172.17.0.100/16。

$ sudo ip netns exec 1234 ifconfig eth0 172.17.0.100/16

如何擷取容器綁定到本地那個 veth 接口上?

答:Docker 容器啟動後,會通過 veth 接口對連接配接到本地網橋,veth 接口命名跟容器命名毫無關系,十分難以找到對應關系。

最簡單的一種方式是通過檢視接口的索引号,在容器中執行 ip a 指令,檢視到本地接口最前面的接口索引号,如 205,将此值加上 1,即 206,然後在本地主機執行 ip a 指令,查找接口索引号為 206 的接口,兩者即為連接配接的 veth 接口對。

參考連結:https://yeasy.gitbook.io/docker_practice/appendix/faq