“AH01071:收到错误'无法打开主脚本”:容器权限或Symfony3问题?

时间:2017-01-14 02:40:34

标签: docker symfony docker-compose

我正在尝试使用Docker和Docker Compose在“LAMP”堆栈中运行一个Symfony 3“基础”应用程序(完全意味着非复杂性,只有几个已安装但未启用的软件包)(我已从中删除了MySQL)这个帖子因为它不相关)。这是我的docker-compose.yml文件:

version: '2'
services:
  php-fpm:
    build: docker/php-fpm
    ports:
        - "80:80"
    volumes:
      - ./sources:/data/www
      - ./data/logs/symfony:/data/www/var/logs
  db:
    image: mysql
    environment:
        MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
        MYSQL_DATABASE: ${MYSQL_DATABASE}
        MYSQL_USER: ${MYSQL_USER}
        MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    volumes:
        - sql-data:/var/lib/mysql

这是Dockerfile容器的php-fpm

FROM reynierpm/docker-centos7-supervisord:latest
ENV TERM=xterm \
    PATH="/root/.composer/vendor/bin:${PATH}" \
    COMPOSER_ALLOW_SUPERUSER=1
RUN yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm \
                   https://rpms.remirepo.net/enterprise/remi-release-7.rpm
RUN yum install -y  \
        yum-utils \
        git \
        zip \
        unzip \
        nano \
        httpd \
        php71-php-fpm \
        php71-php-cli \
        php71-php-common \
        php71-php-gd \
        php71-php-intl \
        php71-php-json \
        php71-php-mbstring \
        php71-php-mcrypt \
        php71-php-mysqlnd \
        php71-php-pdo \
        php71-php-pear \
        php71-php-xml \
        php71-pecl-apcu \
        php71-php-pecl-apfd \
        php71-php-pecl-memcache \
        php71-php-pecl-memcached \
        php71-php-pecl-mongodb \
        php71-php-pecl-redis \
        php71-php-pecl-request \
        php71-php-pecl-uploadprogress \
        php71-php-pecl-xattr \
        php71-php-pecl-zip && \
        yum clean all && rm -rf /tmp/yum*

RUN rm -f /etc/httpd/conf/httpd.conf /etc/httpd/conf.d/* /etc/httpd/conf.modules.d/* && \
    ln -sfF /opt/remi/php71/enable /etc/profile.d/php71-paths.sh && \
    ln -sfF /opt/remi/php71/root/usr/bin/{pear,pecl,phar,php,php-cgi,phpize} /usr/local/bin/. && \
    mv -f /etc/opt/remi/php71/php.ini /etc/php.ini && \
    ln -s /etc/php.ini /etc/opt/remi/php71/php.ini && \
    rm -rf /etc/php.d && \
    mv /etc/opt/remi/php71/php.d /etc/. && \
    ln -s /etc/php.d /etc/opt/remi/php71/php.d

RUN curl -LsS https://symfony.com/installer -o /usr/local/bin/symfony && \
    chmod a+x /usr/local/bin/symfony

COPY container-files /

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer && \
    composer global install --no-dev

RUN yum install -y php71-php-pecl-xdebug && \
    yum clean all && rm -rf /tmp/yum* && \
    php --version

RUN chmod +x /config/bootstrap.sh
RUN echo 'alias sf="php bin/console"' >> ~/.bashrc

WORKDIR /data/www
EXPOSE 80 9001

问题是,如果我尝试使用dev访问http://symfonyapp.local/app_dev.php环境,我会一直收到此错误:

php-fpm  | [Sat Jan 14 15:09:27.655609 2017] [proxy_fcgi:error] [pid 13:tid 140600250660608] [client 172.18.0.1:43960] AH01071: Got error 'Unable to open primary script: /data/www/web/_wdt/210673 (No such file or directory)\n', referer: http://symfonyapp.local/app_dev.php

如果出现上述错误,我可以考虑一下:

  • 所有权|权限问题在容器中的/data/www/web处发生,因为该文件夹归root所有,并且很好.... root我不需要解释< / LI>
  • Symfony3失败了,我也不知道它到目前为止我找不到它
  • Apache | PHP-FPM无法写入导致此列表中第一项的此类文件夹
  • Apache config阻止了要写入的目录/web。 (mod_scurity没有运行所以我不能责怪它)

这是我迄今为止没有成功的尝试,因为我一直都会遇到同样的错误。

  1. 更改容器中的所有权/权限(这导致Linux中的错误,因为卷中的权限也会在主机中更改,Windows中也不会发生这种情况)。以下是我如何实现这一目标的解释。
  2. 如何更改所有权/权限的简要说明:

    php-fpm Dockerfile继承自docker-centos7-supervisord,其scriptENTRYPOINT。所以我创建了一个文件/container-files/config/init/20-permissions.sh,内容如下:

    #!/usr/bin/env bash
    
    chown -R apache:root /data/www && \
    find /data/www -type d -print0 | xargs -0 chmod 775 && \
    find /data/www -type f -print0 | xargs -0 chmod 664
    echo "Set up permissions finished"
    
    exec "$@"
    

    上面的文件在容器启动并装入卷后执行。我确实知道文件已执行,因为我在Set up permissions finished容器日志中看到了php-fpm。虽然因为检查所有权/权限后显示以下内容,但这很奇怪:

    > docker exec -it php-fpm ls -la /data/www/web
    total 57
    drwxr-xr-x 2 root root  4096 Jan 14 03:45 .
    drwxr-xr-x 2 root root  4096 Jan 14 00:40 ..
    -rwxr-xr-x 1 root root  3319 Jan 13 23:54 .htaccess
    -rwxr-xr-x 1 root root   635 Jan 14 03:45 app.php
    -rwxr-xr-x 1 root root  1184 Jan 14 03:45 app_dev.php
    -rwxr-xr-x 1 root root  2092 Jan 13 23:54 apple-touch-icon.png
    drwxr-xr-x 2 root root     0 Dec 13 13:36 bundles
    -rwxr-xr-x 1 root root 21244 Jan 14 00:04 config.php
    -rwxr-xr-x 1 root root  6518 Jan 13 23:54 favicon.ico
    -rwxr-xr-x 1 root root   116 Jan 13 23:54 robots.txt
    

    所以在这种情况下,我不确定这是否顺利或是否可能。我已经创建了一个包含两个分支的存储库,其中包含了所有必需的功能:master将httpd和php-fpm放在一个容器中,httpd将它们放在单独的容器中。虽然两者的结果是相同的。

    为了让一切运转起来,你应该:

    • 运行docker-compose up -d --build --force-recreate( - force-recreate和--build不是必需的,只是以防万一)
    • 运行docker exec -it php-fpm composer update,以便下载项目所需的库。
    • symfonyapp.local添加到您的主机文件

    目前我在Windows中使用Docker,这是关于它的信息:

    Version: 1.13.0-rc6-beta36 (9696)
    Channel: Beta
    Sha1: 64a715b54327a0ec8f28076d1a343f4c811856fb
    Started on: 2017/01/13 18:34:34.519
    Resources: C:\Program Files\Docker\Docker\Resources
    OS: Windows 10 Pro
    Edition: Professional
    Id: 1607
    Build: 14393
    BuildLabName: 14393.693.amd64fre.rs1_release.161220-1747
    

    但我也在Linux中对此进行了测试,并且我的行为也相同,这意味着错误仍然存​​在。

    这里发生了什么?你能给我一些想法或解决方案吗?在这一点上,我不在他们身边,不知道还能做什么。

2 个答案:

答案 0 :(得分:3)

TL; DR composer update期间引入了权限问题。可能是在其中一个脚本中(其中一个列表可以在composer.json中找到)。

我从头开始在带有您的存储库的VM上,并按照您的启动说明进行操作。

git clone https://github.com/reypm/symfony3app
cd symfony3app
docker-compose up -d --build --force-recreate

此时,应该运行20-permissions.sh的chown。为了验证这一点,我查看了容器内部。我看到的错误与/data/www/var/cache/dev有关,所以我查看了该路径中每个目录的权限。

[my-vm]# docker-compose exec php-fpm bash
[container]# ls -la /data/www{,/var{,/cache{,/dev}}}

ls: cannot access /data/www/var/cache/dev: No such file or directory
/data/www:
total 168
drwxrwsr-x 8 apache root   4096 Jan 15 19:26 .
drwxr-xr-x 8 root   root   4096 Jan 15 19:27 ..
-rw-rw-r-- 1 apache root    248 Jan 15 19:26 .gitignore
-rw-rw-r-- 1 apache root     74 Jan 15 19:26 README.md
drwxrwsr-x 5 apache root   4096 Jan 15 19:27 app
drwxrwsr-x 2 apache root   4096 Jan 15 19:26 bin
-rw-rw-r-- 1 apache root   2387 Jan 15 19:26 composer.json
-rw-rw-r-- 1 apache root 119533 Jan 15 19:26 composer.lock
-rw-rw-r-- 1 apache root    978 Jan 15 19:26 phpunit.xml.dist
drwxrwsr-x 3 apache root   4096 Jan 15 19:26 src
drwxrwsr-x 3 apache root   4096 Jan 15 19:26 tests
drwxrwsr-x 4 apache root   4096 Jan 15 19:26 var
drwxrwsr-x 2 apache root   4096 Jan 15 19:26 web

/data/www/var:
total 52
drwxrwsr-x 4 apache root  4096 Jan 15 19:26 .
drwxrwsr-x 8 apache root  4096 Jan 15 19:26 ..
-rw-rw-r-- 1 apache root 34272 Jan 15 19:26 SymfonyRequirements.php
drwxrwsr-x 2 apache root  4096 Jan 15 19:26 cache
drwxrwsr-x 2 apache root  4096 Jan 15 19:26 sessions

/data/www/var/cache:
total 8
drwxrwsr-x 2 apache root 4096 Jan 15 19:26 .
drwxrwsr-x 4 apache root 4096 Jan 15 19:26 ..
-rw-rw-r-- 1 apache root    0 Jan 15 19:26 .gitkeep

到目前为止,这么好。 chown已将所有内容设置为apache:root并使用脚本中指定的模式。

接下来,我退出了容器并运行了作曲家更新。

docker-compose exec php-fpm composer update

出现提示时,我使用了我在git repo中找到的数据库参数,一切安装都很好。接下来,我回到容器中查看权限是否已更改。

[my-vm]# docker-compose exec php-fpm bash
[container]# ls -la /data/www{,/var{,/cache{,/dev}}}

/data/www:
total 164
drwxrwsr-x  9 apache root   4096 Jan 15 19:20 .
drwxr-xr-x  8 root   root   4096 Jan 15 19:18 ..
-rw-rw-r--  1 apache root    248 Jan 15 19:17 .gitignore
-rw-rw-r--  1 apache root     74 Jan 15 19:17 README.md
drwxrwsr-x  5 apache root   4096 Jan 15 19:18 app
drwxrwsr-x  2 apache root   4096 Jan 15 19:21 bin
-rw-rw-r--  1 apache root   2387 Jan 15 19:17 composer.json
-rw-rw-r--  1 apache root 114331 Jan 15 19:20 composer.lock
-rw-rw-r--  1 apache root    978 Jan 15 19:17 phpunit.xml.dist
drwxrwsr-x  3 apache root   4096 Jan 15 19:17 src
drwxrwsr-x  3 apache root   4096 Jan 15 19:17 tests
drwxrwsr-x  5 apache root   4096 Jan 15 19:21 var
drwxr-sr-x 25 root   root   4096 Jan 15 19:21 vendor
drwxrwsr-x  3 apache root   4096 Jan 15 19:21 web

/data/www/var:
total 96
drwxrwsr-x 5 apache root  4096 Jan 15 19:21 .
drwxrwsr-x 9 apache root  4096 Jan 15 19:20 ..
-rw-rw-r-- 1 apache root 34272 Jan 15 19:21 SymfonyRequirements.php
-rw-r--r-- 1 root   root 39637 Jan 15 19:21 bootstrap.php.cache
drwxrwsr-x 3 apache root  4096 Jan 15 19:21 cache
drwxr-sr-x 2 root   root  4096 Jan 15 19:21 logs
drwxrwsr-x 2 apache root  4096 Jan 15 19:17 sessions

/data/www/var/cache:
total 12
drwxrwsr-x 3 apache root 4096 Jan 15 19:21 .
drwxrwsr-x 5 apache root 4096 Jan 15 19:21 ..
-rw-rw-r-- 1 apache root    0 Jan 15 19:17 .gitkeep
drwxr-sr-x 4 root   root 4096 Jan 15 19:21 dev

/data/www/var/cache/dev:
total 636
drwxr-sr-x 4 root   root   4096 Jan 15 19:21 .
drwxrwsr-x 3 apache root   4096 Jan 15 19:21 ..
-rw-r--r-- 1 root   root     90 Jan 15 19:21 annotations.map
-rw-r--r-- 1 root   root 277718 Jan 15 19:21 appDevDebugProjectContainer.php
-rw-r--r-- 1 root   root  38062 Jan 15 19:21 appDevDebugProjectContainer.php.meta
-rw-r--r-- 1 root   root 213247 Jan 15 19:21 appDevDebugProjectContainer.xml
-rw-r--r-- 1 root   root  84170 Jan 15 19:21 appDevDebugProjectContainerCompiler.log
-rw-r--r-- 1 root   root   4790 Jan 15 19:21 classes.map
drwxr-sr-x 3 root   root   4096 Jan 15 19:21 doctrine
drwxr-sr-x 4 root   root   4096 Jan 15 19:21 pools

如您所见,某些内容现在归root:root所有。据我所知,这只是因为容器本身以root身份运行。因此,当您在内部执行作业时,该作业将以root身份运行。因此,默认情况下,它创建的任何内容都由root拥有。

与此同时,Apache以用户&#34; apache&#34;运行,因为这就是supervisord配置的目的。

对于这个问题,可能有更优雅的解决方案,但这个是我提出的最简单的一个:

docker-compose exec php-fpm chown -R apache:root /data/www/var/cache
docker-compose restart php-fpm

之后,应用返回

  

欢迎来到   Symfony 3.2.2

     

您的申请现已准备就绪。您可以在以下网址开始处理:/data/www/

我还没有尝试过比这更好的事情。但我的建议是尝试让你的创业公司运行作曲家更新,然后再做chown工作。你可能不需要知道/data/www的所有内容,因为Apache可能不需要为那里的所有内容写入权限。我的猜测是缓存目录是它需要写的一个地方,所以我选择了那条路径。

答案 1 :(得分:1)

花了好几天时间试图让这个工作起作用后,我终于得到了它,感谢Slack中的Symfony #support频道以及IRC #symfony,#httpd,#php,#docker上的以下频道,最后但并非最不重要的是@DanLowe,他花时间寻找解决方案并帮助解决问题。

事实|想法:

  • 是Symfony 3.2.2问题...... 不是
  • Docker是否在Windows上运行... 不是
  • 目录/web上的权限问题... 不是
  • 是PHP-FPM问题...... 不是
  • 是Apache(httpd)问题...... 不是

问题:由于副本而导致PHP(.ini文件)中的未命中配置从Nginx安装程序粘贴到Apache(之前我使用的是Nginx,然后我转移到Apache,保留了PHP设置)。

// this work in Nginx but does not work in Apache  
// cgi.fix_pathinfo is required to get PHP to adhere to the CGI spec

; Fix the cgi.fix_pathinfo directive
cgi.fix_pathinfo = 0

默认情况下,该行在php.ini文件中进行了注释。但等待这可能是一个问题,当PHP使用FastCGI和ProxyPass等等......好吧(我之前在某处读过)和没有(如果你研究和设置你应该的服务器)。上述问题的解决方案是默认注释掉该行:

; Fix the cgi.fix_pathinfo directive
; cgi.fix_pathinfo = 0

上面介绍的“安全”漏洞的解决方案是我引用here

  

如果您有最新版本的PHP-FPM(~5.3.9 +?),那么您需要   什么也不做,因为下面的安全行为已经是默认行为。

     

否则,找到php-fpm的www.conf文件(也许吧   /etc/php-fpm.d/www.conf,取决于你的系统)。确保你有   这样:

     

security.limit_extensions = .php

     

同样,这些日子在很多地方都是默认的。

在我的情况下,我使用的是PHP 7.1,但即使我通过在/etc/php-fpm.d/www.conf添加这样的行来保护我的服务器。