1、问题背景
在启动服务时,docker compose 涉及文件挂载。相关文件最初由宿主机挂载到 Runner 容器中,然后在 docker-compose.yml 中再次挂载到业务容器。
在宿主机直接执行 docker compose 启动服务一切正常,但在 Runner 容器中执行时,就会报以下错误。
2、报错
1
|
Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error mounting "/home/xxx/client/conf/nginx.conf" to rootfs at "/etc/nginx/nginx.conf": create mountpoint for /etc/nginx/nginx.conf mount: cannot create subdirectories in "/var/lib/docker/overlay2/be07c226551b939ab5c47865c441c289bba7f26e7a449ef8610f5399e7ec2fda/merged/etc/nginx/nginx.conf": not a directory: unknown: 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
|
3、chatgpt给的方案
方案 1:路径一致化
确保 Runner 容器挂载的路径 和 宿主机路径 完全一致。
比如宿主机上有:
1
|
/srv/ci-data/nginx.conf
|
启动 Runner 容器时:
1
|
docker run -v /srv/ci-data:/srv/ci-data gitlab-runner
|
那么 docker-compose.yml 里用:
1
2
|
volumes:
- /srv/ci-data/nginx.conf:/etc/nginx/nginx.conf:ro
|
这样 Docker daemon 解析路径时就能找到正确的文件。
方案 2:把文件做成 Volume
不要直接 bind-mount 宿主机路径,而是:
1
2
|
docker volume create nginx_conf
docker run -v nginx_conf:/etc/nginx ...
|
这样路径类型和内容不会依赖宿主机真实文件结构,避免类型冲突。但缺点是调试不如 bind mount 方便。
4、解决
通过使用方案1成功解决了如上问题。
另外一个小办法
- 在
docker-compose.yml中先不挂载
docker compose起了服务后,通过命令拷贝到对应的业务容器,然后重启业务
示例
原先的挂载
1
2
3
4
|
volumes:
- "$PWD/conf/nginx.conf:/etc/nginx/nginx.conf"
- "$PWD/conf/xxx.pem:/etc/nginx/xxx.pem"
- "$PWD/conf/xxx.key:/etc/nginx/xxx.key"
|
删除这部分挂载,直接docker compose启动,然后拷贝
1
2
3
4
|
docker cp ./conf/nginx.conf <container_name>:/etc/nginx/nginx.conf
docker cp ./conf/xxx.pem <container_name>:/etc/nginx/xxx.pem
docker cp ./conf/xxx.key <container_name>:/etc/nginx/xxx.key
docker exec <container_name> nginx -s reload
|