Docker Swarm
For the foreseable future we will be using docker swarm to manage our servers. Below is a documentation of how to set it up and add nodes when needed.
Setup Docker Swarm
To begin we need to define a manager node by running the following command on the main server
docker swarm init --advertise-addr <server_ip_here> --default-addr-pool "14.0.0.0/20"
For a single node swarm. We do not need this option --advertise-addr <server_ip_here>.
The default-addr-pool is the range of IP addresses that are available for automatic assignment to containers. Use the value of 14.0.0.0/20 for the default pool, unless you have a specific reason to change it.
This command prints out a token for use when adding other nodes to the swarm.
Joining the Swarm
To add another node/server to the manager node for horizontal scaling, we run the following command
docker swarm join --token token_from_previeous_step <ip_of_manager_node:port>.
If you no longer have the token, you can get it again by logging into the manager node and running the following command.
docker swarm join-token worker
Building Images
On staging we can continue manually building our images before using the swarm to deploy the app. This way we don’t store more images than necessary on the ECR.
For production however, we can configure the CI to build, tag, and push new images to the ECR.
Remember to increase the version of updated services before building/pushing images.
Using SemVer(x.y.Z).
For staging changes/deployment increment Z on both staging and build compose files.
For production deployment increment y and reset Z to 0 staging, build, prod compose files
Deploying Services to the Swarm
There are multiple ways to create a service on docker swarm, using docker service and using docker stack. We will be making use of docker stack here inorder to reuse our existing compose files.
We have several compose files for different purposes.
- docker-compose.build.yml: This file is meant for building images for all our services. Whether on the server(staging), or on the CI(for production images).
- docker-compose.prod.yml: This is for deploying the stack in production
docker stack deploy -c docker-compose.prod.yml sh-project - docker-compose.staging.yml: This is for deploying the stack on staging
docker stack deploy -c docker-compose.staging.yml sh-project - docker-compose.preview-build.yml: This is for building images on the test instance
docker-compose -f docker-compose.preview-build.yml build - docker-compose.preview.yml: This is for deploying the stack on the test instance
docker stack deploy -c docker-compose.preview.yml sh-project - docker-compose.yml: This is for local development
Environment Setup
In any environment where the use private registry is needed, there are a couple of things that we need to do first.
- Install awscli on the server if we haven't yet.
sudo apt-get update && sudo apt install awscli. - Configure iam role to access ecr in readonly mode. Our instances already have full admin access so we can skip this step
- Do docker login
aws ecr get-login-password --region us-east-2 | docker login --username AWS --password-stdin 567193262400.dkr.ecr.us-east-2.amazonaws.com - Start docker-swarm.
docker stack deploy -c docker-compose.staging.yml sh-project --with-registry-auth
Without the docker login and the --with-registry-auth flag, swarm won't be able to pull private images.
Deploy the Stack
To deploy docker stack. We run the following command
docker stack deploy -c docker-compose.prod.yml sh-project
Where sh-project is the name of the stack. For consistency, let's keep the stack name the same across all our environments.
Managing the Swarm
Below are a list of commands to manage day to day operations on the swarm.
List services
docker service ls
Or
docker stack services ls
In the following examples sh-project_ds in the name of the service we are operating on. Keep in mind that service names are prefixed by the name of the stack.
Scale a Service
To Increase the number of instances of a particular service we run
docker service scale sh-project_ds=5
View Logs
docker service logs sh-project_ds
Delete a service
docker service rm sh-project_ds
Delete a stack
docker stack rm sh-project
This removes all the services in the stack, then delete the stack itself
Update a service
This could happen during deployment and we want to deploy the newly built service.
docker service update sh-project_ds:version
Remember to increment the version number in the docker-compose files before building and updating.
Rollback an Update
docker service rollback sh-project_ds
Keep in mind that updates can be version change as well scaling updates e.t.c.
Add New Service to the Swarm
When we a new service to our docker-compose.*yml, to make it part of our swarm we will need to use the deploy command. This updates existing services in the stack if their configurations(replicates, versions e.t.c) have changed or skips them, and creates the newly introduced service in our stack.