Como usar o docker-compose com Podman no Linux
Podman é uma alternativa gratuita e de código aberto ao Docker, criada pela Red Hat. Embora o Docker seja provavelmente mais difundido, a ponto de se tornar sinônimo de “containers”, do ponto de vista técnico, o Podman é superior: foi projetado, desde o início, para ser daemonless, é capaz de rodar sem a necessidade de privilégios de root e está melhor integrado no ambiente Linux. Uma das coisas que potencialmente impediu muitos de migrar do Docker para o Podman foi a falta de um equivalente completo do Podman para o docker-compose. Ao criar uma camada de compatibilidade entre Podman e Docker, agora é realmente possível usar o docker-compose como se fosse uma ferramenta nativa do Podman.
Neste tutorial, vemos como instalar o docker-compose nas distribuições Linux mais usadas e como usá-lo com o Podman em vez do Docker.
Neste tutorial você aprenderá:
- Como instalar podman, podman-docker e docker-compose nas distribuições Linux mais utilizadas
- Como configurar o Podman para funcionar com docker-compose
- Como usar o docker-compose com Podman
Instalando pacotes
A primeira coisa que precisamos fazer para usar o docker-compose com o Podman é instalar o pacote podman-docker. Este pacote fornece uma camada de compatibilidade entre Docker e Podman, emulando o Docker CLI, mas executando comandos Podman, nos bastidores.
Para realizar a instalação no Fedora e outras distribuições da família Red Hat, podemos executar:
$ sudo dnf install podman podman-docker
Para instalar o pacote em distribuições Debian e baseadas em Debian, podemos executar:
$ sudo apt install podman podman-docker
Instalando o docker-compose
Agora temos que instalar o docker-compose. Atualmente existem duas versões do docker-compose: a primeira, “v1”, é a versão original e agora obsoleta escrita em Python, que recebe apenas correções de segurança. O segundo, “v2” é escrito em Go, é desenvolvido ativamente e é empacotado como um plugin Docker nos repositórios oficiais do Docker.
Instalando o docker-compose v1
A maioria das distribuições Linux inclui um pacote “docker-compose” que fornece a versão Python da ferramenta. Para instalá-lo no Fedora, executamos:
$ sudo dnf install docker-compose
No RHEL e nos clones, o pacote docker-compose não está disponível imediatamente, nem pode ser instalado (pelo menos no momento da escrita) a partir do repositório EPEL. Nessas distribuições, temos que instalar o docker-compose v1 como um pacote Python com pip, o gerenciador de pacotes python.
Como não queremos executar o pip como root, instalamos o pacote em seu próprio ambiente virtual dedicado, como um usuário padrão e sem privilégios, e então criamos um link simbólico para o executável (alternativamente podemos use uma ferramenta como pipx). No exemplo abaixo, presumo que o diretório ~/.local/bin
exista e esteja em nosso PATH:
$ python3 -m venv virtualenv
$ virtualenv/bin/pip install docker-compose
$ ln -s "${PWD}/virtualenv/bin/docker-compose" ~/.local/bin/docker-compose
Para instalar o docker-compose v1 em distribuições Debian e baseadas em Debian, podemos executar:
$ sudo apt install docker-compose
Instalando o docker-compose v2
Como já dissemos, a versão oficial suportada e desenvolvida ativamente do docker-compose é a v2. Uma maneira universal e de distribuição cruzada de instalá-lo é baixando o binário pré-compilado para a arquitetura do nosso sistema, diretamente do repositório GitHub do projeto. No exemplo abaixo, baixamos a versão Linux x86_64 da versão mais recente (2.27 no momento da escrita):
$ curl -LO https://github.com/docker/compose/releases/download/v2.27.0/docker-compose-linux-x86_64
Depois de baixar o binário, nós o tornamos executável e depois o movemos para um diretório em nosso PATH. Para instalá-lo apenas para nosso usuário, podemos movê-lo para ~/.local/bin
, para instalá-lo em todo o sistema, em vez disso, podemos movê-lo para /usr/local/bin
:
$ chmod +x docker-compose-linux-x86_64
$ sudo mv docker-compose-linux-x86_64 /usr/local/bin/docker-compose
Uma forma alternativa de instalar o docker-compose v2 é a partir do repositório oficial do Docker. Primeiro adicionamos o repositório à nossa distribuição, seguindo o guia oficial, depois instalamos o pacote “docker-compose-plugin”:
$ sudo dnf install docker-compose-plugin
Ao executar o comando acima, instalamos o docker-compose como um plugin Docker em vez de um binário independente: para usá-lo como tal, basta criar um link simbólico em um diretório em nosso PATH:
$ sudo ln -s /usr/libexec/docker/cli-plugins/docker-compose /usr/local/bin/docker-compose
Habilitando e iniciando o soquete Podman
Uma das principais diferenças entre Podman e Docker é o design. O Docker usa uma arquitetura cliente-servidor: o daemon do Docker é executado em segundo plano, normalmente com privilégios de root (embora versões recentes do Docker suportem a execução de uma versão do daemon em nível de usuário sem root), enquanto o Podman usa o chamado “fork-exec ”arquitetura (cada contêiner é executado como um processo filho do Podman). Como o docker-compose foi projetado para funcionar com o Docker, ele espera que o daemon do docker esteja em execução. Por esse motivo, Podman fornece a unidade systemd “podman.socket”. Para usar o docker-compose com o Podman é necessário iniciá-lo e habilitá-lo:
$ sudo systemctl enable --now podman.socket
Se quisermos usar docker-compose com uma instância do Podman sem root, precisamos habilitar e iniciar uma instância do soquete em nível de usuário:
$ systemctl --user enable --now podman.socket
Neste último caso, também precisamos definir e exportar a variável de ambiente DOCKER_HOST
. A maneira tradicional de fazer isso é adicionando a linha abaixo em ~/.bash_profile
ou ~/.profile
, dependendo do shell que estamos usando:
export DOCKER_HOST=unix:///run/user/1000/docker.sock
Para que as alterações tenham efeito imediato em nossa instância de shell atual, sem esperar pelo próximo login, podemos obter o arquivo diretamente:
$ source ~/.bash_profile
Soquete Systemd vs. serviço
Além da unidade de soquete que ativamos na etapa anterior (/usr/lib/systemd/system/podman.socket
), o pacote Podman vem com uma unidade de “serviço” do systemd (/usr/ lib/systemd/system/podman.service
); o que esse serviço realmente realiza e por que usamos a unidade de soquete e não o serviço diretamente?
Para ver o comando que o Systemd executa ao iniciar o serviço Podman, basta dar uma olhada na própria unidade. O que nos interessa, neste caso, é o valor da opção “ExecStart”, na secção “Serviço”:
ExecStart=/usr/bin/podman $LOGGING system service
Podemos ver que quando o serviço é iniciado, o Systemd executa o comando podman system service
. O que este comando faz é criar um serviço de escuta que responde a chamadas de API para Podman. Dessa forma, embora o Podman não precise de um daemon para funcionar, o Podman pode “imitar” a interface do Docker.
Por que habilitamos e iniciamos a unidade de soquete, em vez do serviço diretamente? Fazendo isso, aproveitamos um recurso do Systemd: serviços ativados por soquete. O soquete escuta conexões e inicia o serviço mediante solicitação, utilizando os recursos da maneira mais eficiente.
Usando docker-compose
Depois que tudo estiver pronto, podemos usar o docker-compose como se estivéssemos executando o Docker nos bastidores. O exemplo abaixo é um exemplo básico de um arquivo composto. Ele gera um contêiner para um servidor MariaDB e outro para phpMyAdmin:
version: '3.7'
services:
mariadb:
image: docker.io/mariadb
volumes:
- db:/var/lib/mysql
environment:
TZ: "Europe/Rome"
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_USER: testuser
MYSQL_PASSWORD: testpassword
MYSQL_DATABASE: testdb
phpmyadmin:
image: docker.io/phpmyadmin
environment:
PMA_HOST: mariadb
ports:
- "80:80"
depends_on:
- mariadb
volumes:
db:
Para criar os containers, os volumes e uma rede dedicada para a pilha, executamos:
$ sudo docker-compose up
Conclusões
Neste tutorial aprendemos como configurar o Podman para funcionar com docker-compose. Docker-compose foi projetado para funcionar com Docker, que, diferentemente do Podman, usa uma arquitetura cliente-servidor. Ao habilitar o soquete Podman e instalar o pacote podman-docker, basicamente criamos uma camada de compatibilidade que nos permite usar o docker-compose com o Podman de forma transparente.