写在共享卷docker中

Ajo*_*uve 33 docker

我有一个带有php应用程序的docker

例如,我有一个分享量

/home/me/dev/site <=> /var/www/site
Run Code Online (Sandbox Code Playgroud)

我可以在我的主机上写一些东西,它会与容器同步

如果我发射

sudo docker exec test touch /var/www/site/test.txt
Run Code Online (Sandbox Code Playgroud)

有用

但是,如果我的服务器正在尝试创建一个文件,因为www-data这是因为权限不起作用.

有没有办法让我的共享卷访问www-data

我正在使用boot2docker

tha*_*tah 63

Docker中的(绑定安装的)卷将保留在Docker主机上设置的权限.您可以使用它来设置这些文件和目录的权限,然后在容器中使用它们.

一些背景 ;

Linux中的权限基于用户和组ID('uid'/ 'gid').即使你看到一个用户和组的名称作为所有者,这些名字是不是在Linux的真正重要的是,他们只是在那里让你更容易,看看谁是一个文件的拥有者(他们是从查找/etc/passwd文件) .

您可以在文件上设置任何 uid/gid; 设置这些权限时,用户不必存在.例如;

touch foobar && sudo chown 1234:5678 foobar && ls -la foobar

# UID and GID are set to 1234 / 5678, even though there's no such user
-rw-rw-r-- 1 1234 5678 0 Mar 25 19:14 foobar
Run Code Online (Sandbox Code Playgroud)

检查权限(容器内部和外部)

如上所述,Docker在使用卷时维护主机的所有权.此示例显示卷中的权限和所有权在容器外部内部是相同的;

# (First create a dummy site)

mkdir -p volume-example/site && cd volume-example
echo "<html><body>hello world</body></html>" > site/index.html

# Permissions on the Docker host;

ls -n site

# total 4
# -rw-rw-r-- 1 1002 1002 38 Mar 25 19:15 index.html

# And, permissions inside a nginx container, using it as volume;

sudo docker run --rm -v $(pwd)/site:/var/www nginx ls -n /var/www

# total 4
# -rw-rw-r-- 1 1002 1002 38 Mar 25 19:15 index.html
Run Code Online (Sandbox Code Playgroud)

设置权限

如上所述,用户不必存在才能使用它们,因此即使我们www-data在Docker主机上没有用户,如果我们知道"uid"和"gid",我们仍然可以设置正确的权限.容器内的那个用户;

让我们看看www-data用户的uid和gid 在容器是什么;

sudo docker run --rm nginx id www-data

# uid=33(www-data) gid=33(www-data) groups=33(www-data)
Run Code Online (Sandbox Code Playgroud)

首先更改权限之前检查状态.这次我们以用户身份运行nginx容器www-data;

sudo docker run \
  --rm \
  --volume $(pwd)/site:/var/www \
  --user www-data nginx touch /var/www/can-i-write.txt

# touch: cannot touch `/var/www/can-i-write.txt': Permission denied
Run Code Online (Sandbox Code Playgroud)

接下来,在本地目录上设置权限,看看我们是否能够写入;

sudo chown -R 33:33 site

sudo docker run \
   --rm \
   --volume $(pwd)/site:/var/www \
   --user www-data nginx touch /var/www/can-i-write.txt
Run Code Online (Sandbox Code Playgroud)

成功!

  • 这是一个很好的解释,谢谢。但是如果我们想在主机上和容器内使用不同的 UID/GID 怎么办?例如,`33` 可能是容器内的合法用户,但可能是主机上的“恶人”。此外,我希望所有文件都属于我在主机上的用户帐户,而不是某些神秘用户“33”。 (6认同)
  • 谢谢,你救了我的一天,它在 linux 上运行良好。但是它在带有 docker-machine 的 Osx 上不起作用。有什么建议吗? (2认同)
  • &gt; 我认为最好以另一种方式进行:设置容器的 uid 以匹配主机的 uid 或使用 linux 上的“docker”组 不应使用 `docker` 组,因为它提供访问权限到 docker 套接字(API 访问)。至于匹配容器以当前用户身份运行;这里描述的场景对于开发情况最有用(处理容器外部的文件,但授予容器访问权限),但是, (2认同)
  • 使容器的用途与设计运行时不同,将使您的开发情况与生产情况差异更大(您不应该在生产中使用绑定安装),这可能会导致其他麻烦。 (2认同)

Ist*_*tei 29

将以下行添加到dockerfile并重建映像

RUN usermod -u 1000 www-data
RUN usermod -G staff www-data
Run Code Online (Sandbox Code Playgroud)

  • 完善!这就是我一直在寻找的东西.这个命令的http://linux.die.net/man/8/usermod docs.基本上,www-data的用户ID更改为1000,并将其添加到员工组.为什么1000或员工?运行`docker exec -it CONTAINER_NAME_OR_ID bash`一旦运行`ls -la/var/www`,你会看到ex.`drwxr-xr-x 1 1000名工作人员238 8月20日20:14 html` (3认同)

Ngu*_*ơng 5

我从上面的答案中注意到,即使容器对已安装的卷具有写入权限,但从外部,您无法修改容器创建的文件。

是我发现最好的解决方案。

首先,将其添加到您的 Dockerfile 中

ARG USER_ID
ARG GROUP_ID

RUN addgroup --gid $GROUP_ID user
RUN adduser --disabled-password --gecos '' --uid $USER_ID --gid $GROUP_ID user
USER user
Run Code Online (Sandbox Code Playgroud)

然后在构建图像时使用它

docker build -t myimage \
  --build-arg USER_ID=$(id -u) \
  --build-arg GROUP_ID=$(id -g) .
Run Code Online (Sandbox Code Playgroud)

基本上,这会将容器内部的用户与容器外部的用户同步,以便他们对已安装的卷具有相同的权限。不需要吃东西。

注意:这类似于 VSCode 的方法,使外部用户可以访问 devcontainer 内创建的文件。您可以查看 devcontainer 的构建日志以获取更多详细信息。