Working with Docker-Compose
This article gives you a quick start on how to use docker-compose and scenario in which it will be useful. Compose is a tool for defining and running multi-container Docker applications.
Working with docker-compose
To demonstrate the usage of docker compose, lets create a project whose sole purpose is to show the number of visits to the website.
Prerequistes
- A webserver - Node app
- Redis - to keep track of visits
Solution 1
Single container with node and redis running in it.
Problem
In case of scaling up your application where you have multiple containers running both node and redis in it, one redis instance thinks that page has been visited once whereas others think it has been visited 100 times.
Solution 2
Multiple node containers(containing the web site) talking to the single redis container. Add following files to the project directory where you want your application
1.index.js
const express = require('express');
const redis = require('redis');
const app = express();
const client = redis.createClient();
client.set('visits', 0);
app.get('/', (req, res) => {
client.get('visits', (err, visits) => {
res.send('Number of visits is ' + visits);
client.set('visits', parseInt(visits) + 1);
});
});
app.listen(8081, () => {
console.log('Listening on port 8081');
});
2.package.json
{
"dependencies": {
"express": "*",
"redis": "2.8.0"
},
"scripts": {
"start": "node index.js"
}
}
3.Dockerfile for the node container
FROM node:alpine
WORKDIR /app
COPY ./package.json .
RUN npm install
COPY . .
CMD ["npm","start"]
4.docker-compose.yml
With this we introduce the docker compose. It is used for networking between containers using the docker cli. In above use case we want two containers talking to each other. Docker Compose makes them available to each other without any constratints.
#version of the docker-compose we want to work with
version: '3'
#services refered to containers
services:
#first container
redis-server:
#name of the image
image: 'redis'
#second container
node-app:
#build the container from the current directory and Dockerfile
build: .
ports:
# - in a .yaml file is equivalant to specifying the array
- "8081:8081"
Note: in docker-compose.yml do not use tab, instead use spaces to indent the tags properly
Starting the application with the docker compose
$ docker-compose up -d // -d means run in background
or
$ docker-compose up --build
Stopping the docker-compose
docker-compose down
Managing the container crash with the docker-compose
For automatic container restart we need to specify the restart policy inside a docker-compose.yaml e.g. “no” or “always” or “on-failure” or “unless-stopped” The updated docker-compose.yml file:
version: '3'
services:
redis-server:
image: 'redis'
node-app:
#added a restart policy for one of the container
restart: always
build: .
ports:
- "8081:8081"
Volumes with docker-compose
We have seen how volume works in the last article, now lets see how we introduce the same using docker-compose. A complete docker-compose.yml is as follows:
version: '3'
services:
web:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
volumes:
- /app/node_modules
- .:/app
As mentioned in the previous article on docker that there are many approaches to run many containers at once docker-compose is one of them. Others are listed below
Next steps
- Kubernetes
- Docker Swarm