Book Image

The DevOps 2.1 Toolkit: Docker Swarm

By : Viktor Farcic
Book Image

The DevOps 2.1 Toolkit: Docker Swarm

By: Viktor Farcic

Overview of this book

Viktor Farcic's latest book, The DevOps 2.1 Toolkit: Docker Swarm, takes you deeper into one of the major subjects of his international best seller, The DevOps 2.0 Toolkit, and shows you how to successfully integrate Docker Swarm into your DevOps toolset. Viktor shares with you his expert knowledge in all aspects of building, testing, deploying, and monitoring services inside Docker Swarm clusters. You'll go through all the tools required for running a cluster. You'll travel through the whole process with clusters running locally on a laptop. Once you're confident with that outcome, Viktor shows you how to translate your experience to different hosting providers like AWS, Azure, and DigitalOcean. Viktor has updated his DevOps 2.0 framework in this book to use the latest and greatest features and techniques introduced in Docker. We'll go through many practices and even more tools. While there will be a lot of theory, this is a hands-on book. You won't be able to complete it by reading it on the metro on your way to work. You'll have to read this book while in front of the computer and get your hands dirty.
Table of Contents (22 chapters)
Title Page
Credits
About the Author
www.PacktPub.com
Customer Feedback
Preface
11
Embracing Destruction: Pets versus Cattle

Building service images


Docker images are built through a definition stored in a Dockerfile. With few exceptions, it takes a similar approach as if we would define a simple script. We will not explore all the options we can use when defining a Dockerfile, but only those used for the go-demo service. Please consult the Dockerfile reference (https://docs.docker.com/engine/reference/builder/) page for more info. The go-demo Dockerfile is as follows:

FROM alpine:3.4
MAINTAINER Viktor Farcic <viktor@farcic.com>

RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2

EXPOSE 8080
ENV DB db
CMD ["go-demo"]
HEALTHCHECK --interval=10s CMD wget -qO- localhost:8080/demo/hello

COPY go-demo /usr/local/bin/go-demo
RUN chmod +x /usr/local/bin/go-demo

Each of the statements will be built as a separate image. A container is a collection of images stacked one on top of the other.

Every Dockerfile starts with the FROM statement. It defines the base image that should be used. In most cases, my preference is to use alpine Linux. With its size being around 2MB it is probably the smallest distribution we can use. That is aligned with the idea that containers should have only things that are needed and avoid any extra overhead.

MAINTAINER is for informational purposes only.

The RUN statement executes any command set as its argument. I won't explain this one since it is very specific to the service we're building.

The EXPOSE statement defines the port the service will be listening to. It is followed by the definition of the environment variable DB that tells the service the address of the database. The default value is db and, as you'll see soon, it can be changed at runtime. The CMD statement represents the command that will be run when containers start.

The HEALTHCHECK instruction tells Docker how to test a container to check that it is still working. This can detect cases such as a web server that is stuck in an infinite loop and unable to handle new connections, even though the server process is still running. When a container has a healthcheck specified, it has a health status in addition to its normal status. This status is initially starting. Whenever a health check passes, it becomes healthy (from whatever state it was previously in). After a certain number of consecutive failures, it becomes unhealthy. In our case, the healthcheck will be executed every ten seconds. The command sends a simple request to one of the API endpoints. If the service responds with status 200, the wget command will return 0 and Docker will consider the service healthy. Any other response will be considered as unhealthy and Docker Engine will perform certain actions to fix the situation.

Finally, we copy the go-demo binary from the host to the /usr/local/bin/ directory inside the image and give it executable permissions with the chmod command.

To some, the order of the statements might not look logical. However, there is a good reason behind such declarations and their order. Those that are less likely to change are defined before those that are prone to changes. Since go-demo will be a new binary every time we build the images, it is defined last.

The reasons behind such order lie in the way Docker Engine creates images. It starts from the top-most definition and checks whether it changed since the last time the build was run. If it didn't, it moves to the next statement. As soon as it finds a statement that would produce a new image, it, and all the statements following it are built into Docker images. By placing those that are less likely to change closer to the top, we can reduce the build time, disk usage, and bandwidth.

Now that we understand the Dockerfile behind the go-demo service, we can build the images.

The command is very straightforward and is as follows:

docker build -t go-demo .

As an alternative, we can define build arguments inside a Docker Compose file. The service defined in docker-compose-test-local.yml (https://github.com/vfarcic/go-demo/blob/master/docker-compose-test-local.yml) file is as follows:

  app:
    build: .
    image: go-demo

In both cases, we specified that the current directory should be used for the build process . and that the name of the image is go-demo.

We can run the build through Docker compose with the command that is as follows:

docker-compose \ 
    -f docker-compose-test-local.yml \ 
    build app

We'll use the latter method throughout the rest of the book.

We can confirm that the image was indeed built, by executing the docker images command as follows:

docker images

The output is as follows:

REPOSITORY TAG    IMAGE ID     CREATED        SIZE
go-demo    latest 5e90126bebf1 49 seconds ago 23.61 MB
golang     1.608a89f0a4ee5 11 hours ago   744.2 MB
alpine     latest 4e38e38c8ce0 9 weeks ago    4.799 MB

As you can see, go-demo is one of the images we have inside the server.

Now that the images are built, we can run staging tests that depend on the service and its dependencies to be deployed on a server.