Docker Compose is one of the most important tools in the Docker toolbox. It was originally used to set up an environment for Continuous Integration.
In the latest release Docker Compose has made a significant leap to the production environment. You can either deploy a single server with Docker Machine or use it to set up an entire cluster using Docker Swarm.
Here’s how to use Docker Compose and Docker Stack.
It is easier to create your stack structure using Docker-Compose files. It can be isomorphic between your environments.
Web, Admin, and API are the names of the services we are going to use on the Docker-Compose API to run our stack.
Use Case (Demo)
Let’s say we have an app that is starting to have more users and we need a way to 1) move it easily to faster servers, 2) to speed up the deployment process, and 3) to make the development environment easier.
First of all we are going to move each service code to docker files using Dockerfile. This gives us the ability to create images that are going to run in production mode.
I have prepared the code for you to use it with Docker Compose. I'll explain the infrastructure, and how to build and run the containers
- API Source
- Web Source
- Admin Source
A Single Service Example: Run API in Docker
This API is based on Node.js. We need to use an image with Node.js installed and ready to run.
This configuration uses a node image from Docker hub registry. This script clones the master branch of the API code, installs dependencies, and exposes a port we are going to use to communicate with the server.
Build the API Service Image, an Example
An image is a set of layers of configurations. It can run many instances called containers.
Docker will build an image named
api-demo with tag
latest. Think of it as a Github repo with the branch name. Now that the image has the source code of the API for our service you now can run one or more containers.
Docker will start a new container from the image
api-demo:latest and will publish port 3100 from inside the container to your host (usually is localhost). To stop the container just press
ctrl+c on your terminal.
Now you can go to
http://localhost:3100 and you may see a response from the API server (if you don't, there may be another service using the same port).
Obviously this is just an example. For this process to actually work, we need to run the database, too, and connect the private network Docker creates. Then add each of the services.
Time to Use Docker Compose
We do not want to manually build, run, stop or destroy every service and add extra configuration to our stack.
The infrastructure of our app can be set in its own Github repository and any kind of production configuration can be updated there.
- Infrastructure Source
Configure API for Production
First step is to set the API as a service. Then we tell Docker Compose to build a new image for us called
appdemoinfra_api:latest from the Docker file. You can find this file in app-demo-infra/Docker/api.
$ docker-compose up
docker-compose up, Docker will build the image. It will then start the API container.
Next time we run this code Docker will not create another image. It will simply use the existing image. If we need to make changes to our Dockerfile, we'll have to make a new image.
Rebuild Service Images
Stop service containers
Docker Compose will look for the file inside the directory and will stop all the services in docker-compose.yml. Be aware of not modifying the file or you will need to stop the containers manually.
Remove service containers
This command stops the containers and removes the network.
At this moment all Docker Compose commands will cause it to look by default
docker-compose.yml but you can use another
Even better, we can mix several Docker Compose files and override configurations of our services from last to first in order.
Add the Rest of the Services
We added a few extra services to the file like web app, admin site, and the database. We want web app and admin site to be single page apps optimized for production. We need an extra configuration to remove all the development code and tools to have lightweight containers without unnecessary files in them.
We also added a MongoDB database with no ports published and only connected to the API service because we want the database to be private.
Other tags were added to the file like depends_on, networks, args to make our stack work properly.
At the end our APP infrastructure repository will look like this,
The benefit of this architecture is that we won't need the source code, only the containers. Besides, it offers better documentation for how our app is designed.
We now have the code ready for production.
$ cd app-demo-infra
$ docker-compose up --build
As you'll notice, there is already an implementation of the development environment and ready to use. It also can be deployed in swarm mode.
$ docker-compose -f docker-compose.yml -f develop.yml build api web admin
$ docker-compose -f docker-compose.yml -f develop.yml up