Fedora Silverblue: Ambiente PHP com Podman - Primeira tentativa

leandroramos
editado abril 2020 em SilverBlue

O Podman é um mecanismo de contêiner completo e sem daemon para executar, gerenciar e depurar containers e pods compatíveis com OCI. Ele permite gerenciar containers sem a dependência do daemon e é compatível com a interface da linha de comandos do docker (CLI). O Podman também fornece uma integração aprimorada com o systemd. Com o Podman, você pode facilmente encontrar, criar, executar e compartilhar container. Mudar do Docker para o Podman é fácil e intuitivo.

O parágrafo acima foi copiado do excelente tutorial do @Danniel, por favor, leiam aqui.

Podman e Docker

O Podman é muito parecido com o Docker, e podemos criar contêineres no Podman para usarmos com o Docker e vice-versa. De fato, um dos lugares onde o Podman busca por contêineres é no docker.io. Os comandos utilizados no Podman também são praticamente os mesmos usados no Docker.

Registries

Os registries são lugares onde o podman busca por contêineres, e eles podem ser vistos no arquivo /etc/containers/registries.conf, ou com o comando podman info. Use o arquivo de configurações se quiser adicionar ou remover algum registry. Se for apenas para consultar, use o comando podman info:

Na imagem acima, destaquei um trecho da saída do podman info, onde aparecem os registries:

registries:
  search:
  - registry.fedoraproject.org
  - registry.access.redhat.com
  - registry.centos.org
  - docker.io

Buscando por contêineres com o Podman

Vou usar um contêiner simples para introduzir o assunto e depois ir evoluindo para o uso de vários contêineres, em outros artigos. Ainda não temos um "modelo" de ambiente para desenvolvimento no Fedora Silverblue, e os usuários estão testando soluções diferentes para isso, aguns usando scripts para simulares um docker-compose, outros usando kubernetes. Como estou aprendendo a lidar com isso, vou apostar no uso de kubernetes nos próximos artigos.

Para buscar por contêineres nos registries cadastrados:

podman search lamp

Na imagem acima apareceram vários contêineres, e no caso do LAMP estão todos no docker.io. Vou escolher o que tem mais estrelas (classificação mais alta) e vou ver informações sobre ele. Para ver informações sobre um contêiner, vou usar o programa skopeo:

skopeo inspect docker://docker.io/mattrayner/lamp
# Reparem no prefixo docker:// antes do endereço/usuário/contêiner

Vejamos a saída do comando acima (eu cortei a maioria das linhas em RepoTags e Layers para deixar o texto menor):

{
    "Name": "docker.io/mattrayner/lamp",
    "Digest": "sha256:a0386b0ff145459635cd9b0fbbc1b41a3371a9b6d63ef1682842e395a98bb483",
    "RepoTags": [
        "0.1.0",
        "build-153",
        "build-167-1604-php7",
        "dev",
        "latest"
    ],
    "Created": "2020-03-15T16:16:52.681486212Z",
    "DockerVersion": "17.09.0-ce",
    "Labels": null,
    "Architecture": "amd64",
    "Os": "linux",
    "Layers": [
        "sha256:c64513b741452f95d8a147b69c30f403f6289542dd7b2b51dd8ba0cb35d0e08b",
        "sha256:01b8b12bad90b51d9f15dd4b63103ea6221b339ac3b3e75807c963e678f28624",
        "sha256:c5d85cf7a05fec99bb829db84dc5a21cc0aca569253f45d1ea10ca9e8a03fa9a",
        "sha256:5bbaab6061283824dd5472a6d038455585893ea6b638a313742ffa5338bba83c"
    ],
    "Env": [
        "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
        "DEBIAN_FRONTEND=noninteractive",
        "LANG=en_US.UTF-8",
        "LANGUAGE=en_US:en",
        "LC_ALL=en_US.UTF-8",
        "REFRESHED_AT=2019-06-11",
        "DOCKER_USER_ID=501",
        "DOCKER_USER_GID=20",
        "BOOT2DOCKER_ID=1000",
        "BOOT2DOCKER_GID=50",
        "PHPMYADMIN_VERSION=5.0.1",
        "MYSQL_PASS:-$(pwgen=-s 12 1)",
        "PHP_UPLOAD_MAX_FILESIZE=10M",
        "PHP_POST_MAX_SIZE=10M",
        "PHP_VERSION=7.4"
    ]
}

Ao ver o Dockerfile do contêiner eu vi que ele vem com o ambiente que preciso. Infelizmente vem com MySQL e não com MariaDB, mas vou construir outros contêineres no futuro. Vi que ele também vem com o Composer.

Baixando o contêiner

podman pull docker.io/mattrayner/lamp

Rodando o contêiner

Para executar o contêiner em segundo plano, redirecionando a porta 8080 da máquina para a porta 80 do contêiner:

podman run -d -p 8080:80 lamp

Para ver os contêineres em execução:

podman ps

Para ver as imagens disponíveis:

podman images

Entrando no shell do contêiner

Podemos entrar no shell do contêiner (bash):

podman run -ti lamp /bin/bash

No comando acima:

  • O parâmetro -t ou --tty aloca um pseudo-TTY para o contêiner.
  • O Parâmetro -i ou --interactive abre a entrada padrão STDIN do contêiner para receber comandos
  • lamp é o nome que dei ao contêiner no comando podman run feito acima.
  • /bin/bash é o comando que quero executar no contêiner, ou seja, o shell bash para poder digitar comandos.

Vendo informações sobre o contêiner:

cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.4 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.4 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

Como estamos em um contêiner, o kernel usado é o mesmo da máquina host, ou seja, estamos num contêiner de Ubuntu, mas usando o kernel do Fedora:

uname -r

Se quiserem uma introdução sobre contêineres, vejam o curso Descomplicando o Docker, do Jefferson Fernando - LINUXtips.

Vendo o resultado no navegador

Ao acessar o navegador em http://localhost:8080, temos o servidor web rodando:

Podemos ver o phpMyAdmin rodando em http://localhost:8080/phpmyadmin

Criando usuário no MySQL

Antes de fazer o login no phpMyAdmin, vou criar um usuário no MySQL, pois o root, sem senha, não pode fazer login pela interface web. O contêiner possui um id que pode variar, no meu caso é flamboyant_ganguly, como podemos ver no resultado do comando podman ps. Esse ID será necessário no próximo comando.

Saída do podman ps:

CONTAINER ID  IMAGE                             COMMAND  CREATED         STATUS             PORTS                 NAMES
fc1f2f94b310  docker.io/mattrayner/lamp:latest  /run.sh  46 minutes ago  Up 46 minutes ago  0.0.0.0:8080->80/tcp  flamboyant_ganguly

Criando o usuário leandro com acesso total no MySQL:

podman exec flamboyant_ganguly \
mysql -u root -e \
"GRANT ALL PRIVILEGES ON \
*.* TO 'leandro'@'%' \
IDENTIFIED BY 'senhadanasa';"

Vejam o login do usuário leandro no phpMyAdmin:

Configurando a persistência de dados

Vou reexecutar o contêiner informando volumes (lembrem-se do curso do LINUXtips se quiserem saber o que é isso) para o armazenamento do app e do banco de dados, bem como adicionando a porta do MySQL para usar programas externos ao contêiner. Mas antes disso eu preciso levar o arquivo de configuração do storage para a Home do meu usuário - para não ter problemas ao montar os volumes.

cp /etc/containers/storage.conf ~/.config/containers/storage.conf

Vou alterar as seguintes configurações no arquivo ~/.config/containers/storage.conf:

driver = "overlay"

runroot = "/run/user/1000"

graphroot = "/home/leo/.local/share/containers/storage" #Aqui é necessário colocar o caminho absoluto

mount_program = "/usr/bin/fuse-overlayfs"

Parando e reiniciando o contêiner

Vou parar e executar novamente o contêiner:

podman stop flamboyant_ganguly

Vou criar dois diretórios dentro do meu diretório de trabalho:
mkdir app
mkdir mysl

Vou iniciar o contêiner com o parâmetro --privileged para ter permissões de escrita nos diretórios do contêiner:

podman run --privileged -d \
-p 8080:80 \
-p 3306:3306 \
-v ${PWD}/app:/app \
-v ${PWD}/mysql:/var/lib/mysql \
lamp

No comando acima, o parâmetro -v mapeia as pastas app e mysql para as pastar correspondentes no contêiner.

Verificando as portas:

ss -ntpl

Recriando o usuário no MySQL

Preciso recriar o usuário no MySQL, pois o que foi criado anteriormente não está mais no contêiner, pois não havia persistência dos dados. Reparem que o contêiner mudou de nome, agora é peaceful_satoshi.

podman exec peaceful_satoshi mysql -u root -e "GRANT ALL PRIVILEGES ON *.* TO 'leandro'@'%' IDENTIFIED BY 'senhadanasa';"

Usando cliente externo para o acesso ao MySQL

Agora, com o usuário criado e a porta 3306 aberta, posso fazer login em clientes MySQL de fora do contêiner:

Verificando a persistência

Vou parar e iniciar novamente o contêiner

podman stop peaceful_satoshi
podman run --privileged -d \
-p 8080:80 \
-p 3306:3306 \
-v ${PWD}/app:/app \
-v ${PWD}/mysql:/var/lib/mysql \
lamp

Ao iniciar o contêiner, o usuário leandro continua com acesso ao servidor de banco de dados

Verificando a persistência dos arquivos

Vou criar um projeto Laravel no contêiner

podman exec nome-do-conteiner composer create-project laravel/laravel /app/blog

Arquivos criados no contêiner

Reiniciando o contêiner

podman stop nome-do-conteiner
podman run --privileged -d \
-p 8080:80 \
-p 3306:3306 \
-v ${PWD}/app:/app \
-v ${PWD}/mysql:/var/lib/mysql \
lamp

Ao reiniciar o contêiner, a aplicação continua gravada no disco:

E os arquivos estão gravados na pasta app do host:

Considerações finais

Coisas que preciso fazer para melhorar o procedimento:

  • Criar aliases para os comandos longos
  • Corrigir as permissões das pastas no host para não precisar de sudo para acessá-las
  • Nomear os contêineres para não usar contêineres com nomes diferentes a cada reinício
  • Melhorar o virtualhost no Apache para não precisar digitar o /public no final da URL

Mas, por enquanto, foi suficiente para mostrar um pouco do uso do podman como solução para o trablaho com contêineres para desenvolvimento.

Abraços, pessoal.

Comentários

  • Muito bom , meus parabéns .
    próximo passo é fazer um podman-compose pra subir tudo

  • Obrigado, @Danniel. Eu vou fazer um pouco diferente. Vou usar a toolbox para o PHP e NodeJS, e um contêiner para o MariaDB no Podman. Acho que vai ficar mais simples para eu entender como as coisas funcionam, e depois eu uso o podman-compose para outros serviços. Estou escrevendo a segunda tentativa agora rsrs.

  • @leandroramos Muito bom, Gostei me ajudou muito. Parabéns tive um pouco de dificuldades mais no final foi sucesso.