Hands-On Docker Compose Guide

In a world where it is not uncommon for companies to have millions of containers, simply managing them through the docker CLI will not suffice. We need a tool that can help us manage chunks of containers and define them in a human-readable format. That is exactly what docker compose does.

Basics

At the most basic level, docker compose uses code to manage your infrastructure. This code is written in yaml format. The file that the code is written in is called docker-compose.yaml. Here is a basic docker-compose.yaml file:

version: '3.8'

services:
  service1:
    image: nginx:alpine
    ports:
      - "80:80"
  service2:
    image: alpine

networks:
  mynetwork:

As you can see, the structure of the file is quite basic. Let's go through everything 1 by 1.

  • version: This specifies the version of docker compose in use by the file.
  • services: This specifies the services that the file defines. Each service is, essentially, just the definition for a container. When the file is deployed, 1 container is made out of each service.
    • <service_name>: A single docker-compose.yaml file can have several services. Each service has it's own name. This is how you define the name.
      • image: This is the image that will be used for the container that will be created when this is deployed. Does the same thing as
      • ports: This works the same way as the ports option in the docker run command.
    • ...: There can be many services
  • networks: This is the definition for docker networks.

As you can see, most things work the same way in docker compose as they do in docker. They are just written in yaml format.

Hands-On exercises

Docker compose is a very unique concept. Most things can be explained through theory. Practical experience just reinforces that theory. Docker compose, on the other hand, is very simple to understand the basics of. While I can explain the more complicated concepts through theory, it will be the most dry, dull, and boring thing you have ever heard. This is why I will teach you through making you do hands-on exercises.

In these hands-on exercises, you will need to write docker-compose.yaml files on your own. For your reference, I will give you the docker compose documentation. I will provide you with the solution, but I encourage you to try on your own first.

Basic Web Server

We are going to start with something very simple. You have an HTML file. You need to host a web server on docker with it.

<!DOCTYPE html>
<html>
<head>
    <title>The best website ever!</title>
</head>
<body>
    <h1>Welcome to the website!</h1>
</body>
</html>

Make sure you follow best practices. Since you do not expect this data to change and this is quite a small file, you should not use volumes. Instead, you should create an image the file in it.

Also make sure you do not build the image in advance. You need to make it so the image is built on deployment.

After you come up with a solutions, do not check it immediately. Test it with the following command. Before you run this, make sure you have docker compose installed. Here is a guide.

docker-compose up -d --force-recreate

After you make changes, execute the same command and the updates will be carried out automatically.

If there is something wrong, try to figure it out. Looking at my answer should only be done once you have tried everything.

Solution

There are several solutions, but this is what I used.

docker-compose.yaml:

version: '3.8'
services:
 service1:
  build: .
  ports:
  - "80:80"

Dockerfile:

FROM httpd
COPY ./index.html /usr/local/apache2/htdocs/

This assumes that all these files are in a single directory, and the HTML file is named index.html. You can adapt this to your specific case.

If you got this right first try, you are doing great! You will be a docker compose wizard in no time.

If you struggled on this, that if fine. It's expected. You will only get better with practice.

Multi-Container App

The previous exercise was great to get your feet wet with docker compose, but that wasn't really something useful. All you did is deploy a web server on a container. Now, it's time to take it up a notch. You will be using containers for what they are best for, modularized application components. In short, microservices.


Here are some requirements for this. Because of how important network isolation is, you need to make sure you create a seperate network specifically for this. No ports should be exposed except for the ones that are required. Also make sure that the name of the API container is api. Don't just name the service api. That will not work.

Solution

Here is the docker compose file that works. There are other ways to do it.:

version: '3.8'

services:
 api:
 build:
 context: .
 dockerfile: dockerfile_api
 container_name: api
 networks:
 - app

 web:
 build:
 context: .
 dockerfile: dockerfile_web
 ports:
 - "80:80"
 networks:
 - app

networks:
 app:

Conclusion

Docker compose is a very complicated subject. I haven't even scratched the surface. This was my attempt to teach you docker compose in the most fun way possible. If you have another topic to discuss, you think I could have done something better, or you just want to ask me a question, just drop a comment. I will try my best to help. Before you leave, here is something that will help you.


Comments

Popular posts from this blog

Persistent Data in Docker: Explanation + Hands-On Demo

Pods to Deployments | Kubernetes Architecture Evolution

Docker Compose Explained: Simplifying Multi-Container Deployments