We can all agree that in this era the concept of containerization is almost everywhere. This technology was mainly started to curb the complexity of applications and infrastructure which were resource intensive and very expensive. With containerization, an application is bundled with all the required dependencies in a lightweight executable referred to as a container. This makes it easier to run and maintain the application. Containerization offers a lot of features and benefits such as portability, scalability, isolation, efficiency, simplified deployment and management, versioning and rollbacks etc.
There are quite a number of tools used to run containers, among them are Docker, Podman, Kubernetes, contained, CRI-O, rkt, LXC/LXD etc. In this guide, our main focus is on Podman and Docker.
Podman and Docker are container runtime platforms that hold a lot of similarities. They allow users to build, run, and manage containers. However, they possess some differences:
Docker is a popular and widely used tool that offers a complete ecosystem for container management using Docker Engine, Docker CLI, and Docker Compose. The key features of Docker are:
- Dockerfile: This is a declarative configuration file that defines the steps required when building container images.
- Docker Hub; It is a cloud-based registry that stores and helps you share the container images.
- Docker CLI: Thi is a command-line tool that makes it possible to interact with the Docker daemon to build images, run containers and manage other container resources.
- Docker Compose: This tool is used to run multiple container applications defined in a YAML file.
Podman is the short form of Pod Manager. This is an open-source container runtime that acts as a drop-in replacement for Docker. It is a component of a large container ecosystem, libpod, which provides other tools like Buildah and Skopeo. As opposed to Docker, Podman is daemonless. It doesn’t require a separate daemon to run containers as it interacts directly with the container runtime in the Linux kernel.
Podman Compose just like Docker Compose is used to run multiple containers defined in a declarative YAML file. In this guide, we will learn how to use Docker / Podman Compose on Debian 12 (Bookworm).
Install Docker / Podman Compose
Docker Compose relies on the Docker daemon to operate, while Podman Compose is designed to work with Podman. So use any of the tools, and ensure that the required container runtime is installed.
- Install Docker and Docker Compose on Debian 12 (Bookworm).
Once installed, verify with the command:
$ docker-compose version
Docker Compose version v2.18.1
- Install Podman and Podman Compose on Debian 12 (Bookworm).
Verify the installation with the command:
$ podman-compose version
['podman', '--version', '']
using podman version: 4.3.1
podman-composer version 1.0.3
podman --version
podman version 4.3.1
exit code: 0
Now we are set to use Docker / Podman Compose on Debian 12 (Bookworm).
Using Docker / Podman Compose
Now Docker/Podman Compose can be used to perform several container management tasks. In this guide, we will cover some of the tasks that can be performed using Docker / Podman Compose.
To work with any of these tools, you need to have a declarative YAML file. The file can contain directives. The most popular ones are:
- version: specifies the Docker / Podman Compose version to be used.
- services: This is the name of the container. The section contains several other directives
- networks: this is used to configure the application’s network. You can define the app-specific network
- volumes: maps volumes on the host machine to the container
The services section contains many other directives, the common ones are:
- image: specifies the images to be used by the container. This can be from the local registry or an external one like Docker Hub.
- build: can be used in place of the image directive. This specifies the location of the Dockerfile used to build the image.
- Name: this can be any name for the container for example web, db etc
- restart: instructs the container to restart when the system restarts
- volumes: this links the path on the host machine to the container
- environment: all the environment variables for the container are declared here
- depends_on: sets a dependency to another container.
- port: used to expose container ports with the syntax
host:container
- links: links service to the other in the container using their names
Below is a sample YAML with all the above variables used:
version: '3'
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
volumes:
db_data:
In this guide, we will have a step-by-step demonstration of how to manage a container(s) using Docker / Podman Compose on Debian 12 (Bookworm).
a. Run a Single Application
We will start by demonstrating how to run a single container. First, create a YAML file:
vim docker-compose.yaml
In the file, declare the required directives. For this guide, we will run a simple Nginx container.
version: '3'
services:
web:
image: docker.io/library/nginx:latest
container_name: Nginx
ports:
- "8080:80"
volumes:
- ./src:/usr/share/nginx/html
environment:
- NGINX_HOST=test.computingforgeeks.com
- NGINX_port=80
Save the file and start the container:
##Docker Compose
docker-compose up -d
##Podman Compose
podman-compose up -d
Here, the image will be pulled and the container started. Verify if the container is running:
docker-compose ps
##OR
podman-compose ps
Sample output:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
Nginx nginx:latest "/docker-entrypoint.…" web About a minute ago Up About a minute 0.0.0.0:8080->80/tcp, :::8080->80/tcp
That is it, the container is running. You can also use podman
or docker
commands:
$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
378816ee13e2 docker.io/library/nginx:latest nginx -g daemon o... About a minute ago Up About a minute 0.0.0.0:8080->80/tcp Nginx
2aaa9e372e87 docker.io/library/postgres:latest postgres About a minute ago Up About a minute 0.0.0.0:5432->5432/tcp postgres_db
b. Run Multiple Services
The main purpose of Docker / Podman Compose is to run multiple containers at once. To achieve this, you need to declare the services in the YAML. Open the YAML:
vim docker-compose.yaml
Add the desired container, for example the database container:
version: '3'
services:
web:
image: docker.io/library/nginx:latest
container_name: Nginx
ports:
- "8080:80"
volumes:
- ./src:/usr/share/nginx/html
environment:
- NGINX_HOST=test.computingforgeeks.com
- NGINX_port=80
database:
image: docker.io/library/postgres:latest
container_name: postgres_db
volumes:
- ./dumps:/tmp/
environment:
- POSTGRES_PASSWORD=Passw0rd!
ports:
- "5432:5432"
Run the containers:
##Docker Compose
docker-compose up -d
##Podman Compose
podman-compose up -d
Check the status:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
Nginx docker.io/library/nginx:latest "/docker-entrypoint.…" web 11 minutes ago Up 11 minutes 0.0.0.0:8080->80/tcp, :::8080->80/tcp
postgres_db docker.io/library/postgres:latest "docker-entrypoint.s…" database 12 seconds ago Up 11 seconds 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp
Now we have two containers running. You can have as many containers as possible in the YAML.
c. Build and Use container image
Instead of pulling an image, you can build your own image and use it to run a container. But first, you need to have a Dockerfile created.
git clone https://github.com/docker/getting-started.git
cd getting-started/app
vim Dockerfile
Add the desired directives in the Dockerfile:
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
EXPOSE 3000
You can now create a docker-compose file that uses the Dockerfile:
$ vim docker-compose.yaml
version: '3'
services:
web:
build:
context: .
dockerfile: Dockerfile
container_name: node_app
ports:
- 3000:3000
Build the image and start the container:
docker-compose up -d --build
##OR
podman-compose up -d --build
Sample Output:

View the status of the container:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
node_app app-web "docker-entrypoint.s…" web 25 seconds ago Up 24 seconds 0.0.0.0:3000->3000/tcp, :::3000->3000/tcp
d. Persistent Data Storage
Persistent data storage is used to store container data that survives after the container has been restarted. This is so important when running production deployments.
To declare persistent storage, the volumes
directive is used. For example, on our database container, we can add persistent storage as shown:
version: '3'
services:
web:
image: docker.io/library/nginx:latest
container_name: Nginx
ports:
- "8080:80"
volumes:
- ./src:/usr/share/nginx/html
environment:
- NGINX_HOST=test.computingforgeeks.com
- NGINX_port=80
database:
image: docker.io/library/postgres:latest
container_name: postgres_db
volumes:
- data:/var/lib/postgresql
environment:
- POSTGRES_PASSWORD=Passw0rd
ports:
- "5432:5432"
volumes:
data:
external: true
Now in the above file, external: true
instructs Docker/Podman to use an existing external volume. If the volume with the name data
is not present, you might face errors starting the container.
So create the volume:
docker volume create --name=data
##OR
podman volume create data
Now start the container:
docker-compose up -d
##OR
podman-compose up -d
Once started, the volume will be used to persist data.
$ docker volume inspect data
[
{
"CreatedAt": "2023-06-21T07:58:36-04:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/data/_data",
"Name": "data",
"Options": null,
"Scope": "local"
}
]
e. Start, stop and Remove Containers
you can also start, stop and delete containers using Docker/Podman Compose. Below are the commands to use:
To stop and delete a container
docker-compose down
To stop and remove volumes:
docker-compose down -v
To start a container
docker-compose up -d
Verdict
That marks the end of this guide on how to use Docker / Podman Compose on Debian 12 (Bookworm). I hope you have learned something from this guide.
Are you interested in more articles?
- Run Teleport in Docker Container using Docker Compose
- Run Guacamole Remote Desktop in Docker using Docker Compose
- Run GitLab in Docker Containers using Docker Compose
- Run Elastic stack (ELK) on Docker Containers with Docker Compose