> ## Content Index
> Fetch the complete content index at: https://linuxhandbook.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Beginner's Guide to Using Podman Compose
- URL: https://linuxhandbook.com/courses/podman/podman-compose/
- Published: 2023-01-20T06:09:10.000Z
- Updated: 2025-08-22T07:44:15.000Z
- Description: Podman also has a compose tool that allows you to work with Docker compose like files. Here's all you need to know about it.
- Author: Pratham Patel
- Tags: Podman, #lessons-col, #lesson-duration-45m

If you have looked for [alternatives to Docker](https://linuxhandbook.com/docker-alternatives/), 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](https://github.com/compose-spec/compose-spec/blob/master/spec.md?ref=linuxhandbook.com). 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:

```bash
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:

```bash
sudo dnf install podman-compose
```

OpenSUSE Tumbleweed or **Leap 15** **and later** can install the podman-compose tool like so:

```bash
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 ;)

```bash
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:

```bash
podman-compose --version
```

This should also list your Podman version.

On my Fedora 36 machine, I get the following output:

```bash
$ 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
```

[Get a $10 credit for Fathom, a privacy-focused website analytics companySomeone has shared a link with you that gives you $10 credit upon sign-up.![](https://usefathom.com/assets/images/favicon.svg)Fathom Analytics![](https://usefathom.com/assets/images/pages/social-aff-10bucks.png)](https://usefathom.com/ref/NFMWEH?ref=linuxhandbook.com)

## 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](https://linuxhandbook.com/docker-compose-quick-start/).

For the sake of convenience, below is the compose file that I am using:

```yaml
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:

```bash
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:

```bash
$ 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.

```bash
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:

```bash
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 ;)

```bash
$ 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:

```bash
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:

```bash
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:

```bash
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.