Docker常见问题整理

2022-09-07 13:09:44

镜像相关


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

答:可以使用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 --subnet172.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] 参数来调整容器使用内存的大小


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

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


docker -v挂载文件时遇到的坑

  • 挂载分为文件挂载和目录挂载
  • 文件挂载时,宿主机需要自己提前创建好文件,不然会出问题。自己不创建文件的话 执行完命令后会将它创建成目录
  • 挂载目录时 可以不自己创建目录,会根据目录的挂载路径将 容器内的目录下的文件夹拷贝过来
  • 挂载成功后,如果修改挂载文件的内容,容器内的文件不会实时更新,需要重启容器。如果修改的是挂载目录下的文件,则会实时更新,所以推荐挂载目录

Docker volume 挂载时文件或文件夹不存在

docker volume 可以使我们在启动docker容器时,动态的挂载一些文件(如配置文件), 以覆盖镜像中原有的文件,但是,挂载一个主机上尚不存在的文件夹或者文件到容器中会怎样呢?

文件夹挂载

docker在文件夹挂载上的行为是统一的,具体表现为:

若文件夹不存在,则先创建出文件夹(若为多层文件夹,则递归创建)

用host上的文件夹内容覆盖container中的文件夹内容

docker run-v/path-to-folder/A:/path-to-folder/B test-image

详细说明如下:

host上文件夹存在,且非空

hostcontainermount result
存在的非空文件夹A不存在的文件夹B先在contanier中创建文件夹B,再将A文件夹中的所有文件copy到B中
存在的非空文件夹A存在的非空文件夹B先将container中文件夹B的原有内容清空,再将A中文件copy到B中

无论container中的文件夹B是否存在, A都会完全覆盖B的内容

host上文件夹存在,但为空

hostcontainermount result
存在的空文件夹A存在的非空文件夹Bcontainer中文件夹B的内容被清空

container中对应的文件夹内容被清空

host上文件夹不存在

hostcontainermount result
不存在的文件夹A存在的非空文件夹B在host上创建文件夹A,container中文件夹B的内容被清空
不存在的文件夹A/B/C存在的非空文件夹B在host上创建文件夹A/B/C,container中文件夹B的内容被清空

container中对应的文件夹内容被清空

总结

host上文件夹一定会覆盖container中文件夹:

hostcontainermount result
文件夹不存在/文件夹存在但为空文件夹不存在/存在但为空/存在且不为空container中文件被覆盖(清空)
文件夹存在且不为空文件夹不存在/存在但为空/存在且不为空container中文件夹内容被覆盖(原内容清空, 覆盖为host上文件夹内容)

文件挂载

文件挂载与文件夹挂载最大的不同点在于:

  • docker 禁止用主机上不存在的文件挂载到container中已经存在的文件
  • 文件挂载不会对同一文件夹下的其他文件产生任何影响

除此之外, 其覆盖行为与文件夹挂载一致,即:

  • 用host上的文件的内容覆盖container中的文件的内容
docker run -v /path-to-folder/non-existent-config.js:/path-to-folder/config.js test-image# forbidden

详细说明如下:

host上文件不存在

hostcontainermount result
不存在的文件configA.js已经存在的文件congfigB.js报错,Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type. 同时会在host上生成两个空目录 configA.js 和 configB.js, 但是container无法启动

host上文件存在

hostcontainermount result
存在的文件configA.js存在的文件congfigB.jscontainer中文件名configB.js保持不变,但是文件内容被congfigA.js的内容覆盖了
存在的文件configA.js不存在的文件congfigB.jscontainer中新建一个文件configB.js,其内容为configA.js的文件内容, configB.js所在文件下的所有其他文件维持不变

总结

host上文件一定会覆盖container中文件夹

hostcontainermount result
不存在的文件已经存在的文件禁止行为
存在的文件不存在的文件/已经存在的文件新增/覆盖 (若目录不存在则会创建目录)

结论

文件夹挂载

  • 允许不存在的文件夹或者存在的空文件夹挂载进container, container中对应的文件夹将被清空
  • 非空文件夹挂载进container将会覆盖container中原有文件夹

文件挂载

  • 禁止将不存在的文件挂载进container中已经存在的文件上
  • 存在的文件挂载进container中将会覆盖container中对应的文件, 若文件不存在则新建

应用场景

  1. 从上面的分析可知,文件夹挂载以整个文件夹为单位进行文件覆盖,故可在需要将大量文件挂载进container时使用,另外,如果挂载一个空文件夹或者不存在的文件夹,一般是做逆向使用: 即容器启动后,可能会在容器内挂载点的文件夹下生成一些文件(如日志),此时,在对应的host上的文件夹内就能直接看到。
  2. 文件挂载由于只会覆盖单个文件而不会影响container中同一文件夹下的其他文件,常常被用来挂载配置文件,以在运行时,动态的修改默认配置。
  • 作者:大忽悠爱忽悠
  • 原文链接:https://cjdhy.blog.csdn.net/article/details/123240348
    更新时间:2022-09-07 13:09:44