Introduction

Docker simplifies the process of managing application processes in containers. While containers are similar to virtual machines in certain ways, they are more lightweight and resource-friendly. This allows developers to break down an application environment into multiple isolated services.

For applications depending on several services, orchestrating all the containers to start up, communicate, and shut down together can quickly become unwieldy. Docker Compose is a tool that allows you to run multi-container application environments based on definitions set in a YAML file. It uses service definitions to build fully customizable environments with multiple containers that can share networks and data volumes.

In this guide, you'll learn how to install Docker Compose on Ubuntu and get started using this tool.

[info] Simplify deploying applications to servers with an app platform. Deploy directly from GitHub in minutes.

Key Takeaways

docker compose illustration for: Key Takeaways
  • Install Docker Compose v1 by downloading the binary from GitHub releases and placing it in /usr/local/bin with executable permissions.
  • Define multi-container applications using a docker-compose.yml YAML file that specifies services, networks, volumes, and port mappings.
  • Manage containerized environments with commands like docker-compose up -d to start services, docker-compose ps to check status, and docker-compose down to stop and remove containers.
  • Docker Compose v2 uses docker compose (without hyphen) as a CLI plugin, while v1 uses docker-compose (with hyphen); this tutorial covers v1 installation.
  • Volumes enable file sharing between host and containers, allowing live updates to application files without rebuilding images.

Prerequisites

Overview

To follow this article, you will need:

  • Access to an Ubuntu local machine or development server (compatible with Ubuntu 20.04 and later versions) as a non-root user with sudo privileges. If you're using a remote server, it's advisable to have an active firewall installed. To set these up, please refer to our Initial Server Setup Guide for Ubuntu.
  • Docker installed on your server or local machine, following Steps 1 and 2 of How To Install and Use Docker on Ubuntu.

Note: This tutorial covers installing Docker Compose v1, which uses docker-compose. Docker Compose v2 uses the compose CLI plugin command (documented in our Ubuntu 22.04 version of this tutorial). The main difference is v2 uses docker compose (without hyphen) instead of docker-compose. For compatibility details, see the official Docker documentation.

Docker Compose v1 vs v2 Comparison

The following table compares Docker Compose v1 and v2 to help you choose the right version:

Feature Docker Compose v1 Docker Compose v2
Command Syntax docker-compose (with hyphen) docker compose (without hyphen, as CLI plugin)
Installation Method Standalone binary downloaded from GitHub Installed as Docker CLI plugin via Docker Desktop or Docker Engine package manager
Architecture Separate Python-based binary Integrated into Docker CLI as a plugin
Performance Slower startup time Faster startup and execution
Compatibility Works with older Docker versions Requires Docker 20.10.13+ or Docker Desktop
docker-compose.yml Fully compatible Fully compatible (same file format)
Command Compatibility Original command set Most commands work the same, some enhancements
Updates Manual updates required Updates with Docker Desktop or Docker Engine
Status Still supported but in maintenance mode Actively developed and recommended
When to Use Legacy systems, older Docker versions, or when you need the standalone binary New installations, modern Docker setups, better performance

Key Differences:

  • Command syntax: v1 uses docker-compose up, v2 uses docker compose up
  • Installation: v1 requires manual binary download, v2 installs as part of Docker
  • Performance: v2 is significantly faster due to Go rewrite (v1 was Python-based)
  • Future: Docker recommends v2 for new projects, though v1 remains functional

For most new installations, Docker Compose v2 is recommended. However, this tutorial focuses on v1 for systems that require the standalone binary or compatibility with older Docker versions.

Step 1 — Installing Docker Compose

Download Docker Compose from its official GitHub repository.

First, visit the releases page and note the latest version number (e.g., 1.29.2). Replace 1.29.2 in the command below with the latest version number you found.

The following command downloads the release and saves the executable to /usr/local/bin/docker-compose, making it globally accessible:

				
					sudo curl -L "https://github.com/docker/compose/releases/download/<^>1.29.2<^>/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
				
			

Set executable permissions for the docker-compose command:

				
					sudo chmod +x /usr/local/bin/docker-compose
				
			

Verify the installation:

				
					docker-compose --version
				
			

You'll see output similar to this:

				
					[secondary_label Output]
docker-compose version <^>1.29.2<^>, build 5becea4c
				
			

Docker Compose is now installed. Next, you'll set up a docker-compose.yml file and run a containerized environment.

Step 2 — Setting Up a docker-compose.yml File

Create a web server environment using the official Nginx image from Docker Hub to demonstrate Docker Compose. This environment serves a single static HTML file.

Create a new directory in your home folder and navigate into it:

				
					mkdir <^>~/compose-demo<^>
cd <^>~/compose-demo<^>
				
			

Create an application folder to serve as the document root for your Nginx environment:

				
					mkdir <^>app<^>
				
			

Create a new index.html file in the app folder:

				
					nano app/index.html
				
			

Place the following content into this file:

				
					[label ~/compose-demo/app/index.html]
<!doctype html>
<html lang="en">
<head>
 <meta charset="utf-8">
 <title>Docker Compose Demo</title>
 <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/kognise/water.css@latest/dist/dark.min.css">
</head>
<body>

 <h1>This is a Docker Compose Demo Page.</h1>
 <p>This content is being served by an Nginx container.</p>

</body>
</html>
				
			

Save and close the file. In nano, press CTRL+X, then Y, then ENTER.

Next, create the docker-compose.yml file:

				
					nano docker-compose.yml
				
			

Insert the following content in your docker-compose.yml file:

				
					[label docker-compose.yml]
version: '3.7'
services:
 web:
 image: nginx:alpine
 ports:
 - "8000:80"
 volumes:
 - ./app:/usr/share/nginx/html
				
			

The docker-compose.yml file starts with a version definition specifying the Compose file format version. Version '3.7' is compatible with Docker Compose v1. In newer Docker Compose versions, this field is optional, but including it ensures compatibility.

The services block defines the services in this environment. Here, a single web service uses the nginx:alpine image. The ports directive maps port 8000 on the host to port 80 in the container where Nginx runs.

The volumes directive creates a shared volume between the host and container, mounting the local app folder to /usr/share/nginx/html inside the container, replacing Nginx's default document root.

Save and close the file.

You've set up a demo page and docker-compose.yml file. Next, start the containerized environment with Docker Compose.

Step 3 — Running Docker Compose

With the docker-compose.yml file in place, start the environment. This command downloads necessary Docker images, creates a container for the web service, and runs it in the background:

				
					docker-compose up -d
				
			

Docker Compose checks for the image locally first, then downloads from Docker Hub if needed. You'll see output like this:

				
					[secondary_label Output]
Creating network "<^>compose-demo_default<^>" with the default driver
Pulling web (nginx:alpine)...
alpine: Pulling from library/nginx
cbdbe7a5bc2a: Pull complete
10c113fb0c77: Pull complete
9ba64393807b: Pull complete
c829a9c40ab2: Pull complete
61d685417b2f: Pull complete
Digest: sha256:57254039c6313fe8c53f1acbf15657ec9616a813397b74b063e32443427c5502
Status: Downloaded newer image for nginx:alpine
Creating <^>compose-demo_web_1<^> ... done
				
			

Note: If you encounter a permission error regarding the Docker socket, complete Step 2 of How To Install and Use Docker on Ubuntu to enable running Docker commands without sudo.

The environment is running in the background. Verify the container is active:

				
					docker-compose ps
				
			

This shows information about running containers, their state, and port mappings:

				
					[secondary_label Output]
 Name Command State Ports 
----------------------------------------------------------------------------------
<^>compose-demo_web_1<^> /docker-entrypoint.sh ngin ... Up 0.0.0.0:8000->80/tcp
				
			

Access the demo application at localhost:8000 on a local machine, or <^>your_server_domain_or_IP<^>:8000 on a remote server.

You'll see a page like this:

The shared volume keeps your app folder files in sync with the container's document root. Changes to index.html are automatically reflected when you reload the page.

Next, manage your containerized environment with Docker Compose commands.

Step 4 — Getting Familiar with Docker Compose Commands

Use Docker Compose commands to manage and interact with your containerized environment.

Check logs from your Nginx container:

				
					docker-compose logs
				
			

You'll see output similar to this:

				
					[secondary_label Output]
Attaching to &lt;^&gt;compose-demo_web_1&lt;^&gt;
web_1 | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
web_1 | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
web_1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
web_1 | 10-listen-on-ipv6-by-default.sh: Getting the checksum of /etc/nginx/conf.d/default.conf
web_1 | 10-listen-on-ipv6-by-default.sh: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
web_1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
web_1 | /docker-entrypoint.sh: Configuration complete; ready for start up
web_1 | 172.22.0.1 - - [02/Jun/2020:10:47:13 +0000] "GET / HTTP/1.1" 200 353 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36" "-"
				
			

Pause the environment without changing container state:

				
					docker-compose pause
				
			
				
					[secondary_label Output]
Pausing &lt;^&gt;compose-demo_web_1&lt;^&gt; ... done
				
			

Resume execution after pausing:

				
					docker-compose unpause
				
			
				
					[secondary_label Output]
Unpausing &lt;^&gt;compose-demo_web_1&lt;^&gt; ... done
				
			

Stop containers without destroying data:

				
					docker-compose stop
				
			
				
					[secondary_label Output]
Stopping &lt;^&gt;compose-demo_web_1&lt;^&gt; ... done
				
			

Remove containers, networks, and volumes:

				
					docker-compose down
				
			
				
					[secondary_label Output]
Removing &lt;^&gt;compose-demo_web_1&lt;^&gt; ... done
Removing network &lt;^&gt;compose-demo_default&lt;^&gt;
				
			

This doesn't remove the base image (nginx:alpine). Running docker-compose up again will be faster since the image remains on your system.

To remove the base image:

				
					docker image rm nginx:alpine
				
			
				
					[secondary_label Output]
Untagged: nginx:alpine
Untagged: nginx@sha256:b89a6ccbda39576ad23fd079978c967cecc6b170db6e7ff8a769bf2259a71912
Deleted: sha256:7d0cdcc60a96a5124763fddf5d534d058ad7d0d8d4c3b8be2aefedf4267d0270
Deleted: sha256:05a0eaca15d731e0029a7604ef54f0dda3b736d4e987e6ac87b91ac7aac03ab1
Deleted: sha256:c6bbc4bdac396583641cb44cd35126b2c195be8fe1ac5e6c577c14752bbe9157
Deleted: sha256:35789b1e1a362b0da8392ca7d5759ef08b9a6b7141cc1521570f984dc7905eb6
Deleted: sha256:a3efaa65ec344c882fe5d543a392a54c4ceacd1efd91662d06964211b1be4c08
Deleted: sha256:3e207b409db364b595ba862cdc12be96dcdad8e36c59a03b7b3b61c946a5741a
				
			

Note: For more Docker commands, see How to Install and Use Docker on Ubuntu.

Common Errors and Debugging

docker-compose: command not found

This error indicates docker-compose is not in your system's PATH, usually due to an incomplete installation.

Fix by either adding the directory to your PATH or using the full path. If docker-compose is in /usr/local/bin, run:

				
					/usr/local/bin/docker-compose
				
			

Permission issues when running Docker Compose

Permission issues occur when your user lacks permissions to run Docker commands.

Fix by either running with sudo or adding your user to the docker group. To use sudo:

				
					sudo docker-compose
				
			

To add your user to the docker group:

				
					sudo usermod -aG docker $USER
				
			

Remember to log out and log back in for the changes to take effect.

FAQs

What is Docker Compose used for?

Docker Compose is a tool for defining and running multi-container Docker applications. It allows you to define multi-container applications in a YAML file and start all services with a single command.

For example, you can define a service for a web server and another for a database, and Docker Compose will handle the creation and linking of these services.

What is the latest version of Docker Compose?

Check the Docker Compose releases page for the latest version.

How do I check if Docker Compose is installed?

Run:

				
					docker-compose --version
				
			

This displays the installed Docker Compose version.

Can I install Docker Compose without Docker?

No, Docker Compose requires Docker to be installed and running on your system. Docker Compose is a tool that builds on top of Docker, so Docker must be installed first.

How do I uninstall Docker Compose from Ubuntu?

Since this tutorial installs via binary download, remove it manually:

				
					sudo rm /usr/local/bin/docker-compose
				
			

If you installed via APT, use sudo apt-get purge docker-compose.

Conclusion

In this guide, you've seen how to install Docker Compose and set up a containerized environment based on an Nginx web server image. You've also seen how to manage this environment using Compose commands.

For a complete reference of all available docker-compose commands, check the official documentation.

If you're interested in more usages of Docker Compose, check out the following tutorials: