anon
anon

Reputation:

How to use docker-compose yml file for production?

I have a docker application on my localhost which works fine. I am running PHP, Nginx and Mariadb on it.

The docker-compose.yml file which containes this code:

version: '3'

services:
    db:
      build:
        context: ./mariadb
      volumes:
          - "./.data/db:/var/lib/mysql"
          - "./logs/mariadb:/var/log/mysql"
      environment:
          MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
          MYSQL_DATABASE: ${MYSQL_DATABASE}
          MYSQL_USER: ${MYSQL_USER}
          MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      networks:
        - default
    php-fpm:
      build:
          context: ./php7-fpm
          args:
              TIMEZONE: ${TIMEZONE}
      volumes:
          - ${APP_PATH}:/var/www/app
      environment:
          DB_HOST: db
          DB_PORT: 3306
          DB_DATABASE: ${MYSQL_DATABASE}
          DB_USERNAME: ${MYSQL_USER}
          DB_PASSWORD: ${MYSQL_PASSWORD}
      depends_on:
        - db
      networks:
        - default
    nginx:
      build:
        context: ./nginx
        args:
          - 'php-fpm'
          - '9000'
      volumes:
        - ${APP_PATH}:/var/www/app
        - ./logs/nginx/:/var/log/nginx
      ports:
        - "80:80"
        - "443:443"
      depends_on:
        - php-fpm
      networks:
        - default
networks:
  default:
    driver: bridge

At first I thought there was only one compose file required, and when I built the image, pushed it to docker hub and then pulled that image on my production server, the container failed to launch.

I did some reading and there are many online sources suggesting to use, from 1 to 4 docker file, and to check out two git branches.. among other things ...

I understand that I should at least create one more file called docker-compose-prod.yml, and in that file, I should omit the volumes: and port: attributes, but it seems there is no clear guide on:

  1. how to make docker work on local

  2. exactly when and how to build a container for production.

Can someone clear this up for me please?

Upvotes: 15

Views: 7557

Answers (1)

atline
atline

Reputation: 31674

Suggest you to use Multiple Compose files:

Using multiple Compose files enables you to customize a Compose application for different environments or different workflows.

Next is an example:

(NOTE: next omit some elements of compose file)

docker-compose.yml:

web:
  image: example/my_web_app:latest

docker-compose.dev.yml:

web:
  ports:
    - 80:80
  • Execute docker-compose -f docker-compose.yml -d will have no ports map.
  • Execute docker-compose -f docker-compose.yml -f docker-compose.dev.yml -d will make docker-compose.dev.yml to override some value of docker-compose.yml which make your aims.

For detail, refers to docker doc, it is the official suggestion to handle your scenario, FYI.

UPDATED:

You use build: context: ./mariadb, so compose can always find Dockerfile in the folder mariadb to build, no matter in local dev server or prod server.

Just above will have image build both on dev & prod server, this is one option for you to follow.

Another option as you said in comments:

But on prod server, I can only pull and run image, and the image would have to be built with the prod yml file beforehand

So you may not want to build image again on prod server?

Then, next is a updated solution, just an example:

docker-compose.yml:

db:
  image: your_maridb_image_name:your_maridb_image_version
  networks:
    - default

docker-compose.dev.yml:

db:
  build:
    context: ./mariadb
  ports:
    - "xxx:xxx"

docker-compose.prod.yml:

db:
  otheroptions_special_for_prod_just_a_example: xxx

1) docker-compose -f docker-compose.yml -f docker-compose.dev.yml -d

This will combine as next:

db:
  image: your_maridb_image_name:your_maridb_image_version
  networks:
    - default
  build:
    context: ./mariadb
  ports:
    - "xxx:xxx"

Per docker-compose syntax, if build:context was afford, compose will not docker pull image from docker registry, just find the Dockerfile in context, and finally build a image with the name your specified in image, here it's your_maridb_image_name:your_maridb_image_version.

Then, you need to push it dockerhub, but you do need to stop your local container.

2) docker-compose -f docker-compose.yml -f docker-compose.prod.yml -d

This will combine as next:

db:
  image: your_maridb_image_name:your_maridb_image_version
  networks:
    - default
  otheroptions_special_for_prod_just_a_example: xxx

Per docker-compose syntax, no build:context was afford, so compose will directly docker pull image from remote registry(docker hub), remember you have pushed the image to dockerhub after you finished the development on local dev server? So no need to build image again.

Upvotes: 12

Related Questions