Let's take for example a mobile application who depends on two or more API.
Each of these projects are separated in independent Git repositories. Then we have 3 repositories allowing us to develop each in parallel.
Each projects have their own dependencies:
- First API, for example, requires a SQL database
- Second API, requires a NoSQL database
- The mobile app requires these two APIs
Now I want to "dockerize" all of these projects to simplify development environment and unify it between developers and/or production environment.
Currently in each project we can create a custom docker-compose.yml file working with each projects requirements.
For example in the 1st API
version: "3.7"
services:
first_api:
image: golang:1.13
working_dir:
- /src
depends_on:
- mysql
volumes:
- ".:/src"
command: go run main.go
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_USER_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE_NAME}
adminer:
image: adminer
restart: always
The second API will have a similar docker-compose.yml file but with NoSQL DB instead.
Then in the mobile app repository we will have a docker-compose.yml file with a lot of duplicated code (and exactly same containers) because of its interdependence with the two other API, an some other file identicals (e.g .env files, entrypoint scripts if needed...).
The databases setup/seeding will be also done on 2 repositories too, that can be a little annoying.
The docker-compose.yml file will look like something like this:
version: "3.7"
services:
app:
build:
context: .
args:
- IP=${IP}
ports:
- 19000:19000
- 19001:19001
- 19002:19002
volumes:
- ".:/app"
depends_on:
- first-api
- second-api
first-api:
image: my-registry:5000/first-api
ports:
- 9009:3000
depends_on:
- mysql
volumes:
- ".env:/dist/.env"
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_USER_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE_NAME}
adminer:
image: adminer
restart: always
ports:
- 9099:8080
second-api:
image: my-registry:5000/second-api
ports:
- 9010:3000
depends_on:
- mongo
mongo:
image: mongo
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: ${MONGO_ROOT_USERNAME}
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ROOT_PASSWORD}
mongo-express:
image: mongo-express
restart: always
ports:
- 8081:8081
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: ${MONGO_ROOT_USERNAME}
ME_CONFIG_MONGODB_ADMINPASSWORD: ${MONGO_ROOT_PASSWORD}
In fact in this final docker-compose file we have 4 containers definition totally identical with them inside API's configurations, we also have some environment variables duplicated and versioned in 2 repositories minimum.
Sometime we can also have Dockerfile duplicated, according to specifics cases, DB setup or something too.
Did I miss something somewhere in this Docker development environment setup that would allow me to avoid some duplication?
Is there a best practice or a recommendation to avoid this?
How companies with big interdependent micro-services architecture manage these interdependence?