# 常見問題總結
## 鏡像相關
### 如何批量清理臨時鏡像文件?
答:可以使用 `docker image prune` 命令。
### 如何查看鏡像支持的環境變量?
答:可以使用 `docker run IMAGE env` 命令。
### 本地的鏡像文件都存放在哪里?
答:與 Docker 相關的本地資源都存放在 `/var/lib/docker/` 目錄下,以 `aufs` 文件系統為例,其中 `container` 目錄存放容器信息,`graph` 目錄存放鏡像信息,`aufs` 目錄下存放具體的鏡像層文件。
### 構建 Docker 鏡像應該遵循哪些原則?
答:整體原則上,盡量保持鏡像功能的明確和內容的精簡,要點包括
* 盡量選取滿足需求但較小的基礎系統鏡像,例如大部分時候可以選擇 debian:wheezy 或 debian:jessie 鏡像,僅有不足百兆大小;
* 清理編譯生成文件、安裝包的緩存等臨時文件;
* 安裝各個軟件時候要指定準確的版本號,并避免引入不需要的依賴;
* 從安全角度考慮,應用要盡量使用系統的庫和依賴;
* 如果安裝應用時候需要配置一些特殊的環境變量,在安裝后要還原不需要保持的變量值;
* 使用 Dockerfile 創建鏡像時候要添加 .dockerignore 文件或使用干凈的工作目錄。
更多內容請查看 [Dockerfile 最佳實踐](https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/)
### 碰到網絡問題,無法 pull 鏡像,命令行指定 http_proxy 無效?
答:在 Docker 配置文件中添加 `export http_proxy="http://<PROXY_HOST>:<PROXY_PORT>"`,之后重啟 Docker 服務即可。
## 容器相關
### 容器退出后,通過 docker container ls 命令查看不到,數據會丟失么?
答:容器退出后會處于終止(exited)狀態,此時可以通過 `docker container ls -a` 查看。其中的數據也不會丟失,還可以通過 `docker start` 命令來啟動它。只有刪除掉容器才會清除所有數據。
### 如何停止所有正在運行的容器?
答:可以使用 `docker kill $(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 固定不變
```bash
$ 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/engine/admin/multi-service_container/ 。
### 如何控制容器占用系統資源(CPU、內存)的份額?
答:在使用 `docker create` 命令創建容器或使用 `docker run` 創建并啟動容器的時候,可以使用 -c|--cpu-shares[=0] 參數來調整容器使用 CPU 的權重;使用 -m|--memory[=MEMORY] 參數來調整容器使用內存的大小。
## 倉庫相關
### 倉庫(Repository)、注冊服務器(Registry)、注冊索引(Index) 有何關系?
首先,倉庫是存放一組關聯鏡像的集合,比如同一個應用的不同版本的鏡像。
注冊服務器是存放實際的鏡像文件的地方。注冊索引則負責維護用戶的賬號、權限、搜索、標簽等的管理。因此,注冊服務器利用注冊索引來實現認證等管理。
## 配置相關
### Docker 的配置文件放在哪里,如何修改配置?
答:使用 `upstart` 的系統(如 Ubuntu 14.04)的配置文件在 `/etc/default/docker`,使用 `systemd` 的系統(如 Ubuntu 16.04、Centos 等)的配置文件在 `/etc/docker/daemon.json`。
### 如何更改 Docker 的默認存儲位置?
答:Docker 的默認存儲位置是 `/var/lib/docker`,如果希望將 Docker 的本地文件存儲到其他分區,可以使用 Linux 軟連接的方式來完成,或者在啟動 daemon 時通過 `-g` 參數指定。
例如,如下操作將默認存儲位置遷移到 /storage/docker。
```sh
[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 則在如下的幾個方面進行了改進:
* 移植性:通過抽象容器配置,容器可以實現從一個平臺移植到另一個平臺;
* 鏡像系統:基于 AUFS 的鏡像系統為容器的分發帶來了很多的便利,同時共同的鏡像層只需要存儲一份,實現高效率的存儲;
* 版本管理:類似于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](../../install/) 一節
### 如何將一臺宿主主機的 Docker 環境遷移到另外一臺宿主主機?
答:停止 Docker 服務。將整個 Docker 存儲文件夾復制到另外一臺宿主主機,然后調整另外一臺宿主主機的配置即可。
### 如何進入 Docker 容器的網絡命名空間?
答:Docker 在創建容器后,刪除了宿主主機上 `/var/run/netns` 目錄中的相關的網絡命名空間文件。因此,在宿主主機上是無法看到或訪問容器的網絡命名空間的。
用戶可以通過如下方法來手動恢復它。
首先,使用下面的命令查看容器進程信息,比如這里的 1234。
```bash
$ docker inspect --format='{{. State.Pid}} ' $container_id
1234
```
接下來,在 `/proc` 目錄下,把對應的網絡命名空間文件鏈接到 `/var/run/netns` 目錄。
```bash
$ sudo ln -s /proc/1234/ns/net /var/run/netns/
```
然后,在宿主主機上就可以看到容器的網絡命名空間信息。例如
```bash
$ sudo ip netns show
1234
```
此時,用戶可以通過正常的系統命令來查看或操作容器的命名空間了。例如修改容器的 IP 地址信息為 `172.17.0.100/16`。
```bash
$ 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 接口對。
- 前言
- 修訂記錄
- 如何貢獻
- Docker 簡介
- 什么是 Docker
- 為什么要用 Docker
- 基本概念
- 鏡像
- 容器
- 倉庫
- 安裝 Docker
- Ubuntu
- Debian
- CentOS
- Raspberry Pi
- macOS
- Windows PC
- 鏡像加速器
- 使用鏡像
- 獲取鏡像
- 列出鏡像
- 刪除本地鏡像
- 利用 commit 理解鏡像構成
- 使用 Dockerfile 定制鏡像
- Dockerfile 指令詳解
- COPY 復制文件
- ADD 更高級的復制文件
- CMD 容器啟動命令
- ENTRYPOINT 入口點
- ENV 設置環境變量
- ARG 構建參數
- VOLUME 定義匿名卷
- EXPOSE 暴露端口
- WORKDIR 指定工作目錄
- USER 指定當前用戶
- HEALTHCHECK 健康檢查
- ONBUILD 為他人作嫁衣裳
- 參考文檔
- Dockerfile 多階段構建
- 其它制作鏡像的方式
- 實現原理
- 操作容器
- 啟動
- 守護態運行
- 終止
- 進入容器
- 導出和導入
- 刪除
- 訪問倉庫
- Docker Hub
- 私有倉庫
- 私有倉庫高級配置
- Nexus 3
- 數據管理
- 數據卷
- 掛載主機目錄
- 使用網絡
- 外部訪問容器
- 容器互聯
- 配置 DNS
- 高級網絡配置
- 快速配置指南
- 容器訪問控制
- 端口映射實現
- 配置 docker0 網橋
- 自定義網橋
- 工具和示例
- 編輯網絡配置文件
- 實例:創建一個點到點連接
- Docker 三劍客之 Compose 項目
- 簡介
- 安裝與卸載
- 使用
- 命令說明
- Compose 模板文件
- 實戰 Django
- 實戰 Rails
- 實戰 WordPress
- Docker 三劍客之 Machine 項目
- 安裝
- 使用
- Docker 三劍客之 Docker Swarm
- Swarm mode
- 基本概念
- 創建 Swarm 集群
- 部署服務
- 使用 compose 文件
- 管理敏感數據
- 管理配置信息
- 滾動升級
- 安全
- 內核命名空間
- 控制組
- 服務端防護
- 內核能力機制
- 其它安全特性
- 總結
- 底層實現
- 基本架構
- 命名空間
- 控制組
- 聯合文件系統
- 容器格式
- 網絡
- Etcd 項目
- 簡介
- 安裝
- 集群
- 使用 etcdctl
- CoreOS 項目
- 簡介
- 工具
- 快速搭建 CoreOS 集群
- Kubernetes 項目
- 簡介
- 快速上手
- 基本概念
- kubectl 使用
- 架構設計
- Mesos - 優秀的集群資源調度平臺
- Mesos 簡介
- 安裝與使用
- 原理與架構
- Mesos 配置項解析
- 日志與監控
- 常見應用框架
- 本章小結
- 容器與云計算
- 簡介
- 亞馬遜云
- 騰訊云
- 阿里云
- 小結
- 實戰案例-操作系統
- Busybox
- Alpine
- Debian Ubuntu
- CentOS Fedora
- 本章小結
- 實戰案例-CI/CD
- Drone
- Docker 開源項目
- LinuxKit
- 附錄
- 附錄一:常見問題總結
- 附錄二:熱門鏡像介紹
- Ubuntu
- CentOS
- MySQL
- MongoDB
- Redis
- Nginx
- WordPress
- Node.js
- 附錄三:Docker 命令查詢
- 附錄四:Dockerfile 最佳實踐
- 附錄五:資源鏈接
- 附錄六:Docker 中文資源