如何管理挂载到Docker容器中的卷的权限?

6
我正在开发一个WordPress主题,并希望在我的开发设置中使用Docker。我的操作非常简单,具体如下:
  • 创建运行MySQL 5.7的 database 服务
  • 创建 wordpress 服务,其中我将我的主题文件夹挂载为卷到/var/www/html/wp-content/themes
然而,我遇到了卷权限方面的问题。
我正在处理以下项目文件夹结构:
.
├── docker-compose.yml
└── my-theme

docker-compose.yml文件如下:

version: '3.2'

services:
  database:
    image: mysql:5.7
    volumes:
      - my_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: root

  wordpress:
    depends_on:
      - database
    image: wordpress:php7.3-apache
    ports:
      - '8000:80'
    restart: always
    environment:
      WORDPRESS_DB_HOST: database:3306
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: root
    working_dir: /var/www/html
    volumes:
      - type: volume
        source: ./my-theme
        target: /var/www/html/wp-content/themes/my-theme
volumes:
  my_data: {}

当我运行docker-compose up时,一切都如预期般工作:容器被创建,并且我可以在浏览器中访问WordPress。然而,当我激活安装的主题时,我挂载为卷的主题没有呈现任何内容。
当我使用docker-compose exec wordpress sh命令进入wordpress容器时,我发现wp-content/themes文件夹的所有者是root。因此,我认为这就是问题所在。
我手动递归地运行chown命令将容器中的wp-content文件夹所有权更改后,验证了这是权限问题。
chown -R www-data:www-data /var/www/html/wp-content

完成以上步骤后,我的主题按预期呈现。因此,我正在寻找一种避免进行chown进程的方法(这个想法是任何其他开发人员都可以克隆这个项目,只需运行docker-compose up并开始工作)。

我尝试的第一件事是创建一个Dockerfile,在其中构建一个稍微定制的Wordpress镜像:

FROM wordpress:php7.3-apache
RUN mkdir -p /var/www/html/wp-content/themes/test-theme \
  && chown -R /var/www/html/wp-content

我这么做的原因是事先创建目录并将其chown,以便卷会继承用户:组映射。可惜的是,这是不可能的;挂载卷会覆盖此映射并将其设置回root:root

之后,我尝试在docker-compose.yml文件中设置APACHE_RUN_USERAPACHE_RUN_GROUP环境变量:

version: '3.2'

services:
  database:
    ...

  wordpress:
    ...
    environment:
      WORDPRESS_DB_HOST: database:3306
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: root
      APACHE_RUN_USER: '$(id -u)'
      APACHE_RUN_GROUP: '$(id -g)'
    working_dir: /var/www/html
    volumes:
      - type: volume
        source: ./my-theme
        target: /var/www/html/wp-content/themes/my-theme
volumes:
  my_data: {}

然而,在构建过程中出现了一堆apache错误。

我有点迷茫了。有没有最佳实践来管理Docker中挂载卷的权限?我已经搜索了很多相关的内容,但找到的解决方案有些超出我的理解范围。


你面临的Apache错误是什么?我怀疑'$(id -u)'是错误的,因为Shell变量在单引号之间不会被评估,尽管我不确定这是否适用于此处。除此之外,在Dockerfile中执行chown是完全合法的(这里是一个讨论此问题的GitHub问题)。 - bellackn
实际上,我也认为在Dockerfile中执行chown就可以解决问题(基于您提供的同一GH问题),但是一旦我挂载卷,权限就会被覆盖并设置回root:root。 我通过在wordpress服务中使用和不使用volumes键来测试docker-compose up。当我进入没有挂载卷的容器时,ls -l显示wp-content文件夹的www-data:www-data。一旦我挂载卷,ls -l显示root:root... - idix
2个回答

11

您可以通过覆盖WordPress镜像的入口点来完成此操作。

在您的项目中创建一个名为startup.sh的文件,并使其可执行:

#!/bin/bash

chown -R www-data:www-data /var/www/html/wp-content
docker-entrypoint.sh apache2-foreground

然后在你的 docker-compose.yml 文件中:

...
  wordpress:
...
    working_dir: /var/www/html
    volumes:
        - './my-theme:/var/www/html/wp-content/themes/my-theme'
        - './startup.sh:/startup.sh'
    entrypoint: /startup.sh

这对我有用,如果你在实施过程中遇到问题,请告诉我。


2
稍等,我说得太早了。Wordpress容器的构建比平常延迟了一些,但最终还是成功了。现在它正常运行!感谢你的帮助。 - idix

1

向ChatGPT询问问题,它解决了问题。

FROM php:8.0-apache

# Create a www-data user with the same UID and GID as the host user
ARG WWW_DATA_UID=1000
ARG WWW_DATA_GID=1000
RUN usermod -u $WWW_DATA_UID www-data && groupmod -g $WWW_DATA_GID www-data

# Rest of the Dockerfile...

通过在容器内设置www-data用户的UID和GID与主机相同的值,挂载文件和目录的所有权现在应正确地反映出www-data用户。
version: "3.9"

services:
    wordpress:
        build:
            context: .
        ports:
            - 80:80
        volumes:
            - ./src:/var/www/html:rw
        user: www-data

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接