1

I have a simple Laravel application with Nginx, PHP and MySQL each in its own container. It works great in my development environment but for production I need to remove bind volumes and copy the contents to the image itself instead. But how do I do this?

Do I need a seperate docker-compose-prod.yml file? How can I remove volues for production? How can I copy my source code and configuration to the image when deploying for production?

Here is my docker-compose.yml file

version: '3'

networks:
  laranet:

services:
  nginx:
    image: nginx:stable-alpine

    container_name: nginxcontainer

    ports:
      - "80:80"

    volumes:
      - ./src:/var/www/html
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf

    depends_on:
      - php
      - mysql

    networks:
      - laranet

  mysql:
    image: mysql:5.7.22

    container_name: mysqlcontainer

    ports:
      - "3306:3306"

    volumes:
      - ./mysql:/var/lib/mysql

    networks:
      - laranet

  php:
    build:
      context: .
      dockerfile: php/Dockerfile

    container_name: phpcontainer

    volumes:
      - ./src:/var/www/html

    ports:
      - "9000:9000"

    networks:
      - laranet

and here is my php/Dockerfile

FROM php:7.2-fpm-alpine

RUN docker-php-ext-install pdo pdo_mysql
RUN chown -R www-data:www-data /var/www
RUN chmod 755 /var/www
Liga
  • 3,291
  • 5
  • 34
  • 59

1 Answers1

0

1) copy data only for prod

You can use multistage builds to copy the contents only when you build with the target "prod".

FROM php:7.2-fpm-alpine as base
RUN docker-php-ext-install pdo pdo_mysql
RUN chown -R www-data:www-data /var/www
RUN chmod 755 /var/www

FROM base as dev
VOLUME /var/www/html

FROM base as prod
COPY data /var/www/html
VOLUME /var/www/html

your Docker-compose.yml gets a new line for prod

php:
    build:
      context: .
      dockerfile: php/Dockerfile
      target: prod

container_name: phpcontainer
ports:
  - "9000:9000"
networks:
  - laranet

2) No bind in prod?

would anonymous volumes for dev be a valid solution? e.g. through the definition of VOLUME /var/www/html you specify that the contents of the /var/www/html path should be put into a volume on container start. If no volume is specified in the docker-compose.yml it will create a volume for you. Sweet right?


Sidenote

I do not recommend to split your behavior between dev and prod.

I recommend that you use volumes throughout your stages. The only difference in prod could be that you copy the contents into the image -> before you define the VOLUME, since defining a VOLUME makes the folder unchangeable in the following layers.

david-maze pointed out (see comment)

Putting a VOLUME in your Dockerfile mostly only has confusing side effects, and I'd recommend doing it only if you're absolutely clear on what it means. It's definitely not needed for the OP's setup (and in fact has the likely side effect of leaking anonymous volumes on the production system)


Sources

ckaserer
  • 4,827
  • 3
  • 18
  • 33
  • 1
    Putting a `VOLUME` in your `Dockerfile` mostly only has confusing side effects, and I'd recommend doing it only if you're absolutely clear on what it means. It's definitely not needed for the OP's setup (and in fact has the likely side effect of leaking anonymous volumes on the production system). – David Maze Dec 22 '19 at 10:48
  • Do I also need to copy for nginx as well as php? or only php? – Liga Dec 22 '19 at 11:12
  • Hi Liga, that depends on your use case. I can see in your question that you are using bind volumes for nginx as well. Therefore I assume that you need the data in your nginx container as well. You could create a similar dockerfile to php for your nginx to archive the same behavior. However -> please keep david's comment in mind and make sure not to create orphaned anonymous volumes in your prod environment. – ckaserer Dec 22 '19 at 12:16
  • @ClemensKaserer Can you explain please, why I need the data in both nginx and php? – Liga Dec 22 '19 at 12:27
  • Hi Liga, no I can’t explain why, based on the available information. Can you explain the reason behind nginx volume `/src:/var/www/html` and the php volume `./src:/var/www/html` in your docker-compose.yml? Does it include both your php and html files? Maybe you only need the html files in nginx and the php files in php, but at this point that is pure speculation from my part. – ckaserer Dec 22 '19 at 12:40
  • @ClemensKaserer can I only have one value for nginx? For both html and php files? When I tried that it said it could not find the files. – Liga Dec 22 '19 at 14:36
  • @Liga not sure what you mean. Can you elaborate what you want to accomplish, where you are struggling right now and give an example in your question? – ckaserer Dec 22 '19 at 16:29
  • @ClemensKaserer well, I have a volume bind for nginx and I also have a volume bind for php. But why do I need both? I thought I needed only for nginx. But when I remove the php volume then it doesn't work. Why is that? – Liga Dec 22 '19 at 17:34