Docker - deliver the code to nginx and php-fpm

Viewed 1669

How do I deliver the code of a containerized PHP application, whose image is based on busybox and contains only the code, between separate NGINX and PHP-FPM containers? I use the 3rd version of docker compose.

The Dockerfile of the image containing the code would be:

FROM busybox

#the app's code
RUN mkdir /app

VOLUME /app

#copy the app's code from the context into the image
COPY code /app

The docker-compose.yml file would be:

version: "3"
services:
  #the application's code
  #the volume is currently mounted from the host machine, but the code will be copied over into the image statically for production
  app:
   image: app
   volumes:
    - ../../code/cms/storage:/storage
   networks:
    - backend

  #webserver
  web:
   image: web
   depends_on:
    - app
    - php
   networks:
    - frontend
    - backend
   ports:
    - '8080:80'
    - '8081:443'

  #php
  php:
   image: php:7-fpm
   depends_on:
    - app
   networks:
    - backend

networks:
 cms-frontend:
   driver: "bridge"
 cms-backend:
   driver: "bridge"

The solutions I thought of, neither appropriate:

1) Use the volume from the app's container in the PHP and NGINX containers, but compose v3 doesn't allow it (the volumes_from directive). Can't use it.

2) Place the code in a named volume and connect it to the containers. Going this way I can't containerize the code. Can't use. (I'll also have to manually create this volume on every node in a swarm?)

3) Copy the code twice directly into images based on NGINX and PHP-FPM. Bad idea, I'll have to maintain them to be in concert.

Got stuck with this. Any other options? I might have misunderstood something, only beginning with Docker.

2 Answers

I too have been looking around to solve a similar issue and it seems Nginx + PHP-FPM is one of those exceptions when it is better to have both services running in one container for production. In development you can bind mount the project folder to both nginx and php containers. As per Bret Fisher's guide for good defaults for php: php-docker-good-defaults

So far, the Nginx + PHP-FPM combo is the only scenario that I recommend using multi-service containers for. It's a rather unique problem that doesn't always fit well in the model of "one container, one service". You could use two separate containers, one with nginx and one with php:fpm but I've tried that in production, and there are lots of downsides. A copy of the PHP code has to be in each container, they have to communicate over TCP which is much slower than Linux sockets used in a single container, and since you usually have a 1-to-1 relationship between them, the argument of individual service control is rather moot.

You can read more about setting up multiple service containers on the docker page here (it's also listed in the link above): Docker Running Multiple Services in a Container

The way I see it, you have two options:

(1) Using Docker-compose : (this is for very simplistic development env)

You will have to build two separate container from nginx and php-fpm images. And then simply serve app folder from php-fpm on a web folder on nginx.

# The Application
  app:
    build:
      context: ./
      dockerfile: app.dev.dockerfile
    working_dir: /var/www
    volumes:
      - ./:/var/www
    expose:
      - 9000
  # The Web Server
  web:
    build:
      context: ./
      dockerfile: web.dev.dockerfile
    working_dir: /var/www
    volumes_from:
      - app
    links:
       - app:app
    ports:
      - 80:80
      - 443:443

(2) Use a single Dockerfile to build everything in it.

  • Start with some flavor of linux or php image
  • install nginx
  • Build your custom image
  • And serve multi services docker container using supervisord
Related