Nginx – Serve static content using docker + nginx + php-fpm

dockernginxphp-fpmstatic-content

I'm trying to configure a php webapp using docker. The idea is to run the app using php-fpm in a standalone container and have another container that will run nginx. The idea for this setup is to use that same nginx container to proxy requests to other webapps that are already working on the same machine.
The problem is that I can't get nginx to properly process static files (js, css, etc.), as the requests to those keep going to fpm.

This is what the filesystem looks like:

/
├── Makefile
├── config
│   └── webapp.config
└── webapp
    └── web
        ├── index.php
        └── static.js

I'm running the whole thing using a Makefile that looks like this (not interested in docker-compose for this):

PWD:=$(shell pwd)
CONFIG:='/config'
WEBAPP:='/webapp'

run: | run-network run-webapp run-nginx

run-network:
    docker network create internal-net

run-webapp:
    docker run --rm \
    --name=webapp \
    --net=internal-net \
    --volume=$(PWD)$(WEBAPP):/var/www/webapp:ro \
    -p 9000:9000 \
    php:5.6.22-fpm-alpine

run-nginx:
    docker run --rm \
    --name=nginx \
    --net=internal-net \
    --volume=$(PWD)$(CONFIG)/webapp.conf:/etc/nginx/conf.d/webapp.domain.com.conf:ro \
    -p 80:80 \
    nginx:1.11.0-alpine

This is what my config/webapp.conf looks like.

server {
    listen 80;
    server_name webapp.domain.com;

    # This is where the index.php file is located in the webapp container
    # This folder will contain an index.php file and some static files that should be accessed directly
    root /var/www/webapp/web;

    location / {
        try_files $uri $uri/ @webapp;
    }

    location @webapp {
        rewrite ^(.*)$ /index.php$1 last;
    }

    location ~ ^/index\.php(/|$) {
        include fastcgi_params;

        fastcgi_pass webapp:9000;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;

        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTPS off;
    }
}

Whatever action that needs to get processed using that index.php file will work. However, static files won't be served, resulting in nasty 404 errors (as the php webapp doesn't really have routes configured for those). I believe nginx tries to load those from its own container filesystem, when they are actually in the webapp container, failing back into @webapp.

Is there a way I can configure nginx to serve those files that reside in another container?

Best Answer

I managed to solve the problem by mounting the webapp volume in the nginx container. This is what the run-nginx job looks like now:

run-nginx:
    docker run --rm \
    --name=nginx \
    --net=internal-net \
    --volume=$(PWD)$(CONFIG)/webapp.conf:/etc/nginx/conf.d/webapp.domain.com.conf:ro \
    --volume=$(PWD)$(WEBAPP)/web:/var/www/webapp/web:ro \
    -p 80:80 \
    nginx:1.11.0-alpine

And this is the webapp.conf file, that will try to load the static files from the container and, if that's not possible will proxy the request to the fpm worker:

server {
    listen 80;
    server_name webapp.domain.com;

    root /var/www/webapp/web;

    location ~ \.(js|css|png) {
        try_files $uri $uri/;
    }

    location / {
        rewrite ^(.*)$ /index.php$1 last;
    }

    location ~ ^/index\.php(/|$) {
        include fastcgi_params;

        fastcgi_pass webapp:9000;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;

        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTPS off;
    }
}

However, I'd like to know if there's a better way to do so instead of sharing the same volume twice. Thanks a lot!