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.
Thanks Shin!
Thanks for your interest in
spin
. You have some great ideas and points here.Long story short:
Yes,
spin
will work with any Docker Compose file as long as it the directory looks like:If you have more environments, I could possibly add a
spin --env=debug up
, which would result in:The only trick would be getting your
services.yml
file in there (not sure if I have to include that in the command or if it will automatically grab it from the instruction in the YML).Responding to your questions
Here are my responses to your questions:
General requirements
Check this for an example: https://serversideup.net/open-source/spin/common-services/redis
We run Docker Swarm in production. It just ties into your "docker logs" which can be centralized and cleaned up nicely.
Docker Swarm has this built-in: https://docs.docker.com/config/containers/start-containers-automatically/
Spin does this (just basically a shortcut to
docker-compose.dev.yml
), but the different environments is at our core: https://serversideup.net/open-source/spin/getting-started/introductionSpin passes the commands to
docker compose
and simply just lets Docker do the rest of the work: https://serversideup.net/open-source/spin/getting-started/introductionProduction
You can do that with Docker Swarm: https://docs.docker.com/engine/swarm/admin_guide/
We ❤️ Traefik! https://serversideup.net/open-source/spin/common-services/traefik
Just add what you need in your compose files 😃
Local
Not sure if I fully understand this? You could technically do that by just changing the volume of the webserver that you're running. The only challenge is different branches... It would have to be separate folders or submodules.
Yup, just add it in your
docker-compose.dev.yml
.Definitely easy to do: https://hub.docker.com/_/phpmyadmin
Since we run Traefik in production, we also run it in development. We try to minimize surprises that way 😅
Debug
Yup, just add to docker-compose.dev.yml
Never heard of this, but it looks cool 🤓