How to remove Docker volumes for production and COPY instead?

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?

I understand that the rule is that a production container should be immutable. Correct?

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

Here is a sample of a docker compose file I use from an php application :

version: '3.3'
networks:
  app:
volumes:
  app:
configs:
  nginx:
    file: nginx.conf
services:
  nginx:
    image: nginx:alpine
    configs:
      - source: nginx
        target: /etc/nginx/nginx.conf
    volumes:
      - app:/var/www
    networks:
      - app
    depends_on:
      - app
    ports:
      - "80:80"
  app:
    image: myphpapp
    networks:
      - app
    volumes:
      - app:/var/www

My “myphpapp” image store the application under /app and have an entrypoint script that check if the directory /var/www contain this version of the application and otherwise copy the whole /app to /var/www. This way both containers does see the application content (throw the app volume) while only one image have been created.
This way all you have to give for production is : the compose file and the nginx configuration everything else is within the myphpapp image.

@sebt3 I’m not sure I understand this. I think I need to bind volumes for development environment and I need to copy for production, correct?

Nope, use the same strategy for dev and prod uses.
Have your app inside one of the 2 images so dont use local volumes…

@sebt3 If I have my app source code inside an image, won’t that mean that I have to re-build the image every time I make a change to my code? That makes development very difficult.

Well, all you have to do, is setup a CI/CD chain to build the images for you. Once done, a commit will generate your image.
Beside, on your developement host, nothing stop you from copying your current changes to :

docker volume inspect app -f '{{.Mountpoint}}'

which will have the same behaviour as your current setup

Le lun. 23 déc. 2019 à 10:59, Martin Zeltin via Docker Forums docker@discoursemail.com a écrit :

Thanks for this. This worked exactly as expected.

docker containers by default do not contain any kind of persistence storage!