Docker php-fpm作为www-data运行

时间:2019-04-10 19:47:54

标签: php docker docker-compose

我最近一直在学习使用Docker构建映像和容器。使用Mac时,我对此非常有信心,但是最近切换到Ubuntu,对于开发的这一方面我还是很陌生。

我使用一个标准的新Laravel项目作为我的“代码”,目前仅使用php容器和nginx容器。

我正在使用docker-compose.yml文件创建我的容器:

version: "3.1"

services:
    nginx:
        image: nginx:latest
        volumes:
            - ./code:/var/www
            - ./nginx_conf.conf:/etc/nginx/conf.d/default.conf
        ports:
            - "80:80"
    php:
        image: php:7.3-fpm
        ports:
            - 9000
        volumes:
            - ./code:/var/www

上面的代码可能有也可能没有错误,只是因为我只是将其键入而不是复制和粘贴而已-但它在我的机器上有效。

问题是:

  • php-fpm配置有--with-fpm-user=www-data--with-fpm-group=www-data,并且在php:7.3-fpm Dockerfile (see here)中进行了设置。

  • 主机上的文件与我的用户名和组一起保存为所有者/组。

  • 当我进入容器时,文件归1000和组1000拥有(我假设是到主机上用户帐户和组的映射?)

但是,当我通过浏览器访问该应用程序时,在启动时出现权限被拒绝的错误(当Laravel尝试在存储中创建错误日志文件时)。我认为这是因为php-fpm作为www-data运行,但是存储目录具有所有者/组phil:phil-我的主机所有者和组的权限drwxr-xr-x

经过数小时的谷歌搜索和试用,我尝试了以下方法:

  • 将主机上代码目录的所有者和组递归更改为www-data:www-data。这可以使Laravel应用程序正常工作,但是我现在无法使用PHPStorm在主机上创建或编辑etc文件,因为该目录是只读的(我想是因为phpstorm以我的用户身份运行,并且目录由其他用户拥有/组)。

  • 我已将我的主机用户帐户添加到www-data组,并使用write向该组授予了sudo chmod -R g+w ./code权限,这现在允许该应用程序运行该应用程序,并允许phpstorm编写,执行etc文件,但是当我创建或编辑文件时,文件所有权和组将更改回我的主机phil:phil,我想这将再次破坏应用程序。

  • 我尝试创建一个php映像,并设置env(如上面的链接中所述)以--with-fpm-user=phil --with-fpm-group=phil进行配置,但是在构建之后,它没有任何改变-它仍然与www-data一起运行(阅读github问题后,我认为这是因为envs不能更改,直到后来,此时已经配置了php?)(see github issue here)

我没办法尝试了。我唯一想到的是将主机上的代码目录的所有者和组递归设置为www-data,然后尝试以www-data的身份运行phpstorm,但这感觉很奇怪(更新:我尝试过使用sudo -u www-data phpstorm.sh以www-data用户身份打开phpstorm,但是我遇到了Java异常-与图形有关-因此这种方法也不可行

现在,我唯一想想到的就是从高山基础映像创建一个新的php映像,并完全绕过php的映像-这似乎很不方便,因为维护者想使用ENV而不是ARG

我不确定这种情况下的最佳实践。我是否应该尝试更改php-fpm的运行方式(用户/组)?我应该在主机上更新目录所有者/组吗?我应该以其他用户身份运行phpstorm吗?

从字面上看,任何建议都将不胜感激。

2 个答案:

答案 0 :(得分:2)

几周前遇到了同样的问题。

实际发生的情况是您的主机和容器通过该卷共享相同的文件,因此,它们也共享权限。

在生产中,一切都很好-您的服务器(www-data用户)应该是文件的所有者,因此这里没有问题。开发中的事情变得复杂-当您尝试从主机访问这些文件时。

我知道一些解决方法,其中最棘手的方法似乎是将容器中的www-data uid设置为1000,这样它将与主机中的uid相匹配。

另一种简单的方法是在共享目录中打开777的完全权限,因为它仅在开发版本中需要-(虽然永远不会在生产中完成,但是正如我之前提到的,在生产中您没有任何问题,因此您必须将这两个过程分开,并且只能在开发模式下进行操作

对我而言,最优雅的解决方案似乎是允许所有组成员访问文件(设置770权限),并将www-data添加到您的组中:

usermod www-data -a -G phill #// add it to your group

chown -r phill ./code #// make yourself the owner. might need sudo.

chmod 770 ./code #//grunt permissions to all group members

答案 1 :(得分:0)

根据系统的不同,您有很多选择,但是请记住,您可能必须重新启动运行的进程(例如php-fpm)

一些有关如何实现此目的的示例:(您可以使用docker container exec ...在容器外部运行命令)

  • 示例1:

usermod -g 1007 www-data

它将用户www-data的uid更新为1007

  • 示例2:

deluser www-data

adduser -u 1007 -D -S -G www-data www-data

它将删除用户www-data并使用uid 1007重新创建

  • 获取pid并重新启动过程

要重新启动正在运行的进程,例如php-fpm,您可以这样做:

首先使用以下命令之一获取pid:

pidof php-fpm

ps -ef | grep -v grep | grep php-fpm | awk '{print $2}'

find /proc -mindepth 2 -maxdepth 2 -name exe -lname '*/php-fpm' -printf %h\\n 2>/dev/null | sed s+^/proc/++

然后使用之前获得的pid重新启动进程(如果进程支持USR2信号):

kill -USR2 pid <-用之前的数字替换pid

我发现最简单的方法是在知道正确的pid的情况下更新主机或构建容器(如果您在不同的环境中工作,则并非总是可行的)