How to Install Docker Compose on Ubuntu 24.04 [Step-by-Step]

How to Install Docker Compose on Ubuntu 24.04 [Step-by-Step]
Published on May 24, 2024 Updated on Mar 26, 2026

Docker Compose is a command-line tool for defining and running multi-container Docker applications using a single YAML configuration file. Instead of managing each container separately with individual docker run commands, Compose lets you declare all your services, networks, and volumes in one file and launch everything with a single command.

In this tutorial, you will learn how to install Docker Compose on Ubuntu 24.04, configure a multi-container LAMP stack, manage the container lifecycle, and work with essential Compose features like networking, volumes, and environment variables.

#What is Docker?

Docker is an open-source containerization platform that lets you seamlessly build, share, deploy, and orchestrate applications anywhere, be it on Linux, Windows, Mac, or any other computing environment.

Docker packages applications and their dependencies into containers. Each container runs as an isolated process that shares the host operating system's kernel. Containers are lightweight compared to virtual machines because they do not need a separate OS for each instance. For a deeper look at how Docker works under the hood, read our guide on Docker architecture.

#What is Docker Compose?

Built on top of Docker Engine, Docker Compose is a tool for defining and running multi-container applications. Compose reads a YAML file (named compose.yaml or docker-compose.yml) that describes your application's services, networks, and volumes. It then creates and manages all required containers according to that configuration.

#What does Docker Compose do?

Docker Compose creates containers and other resources defined within the Compose file written in YAML format. With the compose file in place, you can create and launch your multi-container application using the docker compose up command, as we shall see later.

A single Compose file can define web servers, databases, caching layers, message brokers, and any other service your application needs. Compose also handles dependencies between services. If your web application depends on a database, Compose starts the database container first and waits for it to become ready before starting the application container.

#How to use Docker Compose?

Docker Compose is used for providing simplified control when managing multi-container applications. It simplifies the complexities involved in running multiple containers with interlinked services. In addition, it also makes it easier to collect logs and debug issues in multiple containers compared to Docker.

The typical workflow involves three steps. First, write a Dockerfile for each service that needs a custom image (or reference existing images from Docker Hub). Second, define all your services in a compose.yaml file. Third, run docker compose up to start everything. For a quick reference of all available commands, see our Docker Compose cheat sheet.

Ready to supercharge your Docker infrastructure? Scale effortlessly and enjoy flexible storage with Cherry Servers bare metal or virtual servers. Eliminate infrastructure headaches with free 24/7 technical support, pay-as-you-go pricing, and global availability.

#Prerequisites

Before you set sail, ensure you have the following in place:

  • An instance of Ubuntu 24.04 with SSH access;

  • A sudo user configured on the server;

  • Docker installed on your Linux instance.

  • Docker Engine 24.0 or later (required for Compose V2 plugin support). Run docker --version to confirm.

#How to install Docker Compose on Ubuntu 24.04

The below five steps will show you how to install Docker Compose on Ubuntu 24.04. I've included how to update package lists, install Docker Compose, deploy LAMP stack using Docker Compose, run Docker Compose, and learn how to pause, stop, and remove containers.

#Step 1: Update Package Lists

First, log in to your server and update the package lists as follows.

Command Line
sudo apt update

This command downloads and updates package information defined in the /etc/apt/sources.list file and /etc/apt/source.list.d directory.

#Step 2: Install Docker Compose

Docker Compose is hosted on Ubuntu repositories and can easily be installed by running the command:

Command Line
sudo apt install docker-compose -y

However, the version installed from the repositories does not give you the latest version of Docker Compose. To get the most updated version of Docker Compose, download it from its official GitHub repository.

Before downloading the latest Docker Compose plugin binary, create a cli-plugins directory in your home folder.

Command Line
mkdir -p ~/.docker/cli-plugins/

Next, download the Docker compose plugin file to the ~/.docker/cli-plugins/ directory using the curl command as shown.

Command Line
curl -SL https://github.com/docker/compose/releases/download/v2.40.3/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose

Replace v2.40.3 with the latest version from the releases page if a newer version is available.

Run the ls command to verify the presence of the docker-compose file.

Command Line
ls -lh ~/.docker/cli-plugins
Outputtotal 74M  
-rw-r--r-- 1 root root 74M Feb 26 06:27 docker-compose

Next, assign execute permissions to the file using the chmod command.

Command Line
chmod +x ~/.docker/cli-plugins/docker-compose

To confirm the installation was successful, check the Docker compose version.

Command Line
docker compose version
OutputDocker Compose version v2.40.3

#Step 3: Deploy LAMP stack using Docker Compose

With Docker Compose already installed, we will test it by deploying a LAMP stack application. LAMP ( Linux Apache Mysql PHP ) is a popular web hosting stack used to host websites.

To get started, create the project directory and navigate into it. In this case, our project directory is my-demo-app.

Command Line
mkdir ~/my-demo-app  
  
cd ~/my-demo-app

Next, create a docker-compose.yml file.

Command Line
nano docker-compose.yml

Add the following lines of code:

docker-compose.yml
services:
  apache:
    image: php:apache
    container_name: apache-app
    ports:
      - "8080:80"
    volumes:
      - ./src:/var/www/html
    depends_on:
      mysql:
        condition: service_started
    networks:
      - lamp-network

  mysql:
    image: mysql:8.0
    container_name: mysql-app
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: mysql_root_password
      MYSQL_DATABASE: mydatabase
      MYSQL_USER: myuser
      MYSQL_PASSWORD: myuser_password
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - lamp-network

networks:
  lamp-network:
    driver: bridge

volumes:
  mysql-data:

The configuration above sets up two services:

  • apache: This is the Apache web service with PHP support. It runs as a container called apache-app created from the php:apache image. The webserver will serve files from the .src directory which will be created in the project folder. The webserver will run on port 80 on the container which will be mapped on port 8080 on the host system.

  • mysql: This is the MySQL database service with a specified root password, database name, MySQL username, and password. The service runs as a container called mysql-app on port 3306 which is mapped on port 3306 on the host system.

Save the changes in the YAML file and exit.

#Optional: Use an environment file for sensitive values

Storing passwords directly in the Compose file is convenient for testing but risky for production. You can move sensitive values to a .env file in the same directory as your docker-compose.yml:

docker-compose.yml
MYSQL_ROOT_PASSWORD=mysql_root_password  
MYSQL_DATABASE=mydatabase  
MYSQL_USER=myuser  
MYSQL_PASSWORD=myuser_password

Then reference these variables in the Compose file using the ${VARIABLE} syntax:

docker-compose.yml
environment:  
	MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}  
	MYSQL_DATABASE: ${MYSQL_DATABASE}  
	MYSQL_USER: ${MYSQL_USER}  
	MYSQL_PASSWORD: ${MYSQL_PASSWORD}

Docker Compose automatically reads the .env file from the project directory. Add .env to your .gitignore to keep secrets out of version control.

#Step 4: Run Docker compose

Having defined the services to be created, the next step is to start the LAMP stack using Docker Compose. To do so, run the following docker compose command.

Command Line
docker compose up -d

The command downloads the specified Docker images, in this case php:apache and mysql:8.0. Afterward, it creates the mysql-app and apache-app containers and runs them in detached mode using the -d flag.

Additionally, it creates a default network for communication between the services, the mysql-data persistent directory for the database, and the src web directory for storing website files.

Output[+] Running 3/3  
✔ Network my-demo-app_lamp-network Created 0.0s  
✔ Container mysql-app Started 0.3s  
✔ Container apache-app Started 0.5s

To verify currently running containers, run the docker ps command:

Command Line
docker ps

You will get the following output showing all running containers and their details such as status and network ports.

OutputCONTAINER ID IMAGE      COMMAND                  CREATED            STATUS            PORTS                                    NAMES  
8aa5c35c7ad7 php:apache "docker-php-entrypoi..." About a minute ago Up About a minute 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp apache-app  
1158f45d75e6 mysql:8.0  "docker-entrypoint.s..." About a minute ago Up About a minute 0.0.0.0:3306->3306/tcp, [::]:3306->3306/tcp, 33060/tcp mysql-app

You can also list the existing images as shown.

Command Line
docker images
OutputIMAGE      ID            DISK USAGE  CONTENT SIZE  EXTRA  
mysql:8.0  a3dff78d8762  1.08GB      247MB         U  
php:apache 9be84c47f279  744MB       189MB         U

You can check the logs generated by the running containers using the docker compose logs command.

Command Line
docker compose logs
Outputmysql-app | 2026-02-26 04:39:55+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.45-1.el9 started.  
apache-app | AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.18.0.3. Set the 'ServerName' directive globally to suppress this message  
apache-app | AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.18.0.3. Set the 'ServerName' directive globally to suppress this message  
mysql-app | 2026-02-26 04:39:55+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'  
mysql-app | 2026-02-26 04:39:55+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.45-1.el9 started.  
apache-app | [Thu Feb 26 04:39:55.987084 2026] [mpm_prefork:notice] [pid 1:tid 1] AH00163: Apache/2.4.66 (Debian) PHP/8.5.3 configured -- resuming normal operations  
…

To follow logs in real time (similar to `tail -f`), add the `-f` flag:

```bash command
docker compose logs -f

To view logs for a specific service only:

Command Line
docker compose logs apache

At this point, we will create a simple webpage to test the web server. So, navigate to the web directory called src, which is located in the project folder.

Command Line
cd src

Create an index.html file.

Command Line
sudo nano index.html

Here's some sample code you can use to define the welcome page.

index.html
<!DOCTYPE html>  
<html>  
<body>  
<h1>LAMP stack successfully deployed using Docker compose!</h1>  
</body>  
</html>

Save the changes and exit the file. Launch your browser and head over to the server's URL as shown:

http://server-ip:8080

You should get the webpage below, proof that the webserver is running as expected.

Web page showing the server is running as expected

To connect to the mysql-app database container using the MySQL user specified in the YAML file, run the command:

Command Line
sudo docker exec -it mysql-app mysql -u myuser -p

Provide the user's password and hit ENTER to access the MySQL shell as shown.

Command Line
sudo docker exec -it mysql-app mysql -u myuser -p  
OutputEnter password:  
Welcome to the MySQL monitor. Commands end with ; or \g.  
Your MySQL connection id is 12  
Server version: 8.0.45 MySQL Community Server - GPL  
  
Copyright (c) 2000, 2026, Oracle and/or its affiliates.  
  
Oracle is a registered trademark of Oracle Corporation and/or its  
affiliates. Other names may be trademarks of their respective  
owners.  
  
Type 'help;' or '\h'  for  help. Type '\c' to clear the current input statement.  
  
mysql> SHOW DATABASES;  
+--------------------+  
| Database |  
+--------------------+  
| information_schema |  
| mydatabase |  
| performance_schema |  
+--------------------+  
3 rows in  set (0.00 sec)  
  
mysql>

To exit the shell and the container by extension, type exit and hit ENTER.

#Step 5: Pause, stop, and remove containers

To pause the Docker compose environment execution without altering the state of the containers, use the command:

Command Line
docker compose pause
Output[+] Pausing 2/2  
✔ Container mysql-app Paused 0.0s  
✔ Container apache-app Paused 0.0s

To resume execution or unpause the environment, run the command:

docker compose unpause
Output[+] Running 2/2  
✔ Container mysql-app Unpaused 0.0s  
✔ Container apache-app Unpaused 0.0s

To stop the environment without removing the containers, run:

Command Line
docker compose stop
Output[+] Stopping 2/2  
✔ Container apache-app Stopped 1.2s  
✔ Container mysql-app Stopped 1.3s

To stop and remove containers and the default network created by Docker Compose, run the command:

Command Line
docker compose down
Output[+] Running 3/3  
✔ Container apache-app Removed 0.0s  
✔ Container mysql-app Removed 0.0s  
✔ Network my-demo-app_lamp-network Removed 0.1s

To also remove the named volumes defined in the Compose file (this deletes all persistent data, including database contents):

Command Line
docker compose down -v

To remove everything, including images pulled by the Compose project:

Command Line
docker compose down --rmi all -v

Use --rmi all with caution. It removes all images used by the services, so the next docker compose up will re-download them from the registry.

#Essential Docker Compose commands

Beyond the basic up, down, and stop commands, Docker Compose provides several other commands for day-to-day container management. For a full reference, see our Docker Compose cheat sheet.

#Check service status

Command Line
docker compose ps

Lists all containers managed by the current Compose project along with their state, ports, and health status.

#Restart a specific service

Command Line
docker compose restart apache

Restarts the apache service without affecting other services. Compose stops the container and starts a new one using the same configuration.

#Scale a service

Command Line
docker compose up -d --scale apache=3

Runs three instances of the apache service. Scaling requires removing the container_name directive from the service definition, as Docker cannot assign the same name to multiple containers. You also need to remove fixed host port mappings (like "8080:80") or use a range (like "8080-8082:80").

#Execute a command inside a running container

Command Line
docker compose exec mysql bash

Opens a bash shell inside the running mysql container. Unlike docker compose run, the exec command connects to a running container.

#Pull updated images

Command Line
docker compose pull

Downloads the latest versions of all images specified in the Compose file. After pulling, run docker compose up -d to recreate containers with the updated images. For more details on the update workflow, see our guide on how to update Docker images.

#Validate the Compose file

Command Line
docker compose config

Parses and validates the Compose file, then prints the resolved configuration. Use this to catch YAML syntax errors and verify that environment variable substitutions resolve correctly before running docker compose up.

#Docker Compose networking

Docker Compose automatically creates a default network for each project. Every container in the project joins this network and can reach other containers using the service name as a hostname. For example, the apache service connects to MySQL using the hostname mysql (the service name defined in the Compose file).

#Custom networks

You can define custom networks for more control over container communication. The LAMP stack example above uses a custom bridge network called lamp-network. Custom networks let you isolate groups of services from each other within the same Compose project.

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge

Assign services to specific networks:
services:
  web:
    image: nginx
    networks:
      - frontend
      - backend
  api:
    image: node:22-alpine
    networks:
      - backend
  db:
    image: mysql:8.0
    networks:
      - backend

In this setup, the web service can reach both api and db because it belongs to both networks. The api and db services can communicate with each other on the backend network, but cannot directly access services that are only on the frontend network. For more details on Docker Compose networking, see the official networking documentation.

#Docker Compose volumes

Volumes persist data outside the container lifecycle. Without volumes, all data written to a container is lost when the container is removed.

#Named volumes vs. bind mounts

Docker Compose supports two types of volume mappings:

  • Named volumes are managed by Docker. You declare them in the top-level volumes section of the Compose file. Docker stores the data in its own directory on the host (usually /var/lib/docker/volumes/). Named volumes perform better than bind mounts on macOS and Windows.

  • Bind mounts map a specific host directory to a container path. The ./src:/var/www/html mapping in the LAMP stack example is a bind mount. Bind mounts work well for development because code changes on the host are reflected in the container immediately.

volumes:
 mysql-data:          # Named volume - Docker manages storage location
 redis-data:
   driver: local      # Explicit driver (local is the default)

To list all Docker volumes on your system:

Command Line
docker volume ls

To inspect a specific volume and see where Docker stores its data:

Command Line
docker volume inspect my-demo-app_mysql-data

To remove unused volumes and free disk space:

Command Line
docker volume prune

For a full overview of Docker storage options, see the Docker volumes documentation.

#Docker Compose Use Cases

  • Multiple container orchestration: Docker Compose lets you define applications with many containers in one YAML file. In a microservices architecture, you can deploy separate services for API, authentication, and data storage using one file. Each container is configured with its own network settings, environment variables, and volume mounts.

    A single docker compose up -d command replaces long scripts and manual container creation. For orchestration across multiple hosts, tools like Docker Swarm or Kubernetes handle multi-node deployments.

  • Consistent development environments: Docker Compose ensures every developer uses the same containerized services. It defines the complete application stack in a YAML file managed by version control. The file includes databases, message brokers, and external services.

    This simplifies dependency management, communication between services, and persistent storage. In addition, it creates smoother transitions from development to staging and production.

  • Staging environment replication: Docker Compose lets you replicate the exact configuration used in production by enabling you to define all the services (web servers, databases, and etc.) in a single YAML file.

    A single command such as docker-compose up spins up the entire environment, reducing the time and effort required to build and deploy a complex multi-container application. This speed allows teams to quickly test changes and iterate on features without manual setup each time.

  • CI/CD pipeline integration: Many CI/CD systems (GitHub Actions, GitLab CI, Jenkins) support Docker Compose for spinning up test environments. A Compose file can start your application alongside a test database, run integration tests, and tear everything down when tests finish. The docker compose run command executes one-off commands against a service, which is useful for running test suites or database migrations in CI.

#Troubleshooting

#"docker compose" command not found

The docker compose command (without a hyphen) requires the Compose V2 plugin. If you see "command not found," verify that the plugin binary exists at ~/.docker/cli-plugins/docker-compose and has execute permissions. Run chmod +x ~/.docker/cli-plugins/docker-compose to fix permission issues. Also, confirm that your Docker Engine version is 24.0 or later.

#Port already in use

If docker compose up fails with "address already in use," another process is occupying the port. Run sudo lsof -i :8080 (replace 8080 with the conflicting port) to identify the process. Stop that process or change the host port in your Compose file (e.g., from "8080:80" to "8081:80").

#Container exits immediately after starting

Check the container logs with docker compose logs <service-name>. Common causes include incorrect environment variables, missing configuration files, or permission errors on mounted volumes. For database containers, verify that all required environment variables (like MYSQL_ROOT_PASSWORD) are set.

#Changes to the Compose file do not take effect

After editing docker-compose.yml, you must run docker compose up -d again. Compose detects the configuration change and recreates only the affected containers. Running docker compose restart does not apply configuration changes because it only stops and starts the existing containers.

#Volumes not persisting data

Make sure you declared the volume in the top-level volumes section and referenced it correctly under the service. Bind mounts (using ./path:/container/path) require the host directory to exist. If you accidentally ran docker compose down -v, the named volumes were deleted along with all their data.

#Conclusion

You have learned how to install Docker Compose on Ubuntu 24.04, deploy a multi-container LAMP stack, manage container lifecycles, and work with essential features like custom networks, named volumes, and environment variable files.

Docker Compose reduces the complexity of running multi-container applications to a single YAML file and a few commands. Use docker compose up -d to start services, docker compose down to clean up, and docker compose pull followed by docker compose up -d to apply image updates.

FAQs

What is the difference between `docker compose` and `docker-compose`?

`docker-compose` (with a hyphen) is the legacy v1 binary written in Python. `docker compose` (without a hyphen) is the v2 plugin written in Go and bundled with Docker Engine. Docker Compose v1 reached end-of-life in June 2023. Use `docker compose` for all new projects.

Can I use Docker Compose in production?

Docker Compose works well for single-host production deployments, where you run all services on a single server. For multi-host setups that require load balancing, auto-scaling, and rolling updates, use an orchestration platform such as Kubernetes or Docker Swarm.

How do I update images in a Docker Compose project?

Run `docker compose pull` to download the latest versions of all images, then `docker compose up -d` to recreate containers with the updated images. Compose only restarts containers whose images have changed.

Is the `version` key still required in Compose files?

No. Docker Compose V2 and later ignore the `version` key and display a deprecation warning if it is present. The modern Compose Specification does not require it. Remove the `version` line from your Compose files to avoid the warning.

How do I view resource usage for Compose containers?

Run `docker compose top` to see running processes in each container, or `docker stats` to view real-time CPU, memory, and network usage for all running containers.


Can I run multiple Compose projects on the same server?

Yes. Each Compose project is isolated by its project name (which is derived from the directory name by default). Services in different projects do not share networks unless you explicitly configure an external network. Use the `-p` flag to set a custom project name: `docker compose -p my-project up -d`.

Cloud VPS Hosting

Starting at just $3.24 / month, get virtual servers with top-tier performance.

Share this article

Related Articles

Published on Mar 25, 2026 Updated on Mar 26, 2026

Docker Copy Command: Copy Files and Directories in Docker

Learn how to use the Docker COPY command with practical examples. Copy files, directories, and apply best practices for secure, efficient Docker builds.

Read More
Published on Sep 12, 2025 Updated on Nov 14, 2025

Docker Compose Cheat Sheet: Key Commands Guide

Learn Docker Compose commands to easily deploy and manage multi-container apps, scale services, and set up full-stack environments using a single YAML file.

Read More
Published on Aug 19, 2025 Updated on Nov 7, 2025

Docker Pull Command: How to Pull Docker Images

Learn how to search, pull, list, inspect, and remove Docker images step by step. Master Docker image management for smooth app deployment.

Read More
No results found for ""
Recent Searches
Navigate
Go
ESC
Exit
We use cookies to ensure seamless user experience for our website. Required cookies - technical, functional and analytical - are set automatically. Please accept the use of targeted cookies to ensure the best marketing experience for your user journey. You may revoke your consent at any time through our Cookie Policy.
build: 5e057a97e.1746