Beginner's Guide to Using Podman Compose
If you have looked for alternatives to Docker, Podman might have attracted your attention.
One thing that Podman does not yet have is the ability to automatically pull appropriate images and start the containers based on a compose file.
There exists a tool called podman-compose
that is an alternative to docker-compose
tool and it works with Podman, as you would expect. So let us see how to use this tool.
What is podman-compose?
Docker provides the functionality to specify all the necessary details like the container name, image used, restart policy, volumes, bind mounts, ports, labels, etc inside a single file. This file is usually called the docker-compose.yml
file.
This functionality is missing from Podman. Hence we need to use the podman-compose
tool to achieve this functionality.
The podman-compose tool does this by adhering to the Compose specification. This is the same specification that Docker adheres to, making it compatible with an existing docker-compose.yml
file. (There may be some pedantic differences like enclosing values between double quotes ("
), etc but those can be easily solved by looking at the errors.)
Installing the podman-compose tool
Since the podman-compose tool is a relatively new tool, your stable/LTS Linux distribition might not have it in the first party repositories. But nonetheless, let us see what your options are and how to install it.
On Ubuntu 22.10 (Kinetic Kudu) and later and Debian 12 (Bookworm) and later, you can install it using the apt
package manager like so:
sudo apt install podman-compose
Users of Fedora 36 and later (the package version on Fedora 35 is 0.1.7-6.git
) can use the dnf
package manager to install podman-compose like so:
sudo dnf install podman-compose
OpenSUSE Tumbleweed or Leap 15 and later can install the podman-compose tool like so:
sudo zypper install podman-compose
If you are a proud Arch Linux user, you do not need my help. But below is the installation command nonetheless ;)
sudo pacman -Syu podman-compose
Verify the installation
To ensure that the podman-compose utility is either installed or its path is included in the PATH
environment variable, you can check it like so:
podman-compose --version
This should also list your Podman version.
On my Fedora 36 machine, I get the following output:
$ 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
Basics of the podman-compose tool
For the sake of keeping this tutorial short, sweet and digestable, I will not cover the structure of a compose file. But fret not! We already have a quick guide to using docker-compose
.
For the sake of convenience, below is the compose file that I am using:
version: 3.7
services:
reverse-proxy:
image: docker.io/library/caddy:alpine
container_name: caddy-vishwambhar
command: caddy run --config /etc/caddy/Caddyfile
restart: always
ports:
- "8080:80"
- "8443:443"
volumes:
- /docker-volumes/caddy/Caddyfile:/etc/caddy/Caddyfile:Z
- /docker-volumes/caddy/site:/srv:Z
- /docker-volumes/caddy/caddy_data:/data:Z
- /docker-volumes/caddy/caddy_config:/config:Z
- /docker-volumes/caddy/ssl:/etc/ssl:Z
labels:
- io.containers.autoupdate=registry
- pratham.container.category=proxy
environment:
- TZ=Asia/Kolkata
depends_on:
- gitea-web
gitea-web:
image: docker.io/gitea/gitea:latest
container_name: gitea-govinda
restart: always
ports:
- "8010:3000"
- "8011:22"
volumes:
- /docker-volumes/gitea/web:/data:Z
- /docker-volumes/gitea/ssh:/data/git/.ssh:Z
- /etc/localtime:/etc/localtime:ro
labels:
- io.containers.autoupdate=registry
- pratham.container.category=gitea
environment:
- RUN_MODE=prod
- DISABLE_SSH=false
- START_SSH_SERVER=true
- SSH_PORT=22
- SSH_LISTEN_PORT=22
- ROOT_URL=https://git.mydomain.com
- DOMAIN=git.mydomain.com
- SSH_DOMAIN=git.mydomain.com
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=gitea-db:5432
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=/run/secrets/gitea_database_user_password
- GITEA__service__DISABLE_REGISTRATION=true
- TZ=Asia/Kolkata
depends_on:
- gitea-db
secrets:
- gitea_database_user_password
gitea-db:
image: docker.io/library/postgres:14-alpine
container_name: gitea-chitragupta
restart: always
volumes:
- /docker-volumes/gitea/database:/var/lib/postgresql/data:Z
labels:
- io.containers.autoupdate=registry
- pratham.container.category=gitea
environment:
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=/run/secrets/gitea_database_user_password
- POSTGRES_DB=gitea
- TZ=Asia/Kolkata
secrets:
- gitea_database_user_password
secrets:
gitea_database_user_password:
external: true
Let us now start with the basic commands.
Starting all containers from the compose file
Using the up
command, we can create and start the services described in our compose file (docker-compose.yml
).
You can simply use the up
command and start all the specified containers/services that are listed in the compose file like so:
podman-compose up -d
Running the above command will perform all the necessary actions needed to start the services/containers listed in the compose file. That includes steps like the folloiwng:
- Pull all the images that are not available locally
- Create the containers with all the specified options (ports, volumes, secrets, networks, etc)
- Start the containers in a specific order (defined by constraints like
depends_on
)
If you looked closely at the above example, you might have noticed a new option; the -d
option. This option starts the container in the background, detaching it from the current shell.
Once the containers are up and running, you can verify that by running the podman ps
command:
$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d7b7f91c03aa docker.io/library/caddy:alpine caddy run --confi... 4 hours ago Up 4 hours ago 0.0.0.0:8080->80/tcp, 0.0.0.0:8443->443/tcp caddy-vishwambhar
1cfcc6efc0d0 docker.io/library/postgres:14-alpine postgres 4 hours ago Up 4 hours ago gitea-chitragupta
531be3df06d0 docker.io/gitea/gitea:latest /bin/s6-svscan /e... 4 hours ago Up 4 hours ago 0.0.0.0:8010->3000/tcp, 0.0.0.0:8011->22/tcp gitea-govinda
Stop all containers from the compose file
To stop all the containers specified in the compose file, use the down
command.
podman-compose down
Additionally, you can give a timeout so the containers can shut themselves down safely. This is done using either of the following options:
podman-compose down -t TIMEOUT_IN_SECONDS
podman-compose down --timeout TIMEOUT_IN_SECONDS
Please note that the down
command only stops the container(s). If you want to delete containers, that will need to be done manually.
Start, stop or specific services
If you are iterating through multiple configurations like ports, volumes, environment variables, etc, you might be using the podman-compose up
and the podman-compose down
command repeatedly.
This will start and stop all services, respectively. Meaning, if you only have one service to start/stop, you now have to wait for all the services listed in a compose file to start and shut down. That's no good!
To solve this, we can use the start
and stop
commands to start or stop individual services. There is even a restart
command. This does exactly what it says :)
Below is a demonstration where I start the gitea-db
service, stop it and then restart it, just for you ;)
$ podman-compose start gitea-db
$ podman-compose stop gitea-db
$ podman-compose restart gitea-db
Pull all necessary images at once
Let's say that you specified 10 different services in your compose file. What if waiting once is okay to you, but not when you want to start the contiainers--for whatever reason?
If that is the case, all you have to do is use the pull
command like so:
podman-compose pull
Running the above command will pull all the images that are specified in the compose file.
Use a different name for your compose file
Now, I do not know why you might do this. There are several reasons for you to do this. Maybe keeping the compose file's name as docker-compose.yml
triggers you to type docker
instead of podman
.
Whatever the reason might be, you can use either of the following flags to specify the name of the comopse file, like so:
podman-compose -f COMPOSE_FILE_NAME
podman-compose --file COMPOSE_FILE_NAME
Let's assume my compose file is not named docker-compose.yml
, but is instead named my-compose-file.yml
. To use this compose file, I will run the following command:
podman-compose --file my-compose-file.yml
Running the above command will inform the podman-compose
tool that the compose file is named my-compose-file.yml
instead of docker-compose.yml
.
Conclusion
Podman is an amaizng container orchestration tool; and along with the podman-compose
tool, creating multiple containers with your specified details become easier! I recommend that you try out the podman-compose
tool and let us know about your experience.