ReynierPM
ReynierPM

Reputation: 18670

"AH01071: Got error 'Unable to open primary script": Container permissions or Symfony3 issue?

I am trying to run a Symfony 3 "base" application (meaning non complexity at all and just a few bundles installed but not even enabled) in a "LAMP" stack using Docker and Docker Compose (I've removed MySQL from the post because it's not relevant). This is my docker-compose.yml file:

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

And this is the Dockerfile for the php-fpm container:

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

The thing is I am getting this error all the time if I try to access the dev environment using 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

Having the error above I can think in:

This is what I've tried so far without success because I am still getting the same error all the time.

  1. Change ownership/permissions in the container (this lead into an error in Linux since permissions in volumes are changed in host as well, the same doesn't happen in Windows). Below is an explanation in how do I achieve such thing.

Brief explanation in how do I change ownership/permissions:

The php-fpm Dockerfile is inherit from docker-centos7-supervisord which has this script as ENTRYPOINT. So I have created a file /container-files/config/init/20-permissions.sh with the following content:

#!/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 "$@"

The file above gets executed after container starts and volumes are mounted. I did know the file is executed because I am seeing Set up permissions finished in the php-fpm container logs. It's weird though because checking ownership/permissions after show me the following:

> 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

So in this case I am not sure if this is going well or if it's possible even. I have created a repository with two branches with all the necessary to gives this a try: master having httpd and php-fpm both in one container and httpd having them in separated containers. Although the result in both is the same.

To get everything up and running you should:

Currently I am using Docker in Windows, this is the info about it:

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

But I have tested this in Linux as well and I have the same behavior meaning the error still there.

What is happening here? Can you give me some ideas or solution? At this point I am out of them and don't know what else to do.

Upvotes: 4

Views: 4496

Answers (2)

ReynierPM
ReynierPM

Reputation: 18670

After spent days and hours trying to get this working I finally got it thanks to Symfony #support channel in Slack and to the following channels on the IRC #symfony, #httpd, #php, #docker and last but not least to @DanLowe who takes the time to find a solution and help me out with the issue.

The facts|thoughts:

  • Is a Symfony 3.2.2 issue ... is not
  • Is a Docker running on Windows ... is not
  • Is a permission issue on the directory /web ... is not
  • Is a PHP-FPM problem ... is not
  • Is a Apache (httpd) problem ... is not

The problem: A miss configuration in PHP (.ini file) due to a copy & paste from Nginx setup to be used with Apache (previously I was using Nginx and then I moved to Apache leaving the PHP setup as it was).

// 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

By default that line is commented in the php.ini file. But waits this could be an issue when PHP is using FastCGI and ProxyPass and so on .... well yes (I read it somewhere before) and no (if you research and set up your server as it should be). The solution to the problem above is comment out the line as it's by default:

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

The solution to the "security" breach introduced above is and I've quoted from here:

If you have a recent version of PHP-FPM (~5.3.9+?), then you need to do nothing, as the safe behaviour below is already the default.

Otherwise, find php-fpm's www.conf file (maybe /etc/php-fpm.d/www.conf, depends on your system). Make sure you have this:

security.limit_extensions = .php

Again, that's default in many places these days.

In my case I am using PHP 7.1 but even though I've secured my server by adding such line at my /etc/php-fpm.d/www.conf.

Upvotes: 2

Dan Lowe
Dan Lowe

Reputation: 56597

TL;DR: The permission problem is being introduced during composer update. Possibly during one of the scripts (a list of which can be found in composer.json).

I started from scratch on a VM with your repository and followed your startup instructions.

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

At this point, the chown from 20-permissions.sh should have been run. To verify that, I looked inside the container. The error I have seen related to /data/www/var/cache/dev, so I looked at the permissions on every directory in that path.

[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

So far, so good. The chown has set everything to apache:root and using the modes specified in the script.

Next, I exited the container and ran the composer update.

docker-compose exec php-fpm composer update

When prompted, I used the database parameters I found in the git repo, and everything installed fine. Next, I went back into the container to see if the permissions had changed.

[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

As you can see, some things are now owned by root:root. As far as I can tell, this is simply because the container itself runs things as root. So when you exec a job inside, that job is run as root. Therefore, anything it creates is, by default, owned by root.

Meanwhile, Apache runs as the user "apache", because that is what supervisord is configured to do.

There are probably more elegant fixes for this problem, but this one was the simplest one I came up with:

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

After that, the app returns

Welcome to Symfony 3.2.2

Your application is now ready. You can start working on it at: /data/www/

I haven't tried to fix things any better than this. But my suggestion would be to try to have the startup run composer update for you and do the chown job after that. You probably don't need to chown all of /data/www, as Apache probably doesn't need write privs to everything in there. My guess was that the cache directory is one place it needs to write, so I chown'd that path.

Upvotes: 4

Related Questions