Nag*_*gev 0 docker docker-compose
使用docker-compose,使用 Nginx 基础映像中存在的目标目录安装卷可以按预期工作。docker-compose up但是,当挂载目标是在派生映像中创建的子目录时,我收到错误。这是错误的要点:
\n\n将“newdir”安装到“/usr/share/nginx/html/newdir”处的rootfs导致:\ nmkdir newdir:只读文件系统:未知
\n
我不明白为什么它似乎在尝试创建已经存在的目录( newdir )!
\n完整错误如下:
\nERROR: for test_nginx_1 Cannot start service nginx: OCI runtime create failed: container_linux.go:380: starting container process caused: process_linux.go:545: container init caused: rootfs_linux.go:76: mounting "/home/user/test/newdir" to rootfs at "/usr/share/nginx/html/newdir" caused: mkdir /var/lib/docker/overlay2/accdaa147d7825a7d2c71b68f76e0b8663d00f6e46fcfb5c0ec32ada8baf85af/merged/usr/share/nginx/html/newdir: read-only file system: unknown\n\nERROR: for nginx Cannot start service nginx: OCI runtime create failed: container_linux.go:380: starting container process caused: process_linux.go:545: container init caused: rootfs_linux.go:76: mounting "/home/user/test/newdir" to rootfs at "/usr/share/nginx/html/newdir" caused: mkdir /var/lib/docker/overlay2/accdaa147d7825a7d2c71b68f76e0b8663d00f6e46fcfb5c0ec32ada8baf85af/merged/usr/share/nginx/html/newdir: read-only file system: unknown.\nRun Code Online (Sandbox Code Playgroud)\n这是docker-compose.yml:
\nversion: '3'\nservices:\n nginx:\n image: local/mynginx:withsubdir\n volumes:\n - ./html:/usr/share/nginx/html:ro\n - ./newdir:/usr/share/nginx/html/newdir\nRun Code Online (Sandbox Code Playgroud)\n上面的图像local/mynginx:withsubdir是使用以下Dockerfile构建的:
FROM docker.io/library/nginx:1.21\nRUN mkdir /usr/share/nginx/html/newdir && ls -lah /usr/share/nginx/html/newdir\nRun Code Online (Sandbox Code Playgroud)\n我验证了我可以安装该卷并使用 docker 查看其内容:
\n$ docker run --rm -ti -v /home/user/test/newdir:/usr/share/nginx/html/newdir local/mynginx:withsubdir bash\nroot@7db709476271:/# ls /usr/share/nginx/html/newdir\nhallo.imhere\nRun Code Online (Sandbox Code Playgroud)\n所以这个问题似乎是docker-compose特有的。如果我删除docker-compose.yml中的最后一行,则docker-compose up启动成功。如何挂载在派生映像中创建的目录?谢谢。
顺便说一句,我原来的docker-compose.yml更长,并且它有一个构建步骤,指向创建该新目录的Dockerfile。但我在故障排除时创建了这个较小的复制器,并且我使用以下命令手动构建了新图像:
\ndocker build . -t local/mynginx:withsubdir\nRun Code Online (Sandbox Code Playgroud)\n我在两个不同的环境( Docker 版本 20.10.7,构建 20.10.7-0ubuntu1~20.04.1和Docker 版本 20.10.12,构建 e91ed5707e )中遇到相同的错误,无论有或没有:ro.
我的test目录文件:
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 docker-compose.yml\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 Dockerfile\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 html\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 index.html\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 newdir\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 hallo.imhere\nRun Code Online (Sandbox Code Playgroud)\n我做了一些在线研究,但找不到任何解决方案。
\nDocker 尝试在只读目录中创建挂载点,但失败。
正常的 Linux mount (8) 调用和底层的mount (2) 系统调用将某些文件系统挂载到某些现有目录上。Linux 绑定挂载是一种特殊情况,其中挂载的文件系统也是现有目录,并且 Docker 绑定挂载使用相同的机制。
一般来说,在 Docker 中,如果任何类型的挂载目标尚不存在,Docker 都会将其创建为一个新的空目录。通常这是在容器文件系统中,但如果您尝试在其他类型的已安装卷中安装卷,则安装点将在外部卷中创建。
演示这一点的一种简单方法是使用简单docker run命令,在其中安装外部卷和内部卷,但外部卷实际上是绑定安装:
# Create a new empty local "outer" directory
rm -rf outer
mkdir outer
# Create a new empty container...
docker run --rm \
-v "$PWD/outer:/outer" \ # bind-mounting the outer directory
-v inner:/outer/inner \ # mounting a named volume within that
busybox \ # running any image
ls /outer # and a command that exits immediately
# Look inside the host directory, and an empty `inner` directory will exist
ls ./outer
# Clean up
docker volume rm inner
rm -rf outer
Run Code Online (Sandbox Code Playgroud)
(这与Why does docker createempty node_modules and how to避免它?的机制相同。)
现在,考虑到这些机制,您已经告诉 Docker 将外部目录挂载为只读,并且它确实这样做了。那么newdir容器文件系统中不存在该目录,因此 Docker 尝试将其创建为挂载点,但它不能,因为该目录位于只读文件系统中。这就是你得到的错误。
对于纯 Docker 卷,一些可能的解决方法是:
在启动容器之前在主机文件系统上创建挂载点
mkdir ./html/newdir
docker-compose up -d
Run Code Online (Sandbox Code Playgroud)
不要将外部目录挂载为只读
volumes:
- ./html:/usr/share/nginx/html # not ...:ro
Run Code Online (Sandbox Code Playgroud)
将内部目录安装在其他地方,就像您在答案中所做的那样
volumes:
- ./html:/usr/share/nginx/html:ro
- ./newdir:/usr/share/nginx/newdir:ro # not under .../html
Run Code Online (Sandbox Code Playgroud)
更好的答案仍然可能是完全避免这里的交易量。在 Dockerfile 中,您可以COPY将此内容添加到您的映像中。由于容器文件系统与主机隔离,因此消除了容器修改主机文件的风险,并且您可以在 Dockerfile 中根据需要重组内容。这也意味着您可以在另一个系统上运行该映像,而无需拥有要在那里提供的文件的副本。
FROM nginx
COPY html/ /usr/share/nginx/html/
COPY newdir/ /usr/share/nginx/html/newdir/
# no need to repeat base image's EXPOSE or CMD
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2901 次 |
| 最近记录: |