Docker Compose v3 – Production Ready

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.

Stack Structure

It is easier to create your stack structure using Docker-Compose files. It can be isomorphic between your environments.

Services

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
https://github.com/jrsalgado/api-demo
Web Source
https://github.com/jrsalgado/web-app-demo
Admin Source
https://github.com/jrsalgado/admin-demo

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 build -t api-demo:latest .

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 run -it --rm -p "3100:3100" api-demo:latest

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
https://github.com/jrsalgado/app-demo-infra

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.

$ cd app-demo-infra
$ docker-compose up

After running 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

$ docker-compose build --no-cache

Stop service containers

$ docker-compose stop

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

$ docker-compose down

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 .yml file,

$ docker-compose -f ./other_directory/other_file.yml up

Even better, we can mix several Docker Compose files and override configurations of our services from last to first in order.

docker-compose -f docker-compose.yml -f ./other_directory/other_file.yml up

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,

app-demo-infra
-docker-compose.yml
-Docker
--admin
---Dockerfile
--api
---Dockerfile
--web
---Dockerfile

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.

It's Alive!

We now have the code ready for production.

$ git clone https://github.com/jrsalgado/app-demo-infra.git
$ cd app-demo-infra
$ docker-compose up --build

Next Steps

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.

# build service images for development environment
$ docker-compose -f docker-compose.yml -f develop.yml build api web admin
$ docker-compose -f docker-compose.yml -f develop.yml up

 

Share this post

Table of Contents