鏡像相關
如何批量清理臨時鏡像檔案?
答:可以使用 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