如何使用官方WordPress Docker Compose镜像修复wp-content文件权限

29

问题


我使用来自Docker存储库的官方WordPress映像和docker-compose设置WordPress本地环境。

我在Windows上操作。

问题是我的wp-content存在权限问题,因此我无法从WordPress管理面板上传文件。 wordpress error unable to create directory

已经尝试过的方法


我检查了容器内的文件权限,并得到以下输出:

file permissions in the wordpress container

如您所见,我的wp-content所有者是root而不是www-data

立即解决方案是打开容器的bash并输入:
chown -R www-data:www-data /var/www/html/wp-content/

当然,这样做有效,但我不想每次启动新的WordPress项目时都要执行此过程。为此,我已创建了一个像这样的Dockerfile

FROM wordpress:5.1.1

# install dos2unix (fix problem between CRLF and LF)
RUN apt-get update
RUN apt-get install -y dos2unix

# increase upload limit
RUN touch /usr/local/etc/php/conf.d/uploads.ini \
    && echo "upload_max_filesize = 10M;" >> /usr/local/etc/php/conf.d/uploads.ini

# fix permissions issues
COPY entrypoint.sh /
RUN dos2unix /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

我的entrypoint.sh看起来像这样:

#!/bin/bash
echo Fixing permissions...
chown -R www-data:www-data /var/www/html/wp-content/

但后来我意识到我覆盖了原始WordPress镜像的ENTRYPOINT,导致容器总是以代码0退出。

然后我尝试使用CMD代替ENTRYPOINT,并将Dockerfile更改如下:

FROM wordpress:5.1.1

# increase upload limit
RUN touch /usr/local/etc/php/conf.d/uploads.ini \
    && echo "upload_max_filesize = 10M;" >> /usr/local/etc/php/conf.d/uploads.ini

CMD chown -R www-data:www-data /var/www/html/wpcontent/

但我总是收到“文件或文件夹不存在”的错误。

我尝试过像这样使用 CMD:
CMD ["chown", "-R", "www-data:www-data", "/var/www/html/wp-content/"]
但是没有成功。

问题


有没有一种方法可以在原始的 ENTRYPOINT 后运行命令?
否则,您知道解决此问题的更好方法吗?


你如何创建容器? - benaich
4个回答

6
你可以修改你的./entrypoint.sh脚本,在执行你的chown命令后,运行原始镜像的默认入口脚本。
#!/bin/bash
echo Fixing permissions...
chown -R www-data:www-data /var/www/html/wp-content/
docker-entrypoint.sh apache2-foreground

2
这是最佳实践吗?如果默认入口脚本在未来某个时候更改会怎样?现在遇到了这个问题,不确定是否应该使用DockerFile“扩展”wordpress镜像,还是按照您的答案建议去做。 - mathee
@Patrick Steadman 技术上说,整个文件夹都需要由 root 拥有吗? - FooBar
@FooBar 我认为这取决于个人的用例,将 wp-content 设置为 www-data 拥有应该足以允许通过 wp-admin 上传媒体/插件/主题文件,但是它会在从 docker 主机中绑定挂载的文件中编辑文件时创建新的权限问题,可以通过将主机中的当前用户添加到 www-data 组(或系统上 gid 33 的任何组)来解决。所有这些都感觉非常 hacky,希望有更好的解决方案...我尝试更改容器中运行 wordpress 的用户 ID,但没有成功。 - Patrick Steadman

3
根据Docker的文档,你应该使用的命令是 RUN
不要将RUN和CMD搞混。RUN会运行一个命令并提交结果;而CMD不会在构建时执行任何操作,但指定了镜像的预期命令。
因此,在您的Dockerfile中,该行应为:RUN chown -R www-data:www-data /var/www/html/wp-content
此外,为了减少所创建的图层数量和镜像的大小,建议尽可能地链接多个RUN命令。例如(未经测试):
FROM wordpress:5.1.1

# install dos2unix (fix problem between CRLF and LF) and increase upload limit
RUN apt-get update -y && \
    apt-get install -y dos2unix && \
    touch /usr/local/etc/php/conf.d/uploads.ini \
    && echo "upload_max_filesize = 10M;" >> /usr/local/etc/php/conf.d/uploads.ini && \
    chown -R www-data:www-data /var/www/html/wp-content

# fix permissions issues
COPY entrypoint.sh /
RUN dos2unix /entrypoint.sh && \
    chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

1
我有点困惑:您的运行命令已经更改了 wp-content 的所有者。我是否需要所有 entrypoint.sh 相关的内容? - westor
1
很遗憾,这不会起作用。任何更改都会在构建完成后被覆盖。来源:https://docs.docker.com/engine/reference/builder/#notes-about-specifying-volumes - Ángel Jiménez

3
这是由WordPress Docker镜像的创建方式所致。
我创建了一个拉取请求,使得wp-content文件夹在使用卷共享时(或其某些子文件夹)属于www-data
在它被合并之前(如果它被合并),您可以创建自己的WordPress Docker镜像来集成我的更改。从https://github.com/docker-library/wordpress上选择一个文件夹(选择PHP版本,然后选择Web服务器参数)。
  1. 在您的项目中创建一个docker/wordpress文件夹。
  2. 将两个原始文件(Dockerfiledocker-entrypoint.sh)从GitHub复制到该文件夹中。
  3. 替换docker-entrypoint.sh中的以下行:
        if [ "$(id -u)" = '0' ] && [ "$(stat -c '%u:%g' .)" = '0:0' ]; then
            chown "$user:$group" .
        fi

由:
        if [ "$(id -u)" = '0' ]; then
            chown -R "$user:$group" .
        fi

我尝试使用这个git,但是运行Shell文件时出现了错误:https://stackoverflow.com/questions/62752579/entrypoint-sh-line-27-1-unbound-variable - Swe Zin Phyoe

3

问题

父级docker-entrypoint.sh在你的Dockerfileentrypoint.sh之后运行,覆盖了您设置的权限。

解决方案

使用自定义入口点执行延迟命令,该命令在docker-entrypoint.sh运行后设置所有权。

您的Dockerfile

FROM wordpress:php7.4-apache

[...]

ENTRYPOINT ["/entrypoint.sh"]

您的 entrypoint.sh


# In 10 seconds set the ownership

$(sleep 10 && chown -R www-data:www-data /var/www/html/) & 

# Run the parent's ENTRYPOINT and CMD as defined in its Dockerfile
#     (https://github.com/gsusI/wordpress/blob/master/php7.4/apache/Dockerfile)

docker-entrypoint.sh apache2-foreground # run parent entrypoint.

Note: Invoking the parent's ENTRYPOINT and CMD manually means that if the parent Dockerfile alters its last two lines this solution might not work properly.

Therefore is recommendable that wheneber updating the your FROM, you check the parent's Dockerfile to verify the last two lines are still:

ENTRYPOINT ["docker-entrypoint.sh"]

CMD ["apache2-foreground"]

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