2

I'm having some trouble conceptually with an Nginx configuration. Starting with an nginx SSL-terminator reverse-proxy, I use a docker-compose.yml setup with a few containers, each providing a virtual service. These services are provided as subdirs under a single hostname:

net --443--> nginx
             | | `--- ContainerA "https://example.com/serviceA/"
             | `----- ContainerB "https://example.com/serviceB/"
             `------- ContainerC "https://example.com/serviceC/"

Snippets of process lists:

nginx:~$ ps fax
127285 ?        Ss     0:00  nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf -g daemon off;
127419 ?        S      0:00   \_ nginx: worker process
127420 ?        S      0:00   \_ nginx: worker process
127421 ?        S      0:00   \_ nginx: worker process

ContainerA:~$ ps fax
127132 ?        Ss     0:09  php-fpm: master process (/etc/php/7.0/fpm/php-fpm.conf)
234053 ?        S      8:27   \_ php-fpm: pool www
236952 ?        S      8:12   \_ php-fpm: pool www
259123 ?        S      6:42   \_ php-fpm: pool www

I thought there would be efficiency gained by running a single instance of nginx, and using php-fpm in each of the containers.

I think that the premise of php-fpm is such that the containers do not need their own nginx processes; the nginx processes communicates with each container over port 9000 (the network part works). In practice, though, I'm having trouble, so I need to verify that my premise is sound:

Is this assumption of a basic nginx and php-fpm architecture correct? Alternatively, is a proper nginx/php-fpm infrastructure intended to use php-fpm in direct concert (same host and filesystem) or is multi-hosting/multi-filesystem reasonable and efficient?

(I recently reached out to contract some help, and their first response was "you need to run nginx in each container", which didn't make sense to my understanding of php-fpm.)

(There are plenty of questions here that ask specific nginx.conf questions, not about this admittedly higher-level architecture.)

0

This is a weak answer, but I believe:

Yes, this is in general the right philosophy, but with some caveats. php-fpm is there for processing .php files, but I think not for serving all (non-php) files. For that, the front-facing nginx process needs to see all files, even if it does not do the actual PHP processing.

For this to happen smartly using docker, the files in the php-fpm container need to be shared explicitly with the nginx container. The preferred way to do this in docker is to provide a named volume and use it for both containers. For instance, a docker-compose.yml file:

version: '2'
services:
  serviceA:
    image: ... # something served with php-fpm
    volumes:
    - tmpvolA:/path/to/serviceA
  serviceB:
    image: ... # something served with php-fpm
    volumes:
    - tmpvolB:/path/to/serviceB
  nginx:
    image: ...
    volumes:
    - tmpvolA:/var/www/serviceA
    - tmpvolB:/var/www/serviceB
volumes:
  tmpvolA:
  tmpvolB:

(Many many fields are not included ...) The two volumes listed at the end are the "named volumes" of which docker speaks, and are empty for a reason: they are intended to be empty when you start the script, and will be filled by one of the containers. (Actually, it may be filled by both or neither, depending on several factors.)

One side-effect of this is that the volumes persist.

  • "This is good" for efficiency, in that it is not recreated needlessly.
  • "This is bad" because one benefit of having virtualized services is that you can restart it and be guaranteed a clean slate. With persistent named volumes, you do not (automatically) get a clean slate, since the files used in the previous instance will be used instead of the austere version in a lower fs layer.

The way around this "bad" is to flush the volumes manually. This can be done either on shutdown with docker-compose down -v, which per the help:

    -v, --volumes       Remove named volumes declared in the `volumes` section
                        of the Compose file and anonymous volumes
                        attached to containers.

It can also be done manually with docker volume rm <volume-id> or docker volume prune (which removes all currently-unused volumes, whether temporary or named or whatever).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.