Living in the container era, Docker is now a household name. And when we need to define and run multiple containers together, we naturally think of Docker Compose. But have you ever noticed that what used to be a separate binary command called docker-compose
is now integrated as part of the Docker CLI in the form of docker compose
! 🚀.
In this article, we’ll dive into the details of how Docker Compose evolved into the docker compose
plugin, why this change happened, and how you can utilize this powerful tool.
—.
1. What is Docker Compose Plugin (What is Docker Compose Plugin?)
Traditionally, docker-compose
was a separate standalone application developed in Python. When you ran the docker-compose up
command, the docker-compose
binary installed on your system would run, interpreting the docker-compose.yml
file and communicating with the Docker Engine API to manage containers.
However, the docker compose
plugin is now integrated as one of the native subcommands of the Docker CLI, meaning it’s no longer an external command. Just like you use docker run
, docker build
, and so on, docker compose
is just a command that you put after the docker
command. It’s rewritten in Go language and works on the same foundation as the Docker CLI.
💡 Key takeaways:
- Previously:
docker-compose [command]
(separate binary) - Current:
docker compose [command]
(built-in plugin in the Docker CLI)
—.
2. Why the change to a plugin? (Why the Change?)
There are a few important reasons for this change.
2.1. Consistency & Integration 🤝
Docker is moving towards extending and integrating many of its features as plugins. By making docker compose
a plugin, users will be able to perform all Docker-related tasks under one consistent prefix, docker
. This simplifies the user experience and reduces command confusion.
For more information, see: #### 2.2. Performance Improvement ⚡
The old Python-based docker-compose
tended to have a relatively long startup time or use more resources. Rewritten in Go, the docker compose
plugin is much faster and more efficient. This is especially noticeable when managing many containers in large projects.
2.3. Easier Maintenance & Development 🛠️
The Go language is the core language of the Docker ecosystem. By switching docker compose
to Go, the Docker Core team is able to maintain and develop Compose features with the same language and toolchain as the existing Docker Engine and CLI. This makes bug fixes and new feature additions faster.
You can learn more about Compose here: #### 2.4. Simpler Installation ✅
Most modern Docker Desktop versions (Windows, macOS) or Docker Engine installations include the docker compose
plugin by default. You no longer need to install docker-compose
separately with pip
, etc.
—]
3. Key Features & Advantages
The docker compose
plugin inherits all the core functionality of the original docker-compose
and adds the advantages mentioned above.
- Supports the same
docker-compose.yml
file format: You can use your existing YAML files without any changes. This eliminates the migration burden. - Intuitive container orchestration: Build, start, stop, and delete multiple containers with a single command.
- Environment isolation: Build independent container environments for each project to avoid dependency conflicts.
- Scalability and flexibility:** Service definitions, networks, volumes, and more are clearly defined in YAML files, making it easy to manage even complex application stacks.
—.
4. How to Use It (How to Use It?)
The usage is almost the same as docker-compose
, you just need to prefix the command with docker
.
4.1. Check the installation
Most modern Docker Desktop users, or Linux users who installed Docker Engine with apt
or yum
, should already have the docker compose
plugin installed. Check your version with the following command
docker compose version
If you don’t have it installed, you’ll need to install it using the official Docker documentation. (It’s easiest to install Docker Desktop).
4.2. Practice with a simple example project
Let’s familiarize ourselves with the usage by running a simple web application (Flask) and database (Redis) with docker compose
.
First, create the following files
my_flask_app/
├── app.py
├── Dockerfile
├── requirements.txt
└── docker-compose.yml
1. app.py
(Flask application) **2.
from flask import Flask
from redis import Redis
app = Flask(__name__)
redis = Redis(host='redis', port=6379) # Connect to service name 'redis'
@app.route('/')
def hello():
count = redis.incr('hits')
return f'Hello Docker! This page has been viewed {count} times.\n'
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, debug=True)
2. requirements.txt
flask
redis
3. Dockerfile
(for building Flask applications)
FROM python:3.9-slim-buster
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]
**4. docker-compose.yml
(most important!)
version: '3.8'
services:
. web:
build: .
ports:
- "5000:5000"
volumes:
- .:/app # Mount the current directory on the host to /app in the container
depends_on:
- redis
environment:
FLASK_ENV: development
# Uncomment the line below to reflect code changes without restarting the Flask app.
# command: flask run --host=0.0.0.0 --port=5000 --debug --reload
redis:
# use the official redis image. image: "redis:alpine" # use the official redis image.
ports:
- "6379:6379" # Connect local 6379 port to container 6379 port.
4.3. Using the docker compose
command
Now go to the my_flask_app
directory and run the following command.
**1. build and run the service (in the background)
cd my_flask_app
docker compose up -d
up
: Create and start the service defined in thedocker-compose.yml
file.-d
: (detached mode) Run the container in the background.
**2. Check the running service
docker compose ps
With this command, you can check the status of the web
and redis
services.
Example output:
name command service status ports
my_flask_app-redis-1 "docker-entrypoint.s..." redis running 0.0.0.0:6379->6379/tcp
my_flask_app-web-1 "python app.py" web running 0.0.0.0:5000->5000/tcp
**3. Access the web application
Now open a web browser and try to connect to http://localhost:5000
. Each time you refresh the page, you should see “Hello Docker! This page has been viewed N times.” You should see the number in the message increase. This means that the Flask app is successfully communicating with the Redis database.
**4. Check the service logs
docker compose logs web
You can check the logs of the web
service in real time. To view the logs of the redis
service, use docker compose logs redis
.
**5. Stop and delete the service When you’re done, you can stop and delete the running containers with the following commands
docker compose down
down
: Stops the services started withup
and removes the defined network and volumes.
—]
5. Frequently used docker compose
commands (Common Commands)
Command | Description |
---|---|
docker compose up |
Builds and starts all the services defined in docker-compose.yml |
docker compose up -d |
Start all services in the background (detached mode). |
docker compose down |
Stops all running services and removes containers, networks, and volumes. |
docker compose ps |
Show the status of running services. |
docker compose logs [service-name] |
Displays the logs for a specific service, for example, docker compose logs web . |
docker compose build |
Builds the service image (to avoid rebuilding on subsequent up s). |
docker compose exec [service name] [command] |
Runs a command inside a specific running service container. (For example, docker compose exec web bash ) |
docker compose restart [ServiceName] |
Restarts a specific service. |
docker compose pull |
Pre-downloads images for all services defined in docker-compose.yml . |
docker compose config |
Validates the docker-compose.yml file and outputs the final merged configuration. |
—]
- Use multiple Compose files (
-f
): * **Use multiple Compose files. This is useful when you want to apply different settings for development, staging, and production environments.docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
- Using environment variables: **
`` Within the
docker-compose.ymlfile, you can reference environment variables in the form of
$VAR_NAME, and you can use the
.env` file to manage them.# .env file contents DB_PASSWORD=mysecretpassword
# used in docker-compose.yml services: db: environment: mysql_root_password: ${db_password}
- Profiles: * **Docker-compose.yml
You can define multiple service groups inside one
docker-compose.yml
file and run only certain groups as needed.services: frontend: profiles: ["dev"] # ... backend: profiles: ["dev", "prod"] # ... admin: profiles: ["prod"] # ...
docker compose --profile dev up # Run only services belonging to the dev profile
-
- Reuse settings with the
extends
keyword: Reuse settings with theextends
keyword Use to reduce repetitive service definitions and increase reusability.
- Reuse settings with the
—]
Conclusion
The docker compose
plugin represents the future of Docker container orchestration. It retains the same powerful features, while providing deeper integration with the Docker CLI, improved performance, and easier usability. Now docker compose
is a more robust and indispensable tool for managing multiple container applications, from development environments to single-host deployments.
We hope this article has helped you gain a better understanding of the docker compose
plugin, and that it will help you improve your container development and deployment workflows to be more efficient. If you have any questions, feel free to ask them in the comments! Happy containerizing! 🐳✨