At some point docker-compose file gets complicated and we need to version control it. the typical directory structure looks like this:
todo
├── .env
├── docker-compose.yml
├── todo-api/
├── todo-worker/
└── todo-database/
and our docker-compose.yml file is like this:
# todo/docker-compose
version: '3.1'
services:
  todo-database:
    image: postgres:11.3
    volumes:
      - ./todo-database:/docker-entrypoint-initdb.d/
    environment:
      POSTGRES_PASSWORD: $POSTGRES_PASSWORD
  todo-api:
    build: ./todo-api
    environment:
      APP_KEY: $APP_KEY
      DATABASE_URL: postgres://postgres:${POSTGRES_PASSWORD}@todo-database:5432/postgres
  todo-worker:
    build: ./todo-worker
    environment:
      DATABASE_URL: postgres://postgres:${POSTGRES_PASSWORD}@todo-database:5432/postgres
and here is our .env file
# todo/.env
POSTGRES_PASSWORD=secret-1
APP_KEY=secret-2
So how we can version control it?
One way to do it is by creating todo-compose/ folder and moving .env and docker-compose.yml files to todo-compose/ so we can initialize a git repo in it
$ mkdir todo-compose
$ mv docker-compose.yml .env todo-compose/
then we rename .env to .env.example and remove all passwords in it so we can use it as a reference. now todo-compose/ should be like this:
todo-compose
├── .env.example
└── docker-compose.yml
because we moved docker-compose.yml file to its own folder, we will have to modify each service build and volume keys to move up one directory like this:
# todo/todo-compose/docker-compose.yml
version: '3.1'
  # ...
  todo-database:
    volumes:
      - ../todo-database:/docker-entrypoint-initdb.d/
  # ...
  todo-api:
    build: ../todo-api
  # ...
  todo-worker:
    build: ../todo-worker
  # ...
but can we do better? it turns out that we can use symbolic links to make docker think that docker-compose.yml exists in todo/ while in reality it is inside todo/todo-compose/
$ ln -s todo-compose/docker-compose.yml ./docker-compose.yml
now we copy our .env.example reference file to todo/
$ cp todo-compose/.env.example ./.env
next we modify our newly created .env to contain project passwords. now our directory structure should be like this:
todo
├── .env
├── docker-compose.yml -> todo-compose/docker-compose.yml
├── todo-compose/
│   ├── .env.example
│   └── docker-compose.yml
├── todo-api/
├── todo-worker/
└── todo-database/
One benefit that this method has is if you have multiple docker files like this:
todo-compose
├── .env.example
├── docker-compose.yml/
├── docker-compose.prod.yml/
└── docker-compose.dev.yml/
and you were issueing docker-compose -f docker-compose.yml -f docker-compose.dev.yml up in development and docker-compose -f docker-compose.yml -f docker-compose.prod.yml up in production. now you just have to do
# in development
$ ln -s todo-compose/docker-compose.yml ./docker-compose.yml
$ ln -s todo-compose/docker-compose.dev.yml ./docker-compose.override.yml
# in production
$ ln -s todo-compose/docker-compose.yml ./docker-compose.yml
$ ln -s todo-compose/docker-compose.prod.yml ./docker-compose.override.yml
then you can use the same command docker-compose up for development and production
this post first appeared at https://ducaale.github.io
 

 
    
Top comments (0)