5

I tried to have a very minimal setup, to dockerize Laravel app. Even the nginx able to forward the request to Laravel container, I'm still getting GET /index.php" 404

C:\yocto\snapweb>docker-compose logs --follow laravel
Attaching to snapweb_laravel_1
laravel_1  | [23-Jul-2018 07:10:04] NOTICE: fpm is running, pid 1
laravel_1  | [23-Jul-2018 07:10:04] NOTICE: ready to handle connections
laravel_1  | 172.18.0.3 -  23/Jul/2018:07:14:01 +0000 "GET /index.php" 404

When I went inside laravel container, this is how it looks like. Seem fine to me.

Inside Laravel container

/var/www/html # pwd
/var/www/html
/var/www/html # ls -al
total 224
drwxr-xr-x    1 root     root          4096 Jul 23 07:09 .
drwxr-xr-x    1 root     root          4096 Jul 21 08:11 ..
-rwxr-xr-x    1 root     root           668 Jul 23 07:08 Dockerfile
drwxr-xr-x    6 root     root          4096 May  8 19:42 app
-rwxr-xr-x    1 root     root          1686 May  8 19:42 artisan
drwxr-xr-x    3 root     root          4096 May  8 19:42 bootstrap
-rw-r--r--    1 root     root          1477 May  8 19:42 composer.json
-rw-r--r--    1 root     root        144199 Jul 23 07:03 composer.lock
drwxr-xr-x    2 root     root          4096 May  8 19:42 config
drwxr-xr-x    5 root     root          4096 May  8 19:42 database
-rw-r--r--    1 root     root          1022 May  8 19:42 package.json
-rw-r--r--    1 root     root          1134 May  8 19:42 phpunit.xml
drwxr-xr-x    4 root     root          4096 May  8 19:42 public
-rw-r--r--    1 root     root          3675 May  8 19:42 readme.md
drwxr-xr-x    5 root     root          4096 May  8 19:42 resources
drwxr-xr-x    2 root     root          4096 May  8 19:42 routes
-rw-r--r--    1 root     root           563 May  8 19:42 server.php
drwxr-xr-x    5 root     root          4096 May  8 19:42 storage
drwxr-xr-x    4 root     root          4096 May  8 19:42 tests
drwxr-xr-x   37 root     root          4096 Jul 23 07:03 vendor
-rw-r--r--    1 root     root           549 May  8 19:42 webpack.mix.js
/var/www/html # ls -al public
total 32
drwxr-xr-x    4 root     root          4096 May  8 19:42 .
drwxr-xr-x    1 root     root          4096 Jul 23 07:09 ..
-rw-r--r--    1 root     root           593 May  8 19:42 .htaccess
drwxr-xr-x    2 root     root          4096 May  8 19:42 css
-rw-r--r--    1 root     root             0 May  8 19:42 favicon.ico
-rw-r--r--    1 root     root          1823 May  8 19:42 index.php
drwxr-xr-x    2 root     root          4096 May  8 19:42 js
-rw-r--r--    1 root     root            24 May  8 19:42 robots.txt
-rw-r--r--    1 root     root           914 May  8 19:42 web.config
/var/www/html #

May I know what's wrong with my setup? Here's my minimalist Dockerfiles


laravel/Dockerfile

FROM php:7.2.8-fpm-alpine3.7

RUN apk update && \
    apk add git && \
    apk add unzip

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

# Get laravel into a temporary folder.
RUN composer create-project --prefer-dist laravel/laravel laravel-install-tmp

# Move local host files to docker container.
COPY . /var/www/html

# Copy all laravel files, without overwrite files from host.
RUN false | cp -ai /var/www/html/laravel-install-tmp/* /var/www/html/ 2>/dev/null

# Remove temporary folder.
RUN rm -rf /var/www/html/laravel-install-tmp/

WORKDIR /var/www/html

CMD ["php-fpm", "-F"]

nginx/default.conf

server {
    listen 443;
    ssl on;

    ssl_certificate /app/cert.pem;
    ssl_certificate_key /app/key.pem;

    location / {
        try_files $uri /index.php?$args;
    }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass laravel:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }   
}

nginx/Dockerfile

FROM nginx:1.13.9-alpine

COPY . /app

RUN rm /etc/nginx/conf.d/default.conf
COPY default.conf /etc/nginx/conf.d/

docker-compose.yml

version: '2'
services:

  # Note, SSL cert (cert.pem and key.pem) is generated from cloudflare.
  nginx:
    build:
      context: ./nginx
      dockerfile: Dockerfile
    restart: always
    ports:
     - "2053:443"


  laravel:
    build:
      context: ./laravel
      dockerfile: Dockerfile
    restart: always
5
  • 1
    I am working on a similar issue with yii2 at the moment. This seems to be a nginx config issue (at least thats what was giving me 404's). While i am not an expert in nginx, one thing that you seem to be missing is a root /var/www/html; in the server object. Maybe that will help. Commented Jul 23, 2018 at 7:37
  • But I had checked through docker-compose logs --follow laravel, the request has already reach laravel container successful (which is fastcgi_pass by nginx) Commented Jul 23, 2018 at 7:40
  • run nginx in debug mode and check the logs Commented Jul 23, 2018 at 10:05
  • is the docker-compose.yml complete? What networks do you run this with? Commented Jul 23, 2018 at 11:00
  • 1
    Thanks @SimasJoneliunas You are right at the first place. Missing out root /var/www/html/public; is the key solution to the problem. Thanks. Commented Jul 23, 2018 at 20:16

2 Answers 2

4

PHP-FPM

I think you are missing the php-fpm.conf configuration file, mine looks just like a standard one with some changes:

  • error_log = /proc/self/fd/2 allows you to use docker logs
  • daemonize = no
  • include=/etc/php/7.1/fpm/php-fpm.d/www.conf

www.conf which I include in the bottom of php-fpm.conf

standard one with changes:

  • listen = 9000

Dockerfile:

Obviously I copy the php-fpm.conf and www.conf (I use php:7.1.14-fpm-jessie)

... install & cleanup steps
COPY php-fpm.conf /etc/php/7.1/fpm/php-fpm.conf
COPY www.conf /etc/php/7.1/fpm/php-fpm.d/www.conf

the end of Dockerfile for php-fpm looks like:

CMD ["php-fpm", "--fpm-config", "/etc/php/7.1/fpm/php-fpm.conf"]

NGINX

default which I copy in via Dockerfile:

server {
    listen 80 default_server;

    root /var/www/app/public;

    index index.html index.htm index.php;

    server_name _;

    charset utf-8;

    location = /favicon.ico { log_not_found off; access_log off; }
    location = /robots.txt  { log_not_found off; access_log off; }

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass pn-php-fpm:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }

    error_page 404 /index.php;

    location ~ /\.ht {
        deny all;
    }
}

NGINX's Dockerfile:

FROM nginx

RUN  echo "daemon off;" >> /etc/nginx/nginx.conf

COPY default /etc/nginx/conf.d/default.conf

# forward request and error logs to docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
    && ln -sf /dev/stderr /var/log/nginx/error.log

CMD ["nginx"]

Docker compose part

You need to share volumes when composing; what I mean, NGINX + php-fpm must be able to read your application's code

volumes:
  - wherever/your/code/is/on/host:/var/www/app

Note: this answer is WIP and I will edit / comment regularly in order to help OP.

Sign up to request clarification or add additional context in comments.

4 Comments

May I know, for php-fpm, how does it know it needs to look for file in /var/www/html/public/index.php ?
@CheokYanCheng it's passed by the server (NGINX) see fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; So / That's why volume in NGINX should be mapped to exact "target" as fpm container (/var/www/app or whatever you decide to)
Thanks. Missing root /var/www/html/public; in Nginx container, is the reason which makes it broken. (Although error happens in Laravel container)
@CheokYanCheng In my first draft that was the first thing I was going to write down, then I just slapped NGINX config and figured that with rep 18k you will figure it out eventually while I provide you with some concrete example. Good for you and good luck!
1

Here's my very minimal setup, which makes Laravel workable in Docker. Previously, it doesn't work, because it didn't include the following line in Nginx container. (Although error happens in Laravel container)

root /var/www/html/public;

laravel/html (folder)

This folder is generated using the following command line. The command is executed in host machine.

docker run --rm -v $(pwd):/app -w /app composer/composer create-project --prefer-dist laravel/laravel html (Linux)
docker run --rm -v %cd%:/app -w /app composer/composer create-project --prefer-dist laravel/laravel html (Windows)

laravel/Dockerfile

FROM php:7.2.8-fpm-alpine3.7

COPY html /var/www/html

WORKDIR /var/www/html

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

RUN composer install

RUN cp .env.example .env

RUN php artisan key:generate

RUN php artisan optimize

CMD ["php-fpm", "-F"]

nginx/default.conf

server {
    listen 443;
    ssl on;
    root /var/www/html/public;

    ssl_certificate /app/cert.pem;
    ssl_certificate_key /app/key.pem;

    location / {
        try_files $uri /index.php?$args;
    }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass laravel:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }   
}

nginx/Dockerfile

FROM nginx:1.13.9-alpine

COPY . /app

RUN rm /etc/nginx/conf.d/default.conf
COPY default.conf /etc/nginx/conf.d/

docker-compose.yml

version: '2'
services:

  # Note, SSL cert (cert.pem and key.pem) is generated from cloudflare.
  nginx:
    build:
      context: ./nginx
      dockerfile: Dockerfile
    restart: always
    ports:
     - "2053:443"


  laravel:
    build:
      context: ./laravel
      dockerfile: Dockerfile
    restart: always

You can then access Laravel app using

https://localhost:2053/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.