Table of Contents
Brief refresher on DockerFundamentals of DockerDocker ClientDocker ArchitectureContainers and imagesDockerfilesLayersDocker RegistryDocker DaemonDocker HubDockerfile vs Docker ComposeDocker Compose vs Kubernetes: When should you use each?Understanding the relationshipDocker Compose vs Kubernetes comparisonWhen to use Docker ComposePractical examplesFlask + PostgreSQLNode.js + RedisLocal microservice developmentWhen to use KubernetesPractical examplesE-commerce platformSaaS productStreaming platformLarge API infrastructureReal-world workflowStep 1: Develop locally with Docker ComposeStep 2: Test service interactionsStep 3: Deploy to KubernetesCan Kubernetes replace Docker Compose?What do companies actually use?StartupsGrowing companiesEnterprisesHow do you choose?Use Docker Compose if:Use Kubernetes if:Quick-reference guideGetting started with Docker Compose buildHow to use and install Docker ComposeDocker Compose file structureDocker Compose commandsTop 10 Docker Compose errors and how to fix themCommon Docker Compose errors1. Port already in useExample errorWhy it happensHow to fix it2. Service cannot connect to databaseExample errorWhy it happensIncorrect configurationCorrect configurationAdditional fixes3. Container exits immediatelyExample errorWhy it happensHow to investigate4. Docker Compose command not foundExample errorWhy it happensHow to verify5. Volume mount issuesExample errorWhy it happensExample6. YAML syntax errorsExample errorWhy it happensExampleHelpful validation command7. Build failuresExample errorWhy it happensCommon causesVerify build configurationRebuild with detailed output8. Environment variables not loadingExample errorWhy it happensVerify .envCommon mistakesValidate resolved configuration9. Network communication failuresExample errorWhy it happensVerify networksBest practice10. Permission denied errorsExample errorWhy it happensVerify ownershipEssential Docker Compose debugging commandsTake your Docker knowledge to the next levelContinue reading
Docker Compose Tutorial: Advanced Docker made simple

Docker Compose Tutorial: Advanced Docker made simple

21 mins read
Jun 09, 2026
Share
editor-page-cover

Docker is an in-demand, DevOps technology used to set up and deploy applications using containers. Docker’s environment streamlines the application development lifecycle, and Docker Compose, and advanced Docker tool, can be used to simplify your workflow

In this article, we will refresh your knowledge of Docker and show you how to get started with Docker Compose.

If you’re new to DevOps, check out our beginner’s guide to Docker and Kubernetes before proceeding with this tutorial.

Today, we will go over:


Working with Containers: Docker & Docker Compose

Cover
Working with Containers: Docker & Docker Compose

Whether you are a DevOps beginner or just a developer who wants to start working with containers, you’re in the right place. Docker is an in-demand technology that you will be exposed to frequently while on the job. Docker is used for setting up, deploying, and running applications, at scale, by containerizing them. More on that later. Docker also provides developers with a consistent environment for product development, and along with Kubernetes, makes managing the development lifecycle a breeze. In this course, you will learn the fundamentals of Docker such as containers, images, and commands. You’ll then progress to more advanced concepts like connecting to a database container and how to simplify workflows with Docker Compose. At the end, you’ll learn how to monitor clusters and scale Docker services with Swarm.

5hrs
Beginner
16 Playgrounds
5 Quizzes

Brief refresher on Docker#

Docker is an open-source tool for containerization that streamlines application creation and deployment through the use of containers. Containers enable us to bundle all parts of an application into a single package for deployment.

This tool makes it easy for different developers to work on the same project in the same environment without any dependencies or OS issues. Docker functions similarly to a virtual machine, however, it enables applications to share the same Linux kernel.

Docker offers many advantages for developers and DevOps teams. Some of these advantages include:

  • Being highly demanded by both large and small companies.
  • Providing isolation from the main system.
  • Streamlining configuration.
  • Providing access to thousands of pre-configured images through Docker Hub.
  • Supporting many CI tools like Travis and Jenkins.
  • Allowing developers to concentrate solely on writing code.
  • Simplifying deployment management for operations teams.

Docker is frequently utilized in conjunction with Kubernetes, a robust container management tool that automates the deployment of Docker containers. While Docker is utilized to package, isolate, and distribute applications in containers, Kubernetes acts as the container scheduler responsible for deploying and scaling the application.

These two technologies complement each other, making application deployment effortless.

widget

Fundamentals of Docker#

Before diving into advanced Docker concepts, like Docker Compose, we want to make sure to refresh the fundamentals of Docker as a whole. Let’s define and explore the basics of Docker.

Docker Client#

A Docker Client is a component used by a Docker user to interact with the Docker daemon and issue commands. These commands are based on the Docker API.

Docker Architecture#

The Docker Architecture is made of layers, as we will discuss below. The bottom layer is the physical server that we use to host virtual machines. This is the same as a traditional virtualization architecture.

The second layer is the Host OS, which is the base machine (i.e. Windows or Linux). Next, is the Docker Engine, which we use to run the operating system. Above that are the Apps which run as Docker containers. Those Docker Objects are made up of images and containers.

Containers and images#

The basic structure of Docker relies on images and containers. We can think of a container as an object and an image as its class.

A container is an isolated system that holds everything required to run a specific application. It is a specific instance of an image that simulates the necessary environment. The following is an example command for running an Ubuntu Docker container and accessing the bash shell:

docker run -i -t ubuntu /bin/bash

Images, on the other hand, are used to start up containers. From running containers, we can get images, which can be composed together to form a system-agnostic way of packaging applications.

Images can be pre-built, retrieved from registries, created from already existing ones, or combined together via a common network.

Dockerfiles#

Dockerfiles are how we containerize our application, or how we build a new container from an already pre-built image and add custom logic to start our application. From a Dockerfile, we use the Docker build command to create an image.

Think of a Dockerfile as a text document that contains the commands we call on the command line to build an image.

Below is an example of a Dockerfile:

FROM python:3
 
WORKDIR /usr/src/app
 
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
 
COPY . .
 
CMD [ "python", "./your-daemon-or-script.py" ]

Layers#

A Dockerfile works in layers. These are the building blocks of Docker. The first layer starts with the FROMkeyword and defines which pre-built image we will use to build an image. We can then define user permissions and startup scripts.

In Docker, a container is an image with a readable layer built on top of a read-only layer. These layers are called intermediate images, and they are generated when we execute the commands in our Dockerfile during the build stage.

Docker Registry#

Docker Registry is a centralized location for storing and distributing Docker images. The most commonly used public registry is Docker Hub, but you can also create your own private registry.

Docker Daemon#

Docker Daemon runs on a host machine and manages containers, images, networks, and volumes. It receives commands from the Docker client and executes them. The Docker daemon uses Docker images to create containers.

Docker Hub#

Docker Hub is a Docker Registry that provides unlimited storage for public images and offers paid plans for hosting private images. Anybody can access a public image. But to publish and access images on Docker Hub, you must create an account first.

Here are some common commands for using Docker Hub:

  • docker login: Login to your Docker Hub account from the command line.

  • docker pull: Download an image from Docker Hub to your local machine. For example, docker pull alpine.

  • docker push: Upload a local image to Docker Hub. For example, docker push username/image-name.

  • docker search: Search for an image on Docker Hub. For example, docker search alpine.

  • docker tag: Tag an image with a new repository name and/or tag. For example, docker tag image-id username/repository:tag.

  • docker images: List all images on the local machine. docker rmi: Remove an image from the local machine. For example, docker rmi 4535, where 4535 is an ID of an existing image on your machine.


Dockerfile vs Docker Compose#

Both Dockerfile and Docker Compose are tools in the Docker image ecosystem. Dockerfile is a text file that contains an image, and the commands a developer can call to assemble the image. The commands are typically simple processes like installing dependencies, copying files, and configuring settings.

Docker Compose is a tool for defining and running multi-container Docker applications. Information describing the services and networks for an application are contained within a YAML file, called docker-compose.yml.

One of the base functions of Docker Compose is to build images from Dockerfiles. However, Docker Compose is capable of orchestrating the containerization and deployment of multiple software packages. You can select which images are used for certain services, set environment-specific variables, configure network connections, and much more.

Below are the three necessary steps that begin most Docker workflows:

  • Building a Dockerfile for each image you wish to add
  • Use Docker Compose to assemble the images with the build command.
  • Specify the path to individual Dockerfiles using the build command in conjunction with /path/to/dockerfiles

In summary, Dockerfiles define the instructions to a single image in an application, but Docker Compose is the tool that allows you to create and manipulate a multi-container application.

Docker Compose vs Kubernetes: When should you use each?#

As developers move beyond single containers and start building real-world applications, they eventually encounter two important tools: Docker Compose and Kubernetes. Both help manage containerized applications, but they solve different problems and operate at different scales.

Docker Compose focuses on running multiple containers together with minimal configuration. Kubernetes is a full container orchestration platform designed to manage large, distributed applications across many machines.

The important thing to understand is that these tools are not competitors as much as they are complementary. Many developers learn Docker Compose first, use it for local development, and later adopt Kubernetes when their applications and infrastructure grow more complex.

Understanding the relationship#

Docker Compose helps you define and run multi-container applications using a simple YAML file. It excels at local development, testing environments, and small deployments.

Kubernetes goes much further. It handles scheduling containers across clusters, scaling applications automatically, recovering from failures, managing service discovery, and supporting production workloads at scale.

A useful way to think about it is:

  • Docker Compose manages containers on a single machine.

  • Kubernetes manages containers across many machines.

Docker Compose vs Kubernetes comparison#

Category

Docker Compose

Kubernetes

Primary purpose

Multi-container application development

Container orchestration at scale

Learning curve

Low

High

Complexity

Simple

Complex

Local development

Excellent

Possible but often overkill

Production deployments

Small-scale deployments

Designed for production

Scaling

Manual or limited

Built-in auto-scaling

Load balancing

Basic

Advanced

Self-healing

No

Yes

Service discovery

Basic service names

Built-in cluster DNS

Configuration management

Environment variables and Compose files

ConfigMaps, Secrets, and more

Multi-host support

No

Yes

Resource requirements

Low

Higher

Best team size

Individual developers and small teams

Medium to large teams

When to use Docker Compose#

Docker Compose is ideal when simplicity matters more than scalability.

It's particularly useful for:

  • Local development environments

  • Learning Docker and containers

  • Personal projects

  • Small web applications

  • Continuous integration testing

  • Proofs of concept

Practical examples#

Flask + PostgreSQL#

A developer building a Flask application can start both the application and database with a single command:

docker compose up

Node.js + Redis#

Docker Compose makes it easy to run an application server and cache locally without installing dependencies directly on your machine.

Local microservice development#

A team developing several services can run them together on a laptop while preserving realistic networking behavior.

In these situations, Kubernetes often adds complexity without providing significant benefits.

When to use Kubernetes#

Kubernetes becomes valuable when applications grow beyond a few containers or require production-grade reliability.

Common use cases include:

  • Production systems

  • High-availability applications

  • Large microservice architectures

  • Cloud-native applications

  • Enterprise deployments

  • Auto-scaling workloads

Practical examples#

E-commerce platform#

An online store may run dozens of services including:

  • Product catalog

  • Inventory management

  • Payments

  • Search

  • Recommendations

Kubernetes can manage these services across multiple servers and recover automatically if a node fails.

SaaS product#

As customer traffic grows, Kubernetes can automatically scale application instances based on CPU or memory usage.

Streaming platform#

Video processing, recommendations, analytics, and APIs can all be scaled independently.

Large API infrastructure#

Organizations running hundreds of APIs often use Kubernetes to standardize deployments and operations.

Real-world workflow#

Most teams do not start with Kubernetes.

A much more common workflow looks like this:

Step 1: Develop locally with Docker Compose#

Developers use Docker Compose on their laptops to run services together.

Developer laptop↓Docker Compose↓Application + Database + Cache

Step 2: Test service interactions#

Compose allows developers to verify:

  • Networking

  • Environment variables

  • Service dependencies

  • Local integration testing

before deploying anything.

Step 3: Deploy to Kubernetes#

Once the application reaches production scale, Kubernetes takes over.

Local Development↓Docker Compose↓CI/CD Pipeline↓Kubernetes Cluster↓Production Environment

This progression is common across startups, SaaS companies, and enterprise engineering teams.

Can Kubernetes replace Docker Compose?#

Technically, yes.

You can run local environments with Kubernetes using tools such as:

  • Minikube

  • Kind

  • Docker Desktop Kubernetes

However, that doesn't mean you should.

For many projects:

  • Compose is easier to configure

  • Startup time is faster

  • Resource consumption is lower

  • Troubleshooting is simpler

Using Kubernetes for a two-container side project is often like using a cargo ship to cross a small pond.

The additional operational complexity may not provide enough value.

What do companies actually use?#

The answer depends largely on company size and application complexity.

Startups#

Many startups begin with:

  • Docker

  • Docker Compose

  • Simple cloud deployments

Their priority is shipping features quickly.

Growing companies#

As infrastructure becomes more complex, teams often introduce Kubernetes to improve:

  • Scalability

  • Reliability

  • Deployment automation

Enterprises#

Large organizations frequently standardize on Kubernetes because it provides:

  • Consistent deployments

  • Multi-team coordination

  • Cluster-wide resource management

  • Cloud portability

That said, even companies running Kubernetes in production often continue using Docker Compose for local development.

How do you choose?#

Use Docker Compose if:#

  • You're learning containers

  • You need local development environments

  • You have a small team

  • Your application consists of only a few services

  • You want a fast and simple workflow

Use Kubernetes if:#

  • You need high availability

  • You manage many services

  • You require auto-scaling

  • You operate production infrastructure at scale

  • You need advanced deployment strategies and orchestration

The goal isn't to use the most powerful tool—it's to use the right tool for your current needs.

Quick-reference guide#

Local development

Docker Compose

CI testing

Docker Compose

Small startup application

Docker Compose

Personal projects

Docker Compose

Large production system

Kubernetes

Microservices at scale

Kubernetes

Multi-region deployment

Kubernetes

Enterprise platform

Kubernetes

Auto-scaling workloads

Kubernetes

Docker Compose and Kubernetes solve different problems at different stages of an application's lifecycle. Docker Compose excels at simplicity, local development, and smaller deployments, while Kubernetes shines when reliability, scalability, and automation become critical.

For most developers, the best path is straightforward: learn Docker first, become comfortable with Docker Compose, and then explore Kubernetes when you encounter problems that Compose was never designed to solve.

One reason Docker Compose remains so widely used today is that many applications simply don't need the operational complexity that Kubernetes introduces. Choosing the simpler tool when it meets your requirements is often the best engineering decision.

Getting started with Docker Compose build#

Now for the advanced stuff. Docker Compose is a Docker tool used to define and run multi-container applications. With Compose, you use a YAML file to configure your application’s services and create all the app’s services from that configuration.

Think of docker-compose as an automated multi-container workflow. Compose is an excellent tool for development, testing, CI workflows, and staging environments. According to the Docker documentation, the most popular features of Docker Compose are:

  • Multiple isolated environments on a single host
  • Preserve volume data when containers are created
  • Only recreate containers that have changed
  • Variables and moving a composition between environments
  • Orchestrate multiple containers that work together


How to use and install Docker Compose#

Compose uses the Docker Engine, so you’ll need to have the Docker Engine installed on your device. You can run Compose on Windows, Mac, and 64-bit Linux. Installing Docker Compose is actually quite easy.

On desktop systems, such as Docker Desktop for Mac and Windows, Docker Compose is already included. No additional steps are needed. On Linux systems, you’ll need to:

  1. Install the Docker Engine
  2. Run the following command to download Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
  1. Apply permissions to the binary, like so:
sudo chmod +x /usr/local/bin/docker-compose
  1. Test the installation to check it worked properly
$ docker-compose --version
docker-compose version 1.26.2, build 1110ad01

Regardless of how you chose to install it, once you have Docker Compose downloaded and running properly, you can start using it with your Dockerfiles. This process requires three basic steps:

  1. Define your app’s environment using a Dockerfile. This way, it can be reproduced.
  2. Define the services for your app in a docker-compose.yml file. This way, they can run in an isolated environment.
  3. Run docker-compose to start your app.

You can easily add Docker Compose to a pre-existing project. If you already have some Dockerfiles, add Docker Compose files by opening the Command Palette. Use the Docker: Docker Compose Files to the Workspace command, and, when promoted, choose the Dockerfiles you want to include.

You can also add Docker Compose files to your workspace when you add a Dockerfile. Similarly, open the Command Palette and use the Docker: Add Docker Files to Workspace command.

You’ll then be asked if you want to add any Docker Compose files. In both cases, Compose extension will add the docker-compose.yml file to your workspace.


Docker Compose file structure#

Now that we know how to download Docker Compose, we need to understand how Compose files work. It’s actually simpler than it seems. In short, Docker Compose files work by applying multiple commands that are declared within a single docker-compose.yml configuration file.

The basic structure of a Docker Compose YAML file looks like this:

version: 'X'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
redis:
image: redis

Now, let’s look at a real-world example of a Docker Compose file and break it down step-by-step to understand all of this better. Note that all the clauses and keywords in this example are industry-standard and commonly used.

With just these, you can start a development workflow. There are some more advanced keywords that you can use in production, but for now, let’s just get started with the necessary clauses.

version: '3'
services:
web:
# Path to dockerfile.
# '.' represents the current directory in which
# docker-compose.yml is present.
build: .
# Mapping of container port to host
ports:
- "5000:5000"
# Mount volume
volumes:
- "/usercode/:/code"
# Link database container to app container
# for reachability.
links:
- "database:backenddb"
database:
# image to fetch from docker hub
image: mysql/mysql-server:5.7
# Environment variables for startup script
# container will use these variables
# to start the container with these define variables.
environment:
- "MYSQL_ROOT_PASSWORD=root"
- "MYSQL_USER=testuser"
- "MYSQL_PASSWORD=admin123"
- "MYSQL_DATABASE=backend"
# Mount init.sql file to automatically run
# and create tables for us.
# everything in docker-entrypoint-initdb.d folder
# is executed as soon as container is up nd running.
volumes:
- "/usercode/db/init.sql:/docker-entrypoint-initdb.d/init.sql"
  • version ‘3’: This denotes that we are using version 3 of Docker Compose, and Docker will provide the appropriate features. At the time of writing this article, version 3.7 is latest version of Compose.

  • services: This section defines all the different containers we will create. In our example, we have two services, web and database.

  • web: This is the name of our Flask app service. Docker Compose will create containers with the name we provide.

  • build: This specifies the location of our Dockerfile, and . represents the directory where the docker-compose.yml file is located.

  • ports: This is used to map the container’s ports to the host machine.

  • volumes: This is just like the -v option for mounting disks in Docker. In this example, we attach our code files directory to the containers’ ./code directory. This way, we won’t have to rebuild the images if changes are made.

  • links: This will link one service to another. For the bridge network, we must specify which container should be accessible to which container using links.

  • image: If we don’t have a Dockerfile and want to run a service using a pre-built image, we specify the image location using the image clause. Compose will fork a container from that image.

  • environment: The clause allows us to set up an environment variable in the container. This is the same as the -e argument in Docker when running a container.

Congrats! Now you know a bit about Docker Compose and the necessary parts you’ll need to get started with your workflow.

Docker Compose commands#

Now that we know how to create a docker-compose file, let’s go over the most common Docker Compose commands that we can use with our files. Keep in mind that we will only be discussing the most frequently-used commands.

docker-compose: Every Compose command starts with this command. You can also use docker-compose <command> --help to provide additional information about arguments and implementation details.

$ docker-compose --help
Define and run multi-container applications with Docker.

docker-compose build: The build command builds or rebuild images in the docker-compose.yml file. This file contains all the necessary configurations for all the services that make up the application.

The job of the build command prepares images to create containers. If a service is using the pre-built image, it will skip this command. The docker-compose build command reads the Dockerfile for each service, including the instructions to build the image. The built images can then be used to create containers for each service using the docker-compose up command.

Furthermore, we use the docker-compose build command for building the images for the services in a consistent and reproducible way, making deployment in different environments easier.

$ docker-compose build
database uses an image, skipping
Building web
Step 1/11 : FROM python:3.9-rc-buster
 ---> 2e0edf7d3a8a
Step 2/11 : RUN apt-get update && apt-get install -y docker.io

docker-compose images: This command will list the images you’ve built using the current docker-compose file.

$ docker-compose images
          Container                  Repository        Tag       Image Id       Size  
--------------------------------------------------------------------------------------
7001788f31a9_docker_database_1   mysql/mysql-server   5.7      2a6c84ecfcb2   333.9 MB
docker_database_1                mysql/mysql-server   5.7      2a6c84ecfcb2   333.9 MB
docker_web_1                     <none>               <none>   d986d824dae4   953 MB

docker-compose stop: This command stops the running containers of specified services.

$ docker-compose stop
Stopping docker_web_1      ... done
Stopping docker_database_1 ... done

docker-compose run: This is similar to the docker run command. It will create containers from images built for the services mentioned in the compose file.

$ docker-compose run web
Starting 7001788f31a9_docker_database_1 ... done
 * Serving Flask app "app.py" (lazy loading)
 * Environment: development
 * Debug mode: on
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 116-917-688

docker-compose up: This command does the work of the docker-compose build and docker-compose run commands. It builds the images if they are not located locally and starts the containers. If images are already built, it will fork the container directly.

$ docker-compose up
Creating docker_database_1 ... done
Creating docker_web_1      ... done
Attaching to docker_database_1, docker_web_1

docker-compose ps: This command list all the containers in the current docker-compose file. They can then either be running or stopped.

$ docker-compose ps
      Name                 Command             State               Ports         
---------------------------------------------------------------------------------
docker_database_1   /entrypoint.sh mysqld   Up (healthy)   3306/tcp, 33060/tcp   
docker_web_1        flask run               Up             0.0.0.0:5000->5000/tcp
 
$ docker-compose ps
      Name                 Command          State    Ports
----------------------------------------------------------
docker_database_1   /entrypoint.sh mysqld   Exit 0        
docker_web_1        flask run               Exit 0    

docker-compose down: This command is similar to the docker system prune command. However, in Compose, it stops all the services and cleans up the containers, networks, and images.

$ docker-compose down
Removing docker_web_1      ... done
Removing docker_database_1 ... done
Removing network docker_default
(django-tuts) Venkateshs-MacBook-Air:Docker venkateshachintalwar$ docker-compose images
Container   Repository   Tag   Image Id   Size
----------------------------------------------
(django-tuts) Venkateshs-MacBook-Air:Docker venkateshachintalwar$ docker-compose ps
Name   Command   State   Ports
------------------------------

Congrats! You’ve now learned most of the basic commands for Docker Compose. Why stop there? Check out the documentation of other commands and keep learning!

Working with Containers: Docker and Docker Compose

Cover
Working with Containers: Docker & Docker Compose

Whether you are a DevOps beginner or just a developer who wants to start working with containers, you’re in the right place. Docker is an in-demand technology that you will be exposed to frequently while on the job. Docker is used for setting up, deploying, and running applications, at scale, by containerizing them. More on that later. Docker also provides developers with a consistent environment for product development, and along with Kubernetes, makes managing the development lifecycle a breeze. In this course, you will learn the fundamentals of Docker such as containers, images, and commands. You’ll then progress to more advanced concepts like connecting to a database container and how to simplify workflows with Docker Compose. At the end, you’ll learn how to monitor clusters and scale Docker services with Swarm.

5hrs
Beginner
16 Playgrounds
5 Quizzes

Top 10 Docker Compose errors and how to fix them#

Docker Compose dramatically simplifies multi-container development, but when something goes wrong, the error messages can feel overwhelming—especially if you're new to Docker. The good news is that most Docker Compose issues fall into a handful of common categories involving ports, networking, volumes, environment variables, or configuration mistakes.

This troubleshooting guide covers the errors developers encounter most frequently when working with Docker Compose. For each issue, you'll learn how to identify the root cause, inspect the relevant logs, and apply the correct fix.

Most Docker Compose issues can be solved by checking logs, validating YAML, and verifying network/service names.

Common Docker Compose errors#

Error

Common cause

How to fix it

Port already in use

Another process or container is using the port

Change the port mapping or stop the conflicting process

Service cannot connect to database

Wrong hostname, startup timing, or networking issue

Use service names, configure dependencies, and verify networks

Container exits immediately

Application crashes or startup command fails

Inspect logs and verify CMD/ENTRYPOINT

Docker Compose command not found

Compose not installed or wrong version usage

Verify installation and use the correct command

Volume mount issues

Incorrect paths or permission problems

Check paths and file permissions

YAML syntax errors

Invalid indentation or formatting

Validate YAML and use spaces instead of tabs

Build failures

Dockerfile issues or invalid build context

Verify Dockerfile and COPY paths

Environment variables not loading

Missing .env file or incorrect syntax

Verify variable names and file placement

Network communication failures

Containers on different networks

Verify network configuration and service names

Permission denied errors

Ownership or filesystem permission issues

Adjust permissions and container user settings

1. Port already in use#

Example error#

Bind for 0.0.0.0:5432 failed: port is already allocated

Why it happens#

Docker cannot bind a container port if another application or container is already using it.

Common causes include:

  • A local PostgreSQL instance running on the host

  • Another Docker container already using the same port

  • A previously stopped container not cleaned up properly

How to fix it#

First, identify what's using the port:

lsof -i :5432

Or:

netstat -tulpn | grep 5432

Check running containers:

docker ps

You can then either stop the conflicting process or change the Compose port mapping:

ports:- "5433:5432"

2. Service cannot connect to database#

Example error#

Connection refusedCould not connect to database host localhost

Why it happens#

Many developers mistakenly use localhost inside containers.

Within Docker Compose, containers communicate using service names rather than localhost.

Incorrect configuration#

DATABASE_HOST=localhost

Correct configuration#

DATABASE_HOST=db

Where db is the database service name:

services:app:...db:image: postgres

Additional fixes#

Add startup dependencies:

depends_on:- db

Verify networking:

docker compose ps
docker inspect <container_name>

3. Container exits immediately#

Example error#

Exited (1)

Why it happens#

The container's main process crashes immediately after startup.

Common causes:

  • Application exceptions

  • Missing environment variables

  • Incorrect startup commands

  • Invalid configuration files

How to investigate#

View logs:

docker compose logs

View logs for a specific service:

docker compose logs app

Run interactively:

docker compose run app sh

Also verify:

  • CMD

  • ENTRYPOINT

  • Environment variables

  • Application startup configuration


4. Docker Compose command not found#

Example error#

docker-compose: command not found

Why it happens#

Modern Docker installations use Compose V2.

Older tutorials often use:

docker-compose

Newer installations use:

docker compose

How to verify#

docker compose version

Or:

docker --version

If Compose is missing entirely, update Docker Desktop or install Docker Compose separately.


5. Volume mount issues#

Example error#

No such file or directory

Or:

Permission denied

Why it happens#

Typical causes include:

  • Incorrect host path

  • Missing directory

  • Relative path confusion

  • Permission restrictions

Example#

volumes:- ./app:/usr/src/app

Verify the host path exists:

ls -la ./app

Using absolute paths can sometimes eliminate ambiguity:

volumes:- /home/user/project/app:/usr/src/app

6. YAML syntax errors#

Example error#

yaml: line 12: mapping values are not allowed here

Why it happens#

YAML is whitespace-sensitive.

Common mistakes:

  • Tabs instead of spaces

  • Missing colons

  • Incorrect indentation

Example#

Incorrect:

services:app:image: nginx

Correct:

services:app:image: nginx

Helpful validation command#

docker compose config

This validates and renders the final Compose configuration.


7. Build failures#

Example error#

COPY failed: file not found

Why it happens#

Docker cannot locate files referenced in the Dockerfile.

Common causes#

  • Incorrect build context

  • Wrong file paths

  • Missing Dockerfile

Verify build configuration#

build:context: .dockerfile: Dockerfile

Rebuild with detailed output#

docker compose build --no-cache

Check all COPY and ADD statements carefully.


8. Environment variables not loading#

Example error#

DATABASE_URL is not defined

Why it happens#

Compose cannot find the variable definition.

Verify .env#

cat .env

Example:

DATABASE_URL=postgres://user:pass@db:5432/app

Common mistakes#

Incorrect:

DATABASE_URL = value

Correct:

DATABASE_URL=value

Validate resolved configuration#

docker compose config

9. Network communication failures#

Example error#

Temporary failure in name resolution

Why it happens#

Containers cannot discover each other because they are not attached to the same network.

Verify networks#

docker network ls

Inspect configuration:

docker inspect <container_name>

Best practice#

Use service names:

DATABASE_HOST=dbREDIS_HOST=redis

Avoid using container IP addresses.


10. Permission denied errors#

Example error#

Permission denied

Why it happens#

Container users may not have permission to access mounted files.

This commonly occurs on Linux systems.

Verify ownership#

ls -la

Update permissions:

chmod -R 755 ./data

Or change ownership:

chown -R $USER:$USER ./data

You can also configure container users explicitly when necessary.


Essential Docker Compose debugging commands#

docker compose logs

View container logs

docker compose ps

List running containers

docker compose exec <service> sh

Open a shell inside a container

docker compose config

Validate and render Compose configuration

docker inspect <container>

View detailed container information

docker network ls

List Docker networks

docker compose build --no-cache

Rebuild images from scratch

docker compose down

Stop and remove containers

docker compose up -d

Start containers in detached mode

When Docker Compose fails, start with the basics: logs, configuration validation, networking, and service names. Most issues are not Docker bugs—they're usually configuration problems that can be identified quickly with the right debugging workflow.

A good rule of thumb is to check logs first, validate your Compose file second, and inspect networking and environment variables third. Following this process will solve the vast majority of Docker Compose issues you'll encounter in development and CI/CD environments.


Take your Docker knowledge to the next level#

We hope this has familiarized you with Docker Compose and its offers. There’s still a lot to explore and learn to be a true Docker Compose master. Once you are comfortable making docker-compose files and working with the necessary commands, you can move onto the following advancements:

  • Working with multiple Dockerfiles in Compose (common for microservices)
  • Docker Compose environment variables (.env files)
  • Docker Swarm (for scaling and monitoring clusters)
  • Automated deployments with Docker Stack
  • and more

Educative’s advanced Docker course Working with Containers: Docker & Docker Compose is an ideal place to learn these concepts and beyond. Not only will you get a refresher on Docker fundamentals, but you’ll also progress from beginner to advanced concepts like connecting to a web app/database container, building service container images, learning how to utilize the Docker dev CLI plugin, learning how to define services in a compose file, setting build time variables for images, testing, and debugging when needed, working with standalone containers, and hands-on practice with Docker Compose. In the end, you’ll even learn how to monitor clusters and scale Docker services with Swarm.

Jumpstart your career and become an in-demand Docker developer!

At the end, you’ll even learn how to monitor clusters and scale Docker services with Swarm. Jumpstart your career and become an in-demand Docker developer!


Continue reading#

Frequently Asked Questions

What is Docker Compose used for?

Docker Compose is a good tool for defining and managing multicontainer applications. It allows you to create a YAML file where you can specify all your services, and with just one command, you can start or shut down your entire application stack.


Written By:
Amanda Fawcett