附录A 常见问题总结

A.1 镜像相关

1.如何批量清理临时镜像文件?

答:可以使用docker rmi $(docker images -q -f dangling=true)命令。

2.如何查看镜像支持的环境变量?

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

3.本地的镜像文件都存放在哪里?

答:与Docker相关的本地资源都存放在/var/lib/docker/目录下,以aufs文件系统为例,其中container目录存放容器信息,graph目录存放镜像信息,aufs目录下存放具体的镜像层文件。

4.构建Docker镜像应该遵循哪些原则?

答:整体原则上,尽量保持镜像功能的明确和内容的精简,要点包括:

·尽量选取满足需求但较小的基础系统镜像,例如大部分时候可以选择debian:wheezy或debian:jessie镜像,仅有不足百兆大小;

·清理编译生成文件、安装包的缓存等临时文件;

·安装各个软件时候要指定准确的版本号,并避免引入不需要的依赖;

·从安全角度考虑,应用要尽量使用系统的库和依赖;

·如果安装应用时候需要配置一些特殊的环境变量,在安装后要还原不需要保持的变量值;

·使用Dockerfile创建镜像时候要添加.dockerignore文件或使用干净的工作目录。

5.碰到网络问题,无法pull镜像,命令行指定http_proxy无效,怎么办?

答:在Docker配置文件中添加export http_proxy="http://<PROXY_HOST>:<PROXY_PORT>",之后重启Docker服务即可。

A.2 容器相关

1.容器退出后,通过docker ps命令查看不到,数据会丢失么?

答:容器退出后会处于终止(exited)状态,此时可以通过docker ps –a命令查看。其中的数据也不会丢失,还可以通过docker start命令来启动它。只有删除掉容器才会清除所有数据。

2.如何停止所有正在运行的容器?

答:可以使用docker kill $(docker ps -q)命令。

3.如何清理批量后台停止的容器?

答:可以使用docker rm -f $(docker ps -qa)命令。

4.如何获取某个容器的PID信息?

答:可以使用docker inspect —format '{{ .State.Pid }}'<CONTAINERID or NAME>命令。

5.如何获取某个容器的IP地址?

答:可以使用docker inspect —format '{{ .NetworkSettings.IPAddress }}'<CONTAINER ID orNAME>命令。

6.如何给容器指定一个固定IP地址,而不是每次重启容器IP地址都会变?

答:目前Docker并没有提供直接的对容器IP地址的管理支持,用户可以参考本书第20章“网络配置”中介绍的创建点对点连接例子,来手动配置容器的静态IP。或者在启动容器后,再手动进行修改。还可参考后面“其他”类的问题:“如何进入Docker容器的网络命名空间?”

7.如何临时退出一个正在交互的容器的终端,而不终止它?

答:按Ctrl-p Ctrl-q。如果按Ctrl-c往往会让容器内应用进程终止,进而会终止容器。

8.使用docker port命令映射容器的端口时,系统报错“Error:No public port '80' published for xxx”,怎么办?

答:创建镜像时Dockerfile要通过EXPOSE命令指定正确的开放端口;容器启动时指定PublishAllPort=true。

9.可以在一个容器中同时运行多个应用进程么?

答:一般并不推荐在同一个容器内运行多个应用进程。如果有类似需求,可以通过一些额外的进程管理机制,比如supervisord来管理所运行的进程。可以参考https://docs.docker.com/articles/using_supervisord/

10.如何控制容器占用系统资源(CPU、内存)的份额?

答:在使用docker create命令创建容器或使用docker run创建并启动容器的时候,可以使用-c|—cpu-shares[=0]参数来调整容器使用CPU的权重;使用-m|—memory[=MEMORY]参数来调整容器使用内存的大小。

A.3 仓库相关

1.仓库(Repository)、注册服务器(Registry)、注册索引(Index)之间有何关系?

首先,仓库是存放一组关联镜像的集合,比如同一个应用的不同版本的镜像。注册服务器是存放实际的镜像文件的地方。注册索引负责维护用户的账号、权限、搜索、标签等的管理。因此,注册服务器利用注册索引来实现认证等管理。

2.从非官方仓库(例如non-official-repo.com)下载镜像时候,有时候会提示“Error:Invalid registry endpoint https://non-official-repo.com/v1/……”,怎么办?

答:Docker自1.3.0版本往后,加强了对镜像安全性的验证,需要添加私有仓库证书,或者手动添加对非官方仓库的信任。编辑Docker配置文件,在其中添加:DOCKER_OPTS="—insecure-registry non-official-repo"之后,重启Docker服务即可。

A.4 配置相关

1.Docker的配置文件放在哪里,如何修改配置?

答:使用upstart的系统(如Ubuntu 14.04)的配置文件在/etc/default/docker,使用systemd的系统(如Ubuntu 16.04、Centos等)的配置文件在/etc/systemd/system/docker.service.d/docker.conf。

Ubuntu下面的配置文件内容如下,读者可以参考配。(如果出现该文件不存在的情况,重启或者自己新建一个文件都可以解决。)


  1. # Customize location of Docker binary (especially for development testing).
  2. #DOCKERD="/usr/local/bin/dockerd"
  3. # Use DOCKER_OPTS to modify the daemon startup options.
  4. #DOCKER_OPTS="--dns 8.8.8.8 --dns 8.8.4.4"
  5. # If you need Docker to use an HTTP proxy, it can also be specified here.
  6. #export http_proxy="http://127.0.0.1:3128/"
  7. # This is also a handy place to tweak where Docker's temporary files go.
  8. #export TMPDIR="/mnt/bigdrive/docker-tmp"

2.如何更改Docker的默认存储位置?

答:Docker的默认存储位置是/var/lib/docker,如果希望将Docker的本地文件存储到其他分区,可以使用Linux软连接的方式来完成,或者在启动daemon时通过-g参数指定。

例如,如下操作将默认存储位置迁移到/storage/docker。


  1. [root@s26 ~]# df -h
  2. Filesystem Size Used Avail Use% Mounted on
  3. /dev/mapper/VolGroup-lv_root 50G 5.3G 42G 12% /
  4. tmpfs 48G 228K 48G 1% /dev/shm
  5. /dev/sda1 485M 40M 420M 9% /boot
  6. /dev/mapper/VolGroup-lv_home 222G 188M 210G 1% /home
  7. /dev/sdb2 2.7T 323G 2.3T 13% /storage
  8. [root@s26 ~]# service docker stop
  9. [root@s26 ~]# cd /var/lib/
  10. [root@s26 lib]# mv docker /storage/
  11. [root@s26 lib]# ln -s /storage/docker/ docker
  12. [root@s26 lib]# ls -la docker
  13. lrwxrwxrwx. 1 root root 15 1117 13:43 docker -> /storage/docker
  14. [root@s26 lib]# service docker start

3.使用内存和swap限制启动容器时候收到警告:“WARNING:Your kernel does not support cgroup swap limit.WARNING:Your kernel does not support swap limit capabilities.Limitation discarded.”,怎么办?

答:这是因为系统默认没有开启对内存和swap使用的统计功能,引入该功能会带来性能的下降。要开启该功能,可以采取如下操作:

1)编辑/etc/default/grub文件(Ubuntu系统为例),配置GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1";

2)更新grub:$sudo update-grub;

3)重启系统即可。

A.5 Docker与虚拟化

1.Docker与LXC(Linux Container)有何不同?

答:LXC利用Linux上相关技术实现了容器。Docker则在如下的几个方面进行了改进:

·移植性:通过抽象容器配置,容器可以实现从一个平台移植到另一个平台;

·镜像系统:基于AUFS的镜像系统为容器的分发带来了很多的便利,同时共同的镜像层只需要存储一份,实现高效率的存储;

·版本管理:类似于Git的版本管理理念,用户可以更方便地创建、管理镜像文件;

·仓库系统:仓库系统大大降低了镜像的分发和管理的成本;

·周边工具:各种现有工具(配置管理、云平台)对Docker的支持,以及基于Docker的PaaS、CI等系统,让Docker的应用更加方便和多样化。

2.Docker与Vagrant有何不同?

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

Vagrant类似Boot2Docker(一款运行Docker的最小内核),是一套虚拟机的管理环境。Vagrant可以在多种系统上和虚拟机软件中运行,可以在Windows、Mac等非Linux平台上为Docker提供支持,自身具有较好的包装性和移植性。

原生的Docker只能运行在Linux平台上,但启动和运行的性能都比虚拟机要快,往往更适合快速开发和部署应用的场景。

简单说:Vagrant适合用来管理虚拟机,而Docker适合用来管理应用环境。

3.开发环境中Docker和Vagrant该如何选择?

答:Docker不是虚拟机,而是进程隔离,对于资源的消耗很少,但是目前需要Linux环境支持。Vagrant是虚拟机上做的封装,虚拟机本身会消耗资源。

如果本地使用的是Linux环境,推荐都使用Docker。

如果本地使用的是OSX或者Windows环境,那就需要开虚拟机,单一开发环境下Vagrant更简单;多环境开发下推荐在Vagrant里面再使用Docker进行环境隔离。

A.6 其他

1.Docker能在非Linux平台(比如Windows或MacOS)上运行么?

答:可以。目前需要使用docker for mac、boot2docker等软件创建一个轻量级的Linux虚拟机层。

2.如何将一台宿主主机的docker环境迁移到另外一台宿主主机?

答:停止Docker服务。将整个Docker存储文件夹复制到另外一台宿主主机,然后调整另外一台宿主主机的配置即可。

3.如何进入Docker容器的网络命名空间?

答:Docker在创建容器后,删除了宿主主机上/var/run/netns目录中的相关网络命名空间文件。因此,在宿主主机上是无法看到或访问容器的网络命名空间的。用户可以通过如下方法来手动恢复它:

1)使用下面的命令查看容器进程信息,比如这里的1234:


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

2)在/proc目录下,把对应的网络命名空间文件链接到/var/run/netns目录。


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

3)在宿主主机上就可以看到容器的网络命名空间信息。例如:


  1. $ sudo ip netns show
  2. 1234

此时,用户可以通过正常的系统命令来查看或操作容器的命名空间了。例如修改容器的IP地址信息为172.17.0.100/16:


  1. $ sudo ip netns exec 1234 ifconfig eth0 172.17.0.100/16