Use Docker Compose with Podman to Orchestrate Containers on Fedora Linux

Photo by Jonas on Unsplash

Docker Compose is an open-source tool used by developers for orchestrating containers locally or in production. If you are new to containers, I suggest checking out the following links:

Podman, a powerful alternative to Docker CLI, has attracted a lot of developers recently. However, Podman users faced a challenge. Docker Compose was expected to work with Docker daemon only. So, Podman users had to use other alternatives to Docker Compose like using Podman Compose that runs services defined in the Compose file inside a Podman pod. (To learn more about Podman Compose, check out my article Manage Containers on Fedora with Podman Compose on Fedora Magazine.) Another method was manually running different containers of an application and then generating a Kubernetes file with

podman generate
to be later re-run with
podman play
. (To learn more about this method, check out this Moving from docker-compose to Podman pods on Red Hat.)

Podman and Docker Compose

Both of the Docker Compose alternatives mentioned previously have their limitations. At the least they need you to know a little bit more than Container and Docker basics.The good news is that Podman has added support for Docker Compose since version 3.0 so you can now run your traditional docker-compose.yml files with Podman backend. Podman does this by setting up a UNIX socket for

to interact with, similar to the Docker daemon. In this article I will show you how to use Docker Compose both with rootful and rootless Podman.

Required Software

Install the following packages on your system to run Docker Compose with Podman:

  • podman: Tool for managing containers
  • docker-compose: Tool for orchestrating containers
  • podman-docker: Installs a script named docker that emulates docker CLI using Podman. Also links Docker CLI man pages and podman.

Install the above packages using dnf:

sudo dnf install -y podman podman-docker docker-compose

Setting Up Podman Socket

Set up the Podman socket in order for Docker Compose to work:

sudo systemctl enable podman.socket
sudo systemctl start podman.socket
sudo systemctl status podman.socket

This sets up a Unix socket in to communicate with Docker Compose and symlinks it to /var/run/docker.sock. To test if you can communicate with the socket, run the following curl command:

sudo curl -H "Content-Type: application/json" --unix-socket /var/run/docker.sock http://localhost/_ping

If the output from the above command is OK, it means your setup was successful.

Running A Sample Project with Docker Compose

Now, you can start orchestrating your project by going to the project folder and running

sudo docker-compose up
. As an example, I will be using a docker-compose.yml from a sample WordPress project I created as a demo for this article. You can find it Clone the repository on your system and from within the directory, start docker-compose.

sudo docker-compose up

If everything goes well, you will see docker-compose bringing up the services defined in the compose YAML file. Access the new WordPress instance at http://localhost:8080 after the containers are created. To stop the project, you can press Ctrl + C in the terminal where you executed docker-compose up. To remove the containers, execute

sudo docker-compose down

Running Docker Compose with Rootless Podman

The setup shown above uses Podman in root-ful mode. Notice the sudo keyword preceding most of the commands used. Often you will not need to run your projects as root. So, having the option to run docker-compose as a regular user is pretty handy. As of version 3.2.0, Podman supports Docker-Compose with rootless Podman. The setup, however, changes as follows:

systemctl --user enable podman.socket
systemctl --user start podman.socket
systemctl --user status podman.socket
export DOCKER_HOST=unix:///run/user/$UID/podman/podman.sock

Note that when starting the podman socket as non-root user, a user-level socket will be created at /run/user/$UID/podman/podman.sock, where $UID refers is the non-root user’s user ID. We need to set the DOCKER_HOST environment variable to that socket so that Docker Compose can talk to the correct socket. You can add the environment variable to your ~/.bash_profile to make it persistent across system reboots. In root-ful mode, the socket is created in /run/podman/podman.sock which is symlinked to /var/run/docker.sock (the default socket expected by the docker-compose binary). So, we didn’t need to set DOCKER_HOST variable then.

Now, in rootless mode, we can simply run the command

docker-compose up

without “sudo” in the project root folder. This will bring up our WordPress site running on Docker Compose with Podman backend.

WordPress instance running with Docker Compose with Podman backend

Further Reading:

Fedora Project community For Developers Using Software


  1. Chris

    Very useful, thank you

    I think
    export DOCKER_HOST=///run/user/$UID/podman/podman.sock
    Should be
    export DOCKER_HOST=Unix:///run/user/$UID/podman/podman.sock

    • You are right Chris. Thank you for the fix.
      So, the correct value for DOCKER_HOST will be:

  2. Osqui

    Many ways of doing the same. I’ll stick with podman generate/play, which is easy, “native” and lets you go further. Thanks, anyway

    • hammerhead corvette

      Good idea !

    • I didn’t have much success with podman generate and podman play last time I tried. There were some bugs and missing features I guess, e.g. with volume support. After all, the way Podman Play works is different from Docker Compose, but the result should be the same 🙂

    • One more thing, Docker Compose (and Podman Compose that works similarly) is easier to work with. For Podman Play, one has to run containers first and then run Podman Generate to export the container and pod specs to file.

  3. systemctl enable podman.socket && systemctl start podman.socket

    can be replaced by

    systemctl enable --now podman.socket
  4. zer0err0r

    This is useful, Thank you .
    But why dont you use podman-compose instead of using docker-compose .
    I mean this project :

    • Sure, but I think Docker Compose deals with containers defined in docker-compose.yml differently from how Podman Compose does. The former has a concept of service for each container name, while the latter presumably creates requested number of containers and adds them to a pod.

  5. Why it doesn’t work as should? What kind of sourcery did you use to make it work?

    ❯ docker-compose up
    Starting docker-aws_db_1 ... done
    Starting docker-aws_wp_1 ... done
    Attaching to docker-aws_db_1, docker-aws_wp_1
    db_1  | 2021-07-15 10:11:43+00:00 [Note] [Entrypoint]: Entrypoint script for MariaDB Server 1:10.6.3+maria~focal started.
    db_1  | 2021-07-15 10:11:43+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
    db_1  | 2021-07-15 10:11:43+00:00 [Note] [Entrypoint]: Entrypoint script for MariaDB Server 1:10.6.3+maria~focal started.
    db_1  | 2021-07-15 10:11:44 0 [Note] mysqld (mysqld 10.6.3-MariaDB-1:10.6.3+maria~focal) starting as process 1 ...
    db_1  | 2021-07-15 10:11:44 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
    db_1  | 2021-07-15 10:11:44 0 [Note] InnoDB: Number of pools: 1
    db_1  | 2021-07-15 10:11:44 0 [Note] InnoDB: Using crc32 + pclmulqdq instructions
    db_1  | 2021-07-15 10:11:44 0 [Note] mysqld: O_TMPFILE is not supported on /tmp (disabling future attempts)
    db_1  | 2021-07-15 10:11:44 0 [Note] InnoDB: Using Linux native AIO
    db_1  | 2021-07-15 10:11:44 0 [Note] InnoDB: Initializing buffer pool, total size = 134217728, chunk size = 134217728
    db_1  | 2021-07-15 10:11:44 0 [Note] InnoDB: Completed initialization of buffer pool
    db_1  | 2021-07-15 10:11:44 0 [Note] InnoDB: 128 rollback segments are active.
    db_1  | 2021-07-15 10:11:44 0 [Note] InnoDB: Creating shared tablespace for temporary tables
    db_1  | 2021-07-15 10:11:44 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
    db_1  | 2021-07-15 10:11:44 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
    db_1  | 2021-07-15 10:11:44 0 [Note] InnoDB: 10.6.3 started; log sequence number 42185; transaction id 14
    db_1  | 2021-07-15 10:11:44 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
    db_1  | 2021-07-15 10:11:44 0 [Note] Plugin 'FEEDBACK' is disabled.
    db_1  | 2021-07-15 10:11:44 0 [Note] InnoDB: Buffer pool(s) load completed at 210715 10:11:44
    db_1  | 2021-07-15 10:11:44 0 [Warning] You need to use --log-bin to make --expire-logs-days or --binlog-expire-logs-seconds work.
    db_1  | 2021-07-15 10:11:44 0 [Note] Server socket created on IP: ''.
    db_1  | 2021-07-15 10:11:44 0 [Note] Server socket created on IP: '::'.
    db_1  | 2021-07-15 10:11:44 0 [Warning] 'proxies_priv' entry '@% root@81c6df981a94' ignored in --skip-name-resolve mode.
    db_1  | 2021-07-15 10:11:44 0 [Note] mysqld: ready for connections.
    db_1  | Version: '10.6.3-MariaDB-1:10.6.3+maria~focal'  socket: '/run/mysqld/mysqld.sock'  port: 3306 binary distribution
    wp_1  | AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using Set the 'ServerName' directive globally to suppress this message
    wp_1  | AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using Set the 'ServerName' directive globally to suppress this message
    wp_1  | [Thu Jul 15 10:11:44.629174 2021] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.38 (Debian) PHP/7.4.21 configured -- resuming normal operations
    wp_1  | [Thu Jul 15 10:11:44.629231 2021] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'
  6. Algernon Carruthers

    How could we enable this for a Silverblue installation? F34 Silverblue is great distro but would love something like this to ease local development on it.

  7. Erik Sjölund

    I was experimenting a bit with running containerized docker-compose with podman some time ago:

    podman \
    run \
    –rm \
    –detach \
    –env DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock \
    –security-opt label=disable \
    –volume $XDG_RUNTIME_DIR/podman/podman.sock:$XDG_RUNTIME_DIR/podman/podman.sock \
    –volume $(pwd):$(pwd) \
    –workdir $(pwd) \ \
    –verbose \
    up -d

    If I remember correctly, it worked when I tried it out:

Comments are Closed

The opinions expressed on this website are those of each author, not of the author's employer or of Red Hat. Fedora Magazine aspires to publish all content under a Creative Commons license but may not be able to do so in all cases. You are responsible for ensuring that you have the necessary permission to reuse any work on this site. The Fedora logo is a trademark of Red Hat, Inc. Terms and Conditions