Blue-Green Deployment in Docker Cloud
This post is part of my series about implementing a CI/CD pipeline. Please refer to this post for an introduction and a full table of content. In this post I want to demonstrate step by step how to create a simple Node JS application and run it as a stack in Docker Cloud. This includes creating a repository in GitHub and linking it to a repository in Docker Cloud where we will use the auto build feature to create Docker images of the application. I will also show how to scale and load balance the application for high availability and even discuss how we can exercise blue-green deployment to achieve zero down time deployments.
To not over complicate things we create a simple node JS application consisting of a
package.json file and a
server.js file. The content of the
package.json file is
And the content of the
server.js file looks like this
test command is not important at this point. We will come back to it later down. We can now test this application locally by running
on the command line. If we navigate to localhost in the browser we should see something along this
Note that we are listening on port 80! This is important as we move along.
If we want to Docker-ize the application we need a Dockerfile. The content looks like this
Specifically note how we expose port 80. This will be important once we use a load balancer in front of the sample application in the cloud.
We can now build this Docker Image locally
docker build -t blue-green .
and run an instance (container) of it
docker run -dt --name bg -p 80:80 blue-green
Pushing the code to GitHub
Push the code to a new GitHub repository. In my case I called it
BlueGreen. The repo I use can be found here: https://github.com/gnschenker/BlueGreen I have added a simple
.gitignore file which makes sure node modules are not pushed to GitHub. I also added a
Readme.md for documentation purposes.
Creating a Repository in Docker Cloud
Create a new repository in Docker Cloud and link it to the above GitHub repository. Try to build the repo in Docker Cloud. It should take a minute or so and succeed.
Create a Stack in Docker Cloud
Create a new stack in Docker Cloud and name it appropriately. The content of the
Stackfile should look like this
Here we have a definition for the two services
web. The former one represents our load balancer and the latter our node JS application. The web service will be scaled to 3 instances and since we are using high availability strategy the instances will be put on different nodes of our cluster. We use self-healing in the sense as we require the service instances to restart automatically in case of failure. We also need to assign the role
global to the load balancer such as that the service is able to query the Docker Cloud API.
Running the Stack
We can now deploy and run the stack we just defined. As soon as all services are up and running we can access the endpoint of the stack. Please use the Service endpoint and not the Container endpoint.
If everything went as supposed we should then see something like this
If we refresh the browser a few times we will see that the from server: changes between
web-3 which shows us that our node JS application is indeed load balanced.
High Availability for the Load Balancer
We can now also scale our load balancer such as that it is highly available. For that we should change our
Stackfile to look like this
Note line 3 and 4 that have been added. The former guarantees us that the instances of the load balancer are distributed to different cluster nodes while the latter tells us how many load balancer instances we want to run. After we have redeployed the whole stack we can see in the Node dashboard that indeed every node has now 2 containers on it, one for the load balancer and one for the node application.
Now we want to try to realize zero-downtime or non destructive deployment. This is called blue-green deployment. It basically means that we install the new version of a service in parallel to the current existing one. Once the new version is ready we reroute all traffic to the new version and can then decommission the previous version of the service.
Installing the Docker Cloud CLI
First we need to install the Docker Cloud CLI as described here. With this CLI we can script everything in Docker Cloud. Please note that if you are on a Windows machine it is a bit more complicated than just typing
pip install docker-cloud. We first need to have Python installed on our system. We can do that using Chocolatey.
choco install python2
Now create a folder where you want to install Docker Cloud CLI. Navigate to this folder. And then I had to use the full path to
c:\python27\scripts\pip.exe install docker-cloud
Now we want to start to work with tagged Docker images. For this we have to adjust our repository. If we want to have a tagged image generated then we need to either use branches or tags in GitHub. I prefer to use tags. Let’s say we have a version
v1 and a version
v2 we want to play with then we can just create tags in Git as follows
$ git tag -a v1 -m "Version 1"
This creates a tag
v1 with a description
Version 1 at the current commit. We can then push this tag to origin by using
$ git push origin v1
Now we can modify our repository in Docker Cloud. We can add image tags that refer to Git branches or tags (in our case it is tags)
If we want to introduce blue-green deployment (also called non-destructive deployment) we need to modify our
Stackfile as follows
Here we have instead of one service called
web two services called
web-green. Only one of the two services is active at a given time (that is the load balancer is routing the traffic to it). At the beginning the load balancer is wired to
web-blue. We are starting with both services being in version
v1. We can then redeploy the whole stack and once it is up and running we can test it. We should see this
Upgrade green to v2
Use this command to upgrade
web-green to version
$ docker-cloud service set --image clearmeasure/blue-green:v2 --redeploy --sync web-green
The service will be automatically redeployed. Now we can scale up
web-green to also use 3 instances
$ docker-cloud service scale web-green 3
While we are doing this the application still happily uses
v1 of our node js image.
Switch blue to green
Now it is time to switch from web-blue to
web-green and reroute the load balancer. We can do this using this command
$ docker-cloud service set --link web-green:web-green lb
And then we need to redeploy the load balancer service using this command
$ docker-cloud service redeploy lb
And we’ll have this outcome
If something goes terribly wrong we can just rollback by linking the load balancer again with
web-blue and redeploying it.
In this post I have shown how Docker Cloud can be used to provide CI as well as scalability, high availability and blue-green deployment to us with a few simple operations. Everything can be automated through the docker-cloud CLI.