Rolling update with docker-compose
This article covers simple steps to perform rolling update with docker-compose with an example. If you are using docker-compose file in combination with docker swarm, you will probably get rolling update feature out of the box. Otherwise to perform rolling-update with only docker-compose is bit tricky.
Assumptions/ Prerequisites
- You have golang installed on your machine. (If you are using the example from this page for testing)
- You have Docker cli, runtime installed on your machine.
- You have docker-compose cli installed on your machine.
- Your machine is connected to internet.
Steps to follow
If you alredy have docker-compose file and application directly jump to step 4. Otherwise follow from step 1.
1. Creating 2 docker images of a sample golang application.
Follow this article to create docker image with golang app inside it.
Create 2 images, for simplicity lets name them testgoapp:old
and testgoapp:new
. You can change the text printed by helloworld
function to differentiate between 2 images.
2. Creating a docker image with nginx as reverse proxy
Now we will create a docker image which can run nginx as reverse proxy. We will hardcode nginx's config to use goapp from above step as backend server.
For this follow below steps.
a. Create a file nginx.conf
and save following text in it.
1server {
2 // To listen on port 8080
3 listen 8080;
4 root /data/up1;
5
6 location / {
7 //Configuring backend server as goapp.
8 // goapp will later be resolved to goapp container ip(s) by docker's dns
9 set $backend_servers goapp;
10 proxy_pass http://$backend_servers:8080;
11 }
12}
13// Docker's embedded dns server
14resolver 127.0.0.11 valid=5s;
b. Create a file DockerfileNginx
and save following text in it.
1FROM nginx:1.19
2COPY nginx.conf /etc/nginx/conf.d/site.conf
3CMD ["nginx", "-g", "daemon off;"]
c. Run the following command to create docker image for nginx.
1docker build -t testnginx -f DockerfileNginx .
3. Running the nginx and goapp together using docker-compose
a. Create a file docker-compose.yml
and save following text in it.
1version: "3.3"
2
3services:
4 nginx:
5 image: testnginx
6 depends_on:
7 - goapp
8 ports:
9 - "8000:8080"
10 goapp:
11 image: testgoapp:old
b. Bring up the applications by running following command
1cd /path/where/docker/compose/file/is
2docker-compose up -d
If every thing worked you should be able to reach helloworld endpoint in web browser with http://localhost:8000/helloworld
4. Performing rolling update
Now comes the intersting part where you will update the goapp to newer version, without having downtime. Follow below steps.
a. Update docker-compose.yml
file to use testgoapp:new
image.
1version: "3.3"
2
3services:
4 nginx:
5 image: testnginx
6 depends_on:
7 - goapp
8 ports:
9 - "8000:8080"
10 goapp:
11 image: testgoapp:new
b. Scale the goapp
to 2 instance using below command
1docker-compose up -d --scale goapp=2 --scale nginx=1 --no-recreate
This step makes sure that your old go application is not removed but the new golang application is added.
If every thing worked you should be able to reach http://localhost:8000/helloworld
c. Remove the old golang app manually running below command
1docker container ls
2#copy the old container id
3docker container rm -f <old-container-id>
If every thing worked you should be able to reach http://localhost:8000/helloworld
, and will see the message from new application.
d. Clean up docker-compose state by running the following command
1docker-compose up -d --scale goapp=1 --scale nginx=1 --no-recreate
If every thing worked you should be able to reach http://localhost:8000/helloworld
, and will see the message from new application.
In Conclusion, rolling update with docker-compose is possible but not very clean. You need to modify the above commands to match your setup if you are not using the example setup.