Getting Started with Docker Swarm
Quick introduction to getting around Docker Swarm, Docker’s native clustering system, similar to Kubernetes & Apache Mesos.
A quick definition:
swarm
is a simple tool which controls a cluster of Docker hosts and exposes it as a single “virtual” host.
For me, Docker is a bit of a shift in thinking compared to a regular virtualbox. Docker Swarm takes the container applies concept to multi-node networked instances.
Requirements
For this article, I will be working with Docker Swarm within a single virtualbox, just to keep things simple.
- Virtualbox installed
- vagrant installed
- Download this Vagrantfile
Getting Started
With everything in the requirements section completed, in the folder containing the Vagrantfile, run this command in the terminal:
$ vagrant up manager
... # lots of build messages
$ vagrant ssh manager
The rest of the article will work within the manager virtualbox.
Showing Docker Swarm Services
In Docker Swarm, every running container(s) is a service. Instead of Docker managing them directly, Docker Swarm uses the Docker API to create containers from images.
To see Docker Swarm services, run: docker swarm ls
vagrant@manager:/vagrant$ sudo docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
ID | the container ID |
NAME | the unique name for the service |
MODE | which mode the service is in: replicated or global |
REPLICAS | the number of replicas the service is running in |
IMAGE | the Docker image used for the service |
PORTS | which ports connect the host to the service |
Contrast this with docker ps
vagrant@manager:/vagrant$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
So, different information for different use cases.
Start nginx Service
Now that we know how to see what Docker Swarm services are running, let’s start one up!
I’m going to use a simple & well-known image: nginx. I would like to focus on the other parts of the Docker Swarm commands before thinking about how to create an image for the service.
To create a Docker Swarm service with nginx, run command: docker
service create <image name>
vagrant@manager:/vagrant$ sudo docker service create nginx
7ctrcae7sob0tjabccqfea1pd
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
vagrant@manager:/vagrant$
Oooh, that loks a bit different. There’s a nice progress bar and a
message stating the service status. Service converged
nginx Service Status
Let’s check out what the status of the service using docker service
ls
.
vagrant@manager:/vagrant$ sudo docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
7ctrcae7sob0 objective_hermann replicated 1/1 nginx:latest
Oooh, that’s cool. The service: replicated
and it’s running on 1/1 replicas.
docker ps
Let’s checkout what docker ps
shows:
vagrant@manager:/vagrant$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5bb3e80c076d nginx:latest "nginx -g 'daemon of…" About a minute ago Up About a minute 80/tcp objective_hermann.1.6agqbzmx8qiazhwwncdegknwa
Oooh, that’s interesting. The names match: objective_hermann, but
the docker ps
command lists and additional ending:
.1.6agqbzmx8qiazhwwncdegknwa, so the container and service are not
1:1. The container ID is different than the service ID.
Docker Service ps
Docker Swarm has its own ps
command, which gives different
information:
vagrant@manager:/vagrant$ sudo docker service ps objective_hermann
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
6agqbzmx8qia objective_hermann.1 nginx:latest manager Running Running about a minute ago
ID | This |
NAME | Similar to the docker service ls and docker ps difference, this has only .1 added to its name |
IMAGE | This lists the image used for the service |
NODE | Nodes this service running on |
DESIRED STATE | The desired state of this service: running or shutdown |
CURRENT STATE | Current state of the service |
ERROR | Error meessage from creating the service |
PORTS | Ports connecting the host to the service |
Stopping Docker Service
Now that we have a Docker Service running in Swarm, how can we stop it?
By using the command: docker service rm <service name>
, so to remove
the objective_hermann service:
vagrant@manager:/vagrant$ sudo docker service rm objective_hermann
objective_hermann
and checking:
vagrant@manager:/vagrant$ sudo docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
That was easy!
Accessing Service
nginx that is not accessible through any ports is not fun. Let’s
create the service again with ports mapped using the option:
--publish <host port number>:<service port number>
vagrant@manager:/vagrant$ sudo docker service create --publish 80:80 nginx
m6e5hvq8jnwahuy7x93rb1yk6
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
Let’s check by using a quick curl
to see what nginx returns:
vagrant@manager:/vagrant$ curl localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
More Formal Format
Another, more formal and explicit version of the same command:
vagrant@manager:/vagrant$ sudo docker service create --publish published=80,target=80 nginx
Updating Service Port
If the service is already running, say you forgot to specify ports
when creating the service, use the docker service update
command
with publish-add
to update the service:
vagrant@manager:~$ sudo docker service create nginx
s65up92ko7hxdi2lei91358el
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
vagrant@manager:~$ sudo docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
s65up92ko7hx eloquent_bohr replicated 1/1 nginx:latest
vagrant@manager:~$ sudo docker service update --publish-add 80:80 eloquent_bohr
eloquent_bohr
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
vagrant@manager:~$ sudo docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
s65up92ko7hx eloquent_bohr replicated 1/1 nginx:latest *:80->80/tcp
It’s basically the same as if you manually stopped the service and restarted with the right fields, but in update case, the service ID does not change.
Conclusion
This time, I went over how in a single node Docker Swarm to:
- list services
- create a new Docker Swarm from the nginx image
- make the service accessible by specifying or updating its ports
- delete services that are in a single node Docker Swarm.
Docker Swarm builds on the concepts of Docker, and although commands
are similar, like ps
is in both docker and docker service, it’s
intended usage is different.
I chose to focus on using a known Docker image, nginx, to learn about Docker Swarm.
Next time, I will focus on how to create a service in Docker Swarm from your Docker image.