How to deploy to production when using docker compose?

I heard someone say that…

Docker compose is designed for development NOT for production.

But I have seen people use Docker compose on production with bind mounts. Then pull the latest changes from github and it appears live in production without the need to rebuild. But others say that you need to COPY . . for production and rebuild.

But how does this work? Because in docker-compose.yaml you can specify depends-on which doesn’t start one container until the other is running. If I don’t use docker-compose in production then what about this?

How would I push my docker-compose to production (I have 4 services / 4 images that I need to run). With docker-compose up -d it is so easy.

version: '3'
services:

  # Nginx client server
  nginx-client:
    container_name: nginx-client
    build:
        context: .                  
    restart: always
    stdin_open: true  
    environment:
      - CHOKIDAR_USEPOLLING=true  
    ports:
      - 28874:3000
    volumes:
      - ./client:/var/www
      - /var/www/node_modules
    networks:
      - app-network


  # MySQL server for the server side app
  mysql-server:
    image: mysql:5.7.22
    container_name: mysql-server
    restart: always
    tty: true
    ports:
      - "16427:3306"
    environment:
      MYSQL_USER: root
      MYSQL_ROOT_PASSWORD: BcGH2Gj41J5VF1
      MYSQL_DATABASE: todo
    volumes:
      - ./docker/mysql-server/my.cnf:/etc/mysql/my.cnf
    networks:
      - app-network


  # Nginx server for the server side app
  nginx-server:
    container_name: nginx-server
    image: nginx:1.17-alpine
    restart: always
    ports:
      - 49691:80
    volumes:
      - ./server:/var/www
      - ./docker/nginx-server/etc/nginx/conf.d:/etc/nginx/conf.d
    depends_on:
    - php-server
    - mysql-server
    networks:
      - app-network


  # PHP server for the server side app
  php-server:
    build:
      context: .        
      dockerfile: ./docker/php-server/Dockerfile
    container_name: php-server
    restart: always
    tty: true
    environment:
      SERVICE_NAME: php
      SERVICE_TAGS: dev
    working_dir: /var/www
    volumes:
      - ./server:/var/www
      - ./docker/php-server/local.ini:/usr/local/etc/php/conf.d/local.ini
      - /var/www/vendor
    networks:
      - app-network
    depends_on:
      - mysql-server


# Networks
networks:
  app-network:
    driver: bridge

What you want
– seperation of concerns: strip out the build part and create and use a ci/cd pipeline to trigger builds on git push, build each needed image and push it to a private container registry. Use the images in your docker-compose.yml; use compose for deployments only,
– use a deployment pipeline to deploy your docker-compose stacks
– treat images as fixed artifacts: indeed do COPY the source code and if necessary compile binaries and make them part of the image. It is necessary that a tag results in a specific version (=development state) of your application. Use different tags for dev and production images. Every other approach is a development solution at best.
– Consider to move to multinode docker swarm deployments, rather then single node docker-compose deployments
– Consider using a nfs server to store the details and use volumes to access them, rather then bind mounts - if a container is respawned on a different node, the volume content will be still accessible.
– depends_on will only work for docker-compose, there is no such thing for Docker Swarm or Kubernetes. Make sure you “wait for dependencies” in your entrypoint scripts instead!
– with envsubst you can introduce a simple templating that goes beyond what .env files are capable to do. I posted some examples in the forum on how to leverage it

I have seen Docker Swarm and Kubernetes beeing used in production.While you encounter Kubernetes practicaly everywhere, Swarm is rarely seen. While Swarm uses compose.yml files, Kubernetes uses a bunch of yml based manifest files to archive the same (to be fair: it is way more powerfull than Swarm) or Helm Charts (which you have to write yourself for your own apps).