这是一个最小的docker-compose.yml
:
version: "3.6"
services:
foo:
user: "${UID}:${GID}"
image: node:latest
container_name: foo
working_dir: /var/www/foo
volumes:
- bar:/var/www/foo/bar
volumes:
bar:
运行docker-compose up
后,命名卷将在/var/lib/docker/volumes/project_bar
处创建,并且project_bar
目录由 root
所有 - 这很好。尽管其中的_data
目录也由root
拥有 - 我希望它由特定的非root用户拥有。
例如:
docker-compose run --rm foo sh -c "mkdir bar/foo"
将失败,并显示mkdir:无法创建目录“bar/foo”:权限被拒绝
。
我的印象是指定 user: "${UID}:${GID}"
(注意:uid
/gid
可供docker
使用,在shell中导出)将解决这个问题。显然我错了。
有没有办法让 /var/lib/docker/volumes/project_bar/_data
由特定用户拥有?如果可能的话,不要chown
'ing任何东西。并且不涉及 Dockerfile
。
编辑:澄清一下,我希望容器中的 /var/www/foo/bar
以及 /var/lib/docker/中的等效项卷
由特定用户而非 root 用户拥有。
最佳答案
您要么涉及 Dockerfile,要么需要使用单独的进程设置卷。命名卷将使用镜像的内容进行初始化,包括文件、目录、所有者和权限。当卷为空或不存在时会发生这种情况。
所以你的选择包括:
- 更新镜像以包含该目录所需的所有权。请注意,如果图像将其定义为卷,则您的更改必须先于该定义。
- 提前创建一个具有所需所有权的卷并将其安装到容器中
- 修改容器的入口点以 root 身份运行,修复权限,然后切换到所需的用户(使用 gosu 等)
扩展第二个选项,您可以通过运行临时容器来执行任务来创建具有所需所有权和内容的卷:
docker container run --rm -v bar-data:/data busybox /bin/sh -c \
"touch /data/.initialized && chown -R ${UID}:${GID} /data"
然后在您的撰写文件中,您可以将该卷声明为外部卷:
version: "3.6"
services:
foo:
user: "${UID}:${GID}"
image: node:latest
container_name: foo
working_dir: /var/www/foo
volumes:
- bar:/var/www/foo/bar
volumes:
bar:
# tell compose this volume is externally created with a different name
external: true
name: bar-data
这将创建一个包含单个文件的卷,需要防止 docker 从镜像内容中重新初始化空卷。这也意味着您需要在卷中加载所需的任何数据,否则卷将是空的。将数据复制到卷的常见方法是使用 tar:
tar -cC source_dir . | \
docker run --rm -i -v foo-data:/target busybox tar -xC /target
关于docker-compose:以特定用户身份创建命名卷,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61250908/