Managing multi-container applications using standard docker run commands can quickly become complex, verbose, and error-prone. Each container requires separate flags for port exposures, environment variables, network attachments, and volume mounts.
Docker Compose is a tool that simplifies this process by allowing developers and system administrators to define and manage multi-container Docker applications declaratively using a single YAML file (typically named docker-compose.yml).
A standard Docker Compose file is structured around three key configurations:
Services (services):
Defines the distinct containers that make up your application (e.g., a database service, a caching service, and a web server service). You specify the base image, build contexts, environment configurations, and restart policies within each service.
Volumes (volumes):
Defines persistent storage resources that can be shared between multiple services or mounted directly to directories on the host system (bind mounts).
Networks (networks):
Defines virtual isolated networks. By default, Docker Compose sets up a single default network for your application. Each container for a service joins this network and is both reachable and discoverable by other containers using their service name as the hostname.
graph TD
subgraph Host Machine (Port 6100)
HostDir["Host Directory (/opt/data/)"]
end
subgraph Docker Compose Environment
httpd["Apache Container (httpd)"]
httpd -->|Maps Port 80 to Host Port 6100| Host
HostDir -->|Volume Bind Mount| WebRoot["Container Web Root (/usr/local/apache2/htdocs/)"]
end
Below are the essential commands used to manage environments defined by Docker Compose:
docker compose up:
Builds, (re)creates, starts, and attaches to containers for a service.
-d (detached) mode to run containers in the background: docker compose up -ddocker compose down:
Stops and removes containers, networks, volumes, and images created by up.docker compose ps:
Lists the status of running containers managed by the current Compose file.docker compose logs:
Streams output logs from all running containers in the stack.docker compose exec <service> <command>:
Executes a command inside the running container of a specific service.stapp03) (can vary in labs, e.g., stapp01, stapp02, stapp03)banner (associated with stapp03; tony for stapp01, steve for stapp02)/opt/docker/docker-compose.ymlhttpdhttpdhttpd:latest6100 mapped to Container Port 80/opt/data mounted to Container Web Root /usr/local/apache2/htdocsEstablish an SSH connection from the Jump Host to App Server 3:
ssh banner@stapp03
Provide the server password when prompted.
Ensure the target directory exists for the Docker Compose configuration:
sudo mkdir -p /opt/docker
Create and edit the YAML file using a text editor (e.g., vi):
sudo vi /opt/docker/docker-compose.yml
Add the following configuration block:
version: '3.8'
services:
httpd:
image: httpd:latest
container_name: httpd
ports:
- "6100:80"
volumes:
- /opt/data:/usr/local/apache2/htdocs
restart: always
Save and exit the text editor (:wq).
Navigate to the directory containing the Compose file and start the stack in detached mode:
cd /opt/docker
sudo docker compose up -d
If using older versions of Docker Compose, run sudo docker-compose up -d instead.
Check if the service container is active and running:
docker compose ps
# or
docker ps
Expected Output:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2a3b4c5d6e7f httpd:latest "httpd-foreground" 5 seconds ago Up 5 seconds 0.0.0.0:6100->80/tcp httpd
Create a test file in the host data directory and verify that it is served correctly by the web server:
# Write test file on Host
echo "Nautilus DevOps Team - Challenge 44" | sudo tee /opt/data/index.html
# Query the HTTP service on host port 6100
curl http://localhost:6100
Expected Output:
Nautilus DevOps Team - Challenge 44
Log out of the Application Server:
exit