How to use docker-compose yml file for production?
Asked Answered
V

1

14

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?

Vestryman answered 10/10, 2018 at 1:6 Comment(0)
B
11

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.

Bugbee answered 10/10, 2018 at 2:16 Comment(9)
Thanks, I will try your code later, as I just asked a new question about what attr to remove for my dev file to make a prod one. I have no clue aside from removing volumes and ports.....Vestryman
... your answer is clear and simple but I don't understand one thing. When/Where do I use docker-compose for the production one (the first execute)?? because I understand on local, I can use the second execute, and it would merge the two files, and I would have a compose files with ports, volumes and all is ok, 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 how do I do that in local once I finished making my app? do I stop docker then build it with prod.yml then push it?Vestryman
For your first comment: Indeed I do not know how to delete an option, but you may always set up a minimal docker-compose.yml with the least common options there, then put different things to docker-compose-dev.yml & docker-compose-prod.yml, this just a workaround, see if anyone can help you in your new question.Bugbee
For your second comment: I'm a little confused, 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. But maybe you do want to build again for mariadb on product server? If it's your aim, see updated answer.Bugbee
Oh, thanks for answering I have been trying to make docker work now 3 weeks, just a quick question, have you ever encountered [emerg] 1#1: host not found in upstream "php-fpm:9000" in /etc/nginx/conf.d/upstream.conf:1 error? I have been on this ALL day until now and it might be the reason my app is not working. The issue is related from this and this files. everything works on local, but on prod nginx exits due to that error,Vestryman
I think if I fix that error, everything will be fine. I have been looking for that error on every google link that exists until I ran out but still can't fix it. I don't know what is wrong with my appVestryman
Are you sure php-fpm is a hostname of your one pc? Check your /etc/hosts to add binding or just use ip? You can ping php-fpm in your container to confirm that. Anyway it is really another question.Bugbee
Yeah, I think that is how it is done. I am used to localhost or 127.0.0.1 but it turns out in docker, it is different. Yes, I will get back to your answer as soon as I fix this blocking issueVestryman
I added bounty to draw attention, hope you can include more?? thanksVestryman

© 2022 - 2024 — McMap. All rights reserved.