There are many approaches to implementing a reuse of a common preset for Docker services for multiple environments, such as production and local environments.
This makes it possible to ensure the highest consistency for different environments with the same code-base. Implementing reuse of docker compose options also makes it easier to manage them.
I found on github a project called serversideup/spin. They took an approach using a feature called Docker overrides, to change some properties of common services for different environments.
After reading through their documentation, I realized that there are a few real-life cases where this project can not implement (or is difficult to archive).
That's why I decided to talk to the project owner and create this gists, for testing and discussion purposes.
If you would like supporting my projects, buy me a coffee 😉.
I really appreciate your love and supports.
Let's assume that we need to build the following environments with the same code-base using the popular framework Laravel. The general requirement is that they should be as consistent as possible, and easy to operate.
- Use a redis instance as a cache service
- Limit size of log files for all containers
- Automatically restart the container when it fails
- Simply launch docker for different environments
- Friendly with docker compose CLI
- One web backend can scale to many instances
- Use traefik as gateway, support HTTP and HTTPS
- No need for other services like mysql, phpmyadmin attached
- Two instances for web backend to test 2 different branches of code
- The first web backend runs on port 8001
- Second web backend running on port 8002
- Use additional mysql, phpmyadmin services for local development
- phpmyadmin running on port 8080
- No need to use traefik as gateway as each backend runs on its own port
- A web backend instance, running on port 80
- A blackfire service for profiling web backend
- Use additional mysql, phpmyadmin services for local development
- phpmyadmin running on port 8080
- No need to use traefik as gateway as each backend runs on its own port
This setup should follow the official Docker guidlines as much as possible.
I was able to easily implement the above requirements in a simple way following the following concept structure.
./
┝━ services.yml
┝━ docker-compose.prod.yml
┝━ docker-compose.local.yml
┝━ docker-compose.debug.yml
┝━ webroot/
┝━ dev-1/
┝━ dev-2/
┝━ debug/
└─ dcom.sh
-
services.yml
contains definitions for all services -
docker-compose.prod.yml
contains services forproduction
-
docker-compose.local.yml
contains services forlocal
-
docker-compose.debug.yml
contains services fordebug
-
webroot/
contains source code forproduction
-
dev-1/
anddev-2/
contain contain source code forlocal
-
debug/
contains source code fordebug
-
dcom.sh
is a wrapper script for docker compose
As a result, you can easily run a single command to start all the necessary services for each predefined environment with docker compose.
For example, to run services for the production
environment:
docker-compose -f docker-compose.prod.yml up -d
Very simple, right?
You don't need any other shell script, nor do you need to remember complicated command syntax to run it.
You might be wondering: "What is the shell script dcom.sh
for?", am I right?
This is a wrapper to shorten your command line. dcom
is short for "docker-compose".
We use it like this:
./dcom.sh env_name [arguments]
For example, to run services for the production
environment:
./dcom.sh prod up -d
The parameter for dcom.sh
is fully compatible with docker-compose
interface.
./dcom.sh prod up -d
Q: I am running this on
production
environment. As mentioned on the Use case, I want to run the service backend in 2 different instances onproduction
, how can I do that?
A: It's very simple, you just need to run the command below, traefik will act as a load balancer for those instances intelligently.
./dcom.sh prod up -d --scale backend=2
Then check all running services with this:
./dcom.sh prod ps
Ref: Docker Compose CLI reference
If you like this project, please support my works 😉.
From Vietnam 🇻🇳 with love.
@jaydrogers
Specifically, after going through your example, I am confused as to why create 2 docker-compose files when I can simply use just
docker-compose.dev.yml
. I'm not saying your concept is incorrect, please don't misunderstand me.From a DevOps point of view, I don't really see the point of creating a
docker-compose.yml
file in your example. For me, in most practical cases, I just bring the contents of thedocker-compose.yml
file into thedocker-compose.dev.yml
file, it should work! Then I may not need spin because the docker-compose command has also become simpler.In other cases, your wordpress example, I find the docker-compose files for various environments are mostly written quite differently, which means the reusability of those environments is low, and they will lack of consistency. At that time, I thought that overriding the base
docker-compose.yml
file was not necessary anymore.Last but not least.
I believe you will be able to gradually improve this project, and in the future it will not only be used for development, but can be more flexible for medium and large projects to use.
Regards.