Docker Compose is a tool that allows you to define and manage multiple containers and Docker applications using a simple YAML configuration file. Instead of typing Docker CLI commands manually to set everything up, you can put all the configuration in a YAML file. Compose lets you configure and define everything in one place and start it up with a single command. This is especially useful if you have an application stack made of different pieces and want to start and automate them all together. Managing this with manual commands would be difficult and inefficient.

Make a directory for your project to keep clean

mkdir project

Go into your project directory

cd project

Make a YAML file named docker-compose.yml and put this docker-compose.yml into the project directory

nano docker-compose.yml

Copy and paste this in. After you paste it in hit ctrl + o then enter then ctrl + x to save it and exit nano.

services:
  apache:  # Name of the service (can be anything you like)
    image: httpd:latest  # Use the official Apache HTTP Server image (latest version)
    ports:
      - "8080:80"  # Maps port 80 inside the container to port 8080 on your host
                   # So you'll access the site at http://localhost:8080
A screenshot of a computer screen

AI-generated content may be incorrect.

Now to run the compose file you would run this command with the -d which means detached mode. This would run the compose on the local machine only. By default, it looks for the name docker-compose.yml. If you named it something else you would need to specify the name with the -f (name) to specify your custom name which I will show you later.

docker compose up -d

Run this to see the compose running

docker compose ps

Containers should have opened and started to run as well. You can check this with docker ps

docker ps
A black screen with white text

AI-generated content may be incorrect.

We also have the site up and running. Just type in localhost:8080 in a browser and you should see your website pop up.

A screenshot of a computer

AI-generated content may be incorrect.

To shut the service down you would run this command

docker compose down

If you had a custom name for your docker-compose.yml like for example website.yml you would run the -f flag to specify the file name like this. Use the -d still because we want it to run in detached mode.

docker compose -f website.yml up -d

And to shut it down would be the same thing but with down

docker compose -f website.yml down

Let’s deploy this in a swarm. If you don’t have a swarm already you can read this page on how to make one: https://nodetechsystems.ca/docker-swarm-orchestration/

We need a new YAML file cause our original one does not have specified replicas and we need at least 3 replicas because I have 3 nodes in my swarm. I will make a new one. This one I will call custom-apache.yml.

nano custom-apache.yml

Below:

services:
  apache:  # Service name; you can choose any name here
    image: httpd:latest  # Use official Apache HTTP Server image from Docker Hub

    ports:
      - "8080:80"  # Map port 8080 on the host to port 80 inside the container
                   # When deployed to Swarm, port 8080 will be published on all nodes,
                   # and traffic will be load balanced to replicas

    deploy:
      replicas: 3  # Run 3 instances of this service (Swarm will try to spread them across nodes)
      restart_policy:
        condition: on-failure  # Restart containers only if they exit with failure (non-zero status)
                              # Helps keep the service healthy automatically
A screenshot of a computer error

AI-generated content may be incorrect.

Deploy the stack on the swarm manager using this command. The -c flag specifies the compose file that will exist on your manager, this is the file you created on your manager that contains the configuration. I gave the stack name of nodestack. So, what this actually does is deploys a group of services (a stack) to the docker swarm cluster.

docker stack deploy -c custom-apache.yml nodestack
A screenshot of a computer

AI-generated content may be incorrect.

Docker swarm reads the compose file (custom-apache.yml) and creates all the services defined in it. It schedules those services across the nodes in our swarm cluster.

Check status of what’s going on behind the scenes

docker stack services nodestack
docker service ls
docker service ps nodestack_apache
A black screen with white text

AI-generated content may be incorrect.

We can scale this stack if we want to. We have 3 replicas (3 containers running across 3 nodes) so when we run this command go to each node and run docker ps, you should see 5 containers total running across your 3 nodes.

docker service scale nodestack_apache=5
A screen shot of a computer

AI-generated content may be incorrect.

To update the stack with a new configuration file (changes to the .YAML) run this

docker stack deploy -c custom-apache.yml nodestack

You can remove the stack with this command

docker stack rm nodestack

Keep in mind that docker compose commands are for local machine use only and docker stack deploy is for swarm only. If you are working with swarms you are using docker stack deploy commands and if you are just working with one machine you are using docker compose commands

We first deployed a Docker Compose YAML file on a single host, which created one running container (1 replica) for the service on that machine. Then, we deployed a different YAML stack file to the Docker Swarm cluster, which created 3 replicas (containers) of the service distributed automatically across the 3 nodes then we scaled the replicas to 5 (5 containers in the swarm now instead of 3). I did not cover volumes here, but we could have used one to mount a custom .html file but that would require placing the file on every node individually. If you want to go this route, you can configure it in the YAML file as well. Alternatively, you could use a shared volume backed by something like NFS or build a custom Apache image with the HTML file inside it. Docker compose is useful for automation because you can specify everything you need to specify in a single file and deploy that to either one local machine or multiple machines across the swarm. It is a powerful tool that simplifies deployment and makes life easier for anyone who needs to deploy complex applications consistently and efficiently without manually configuring each component on every machine.