Docker é uma ferramenta que permite a distribuição de softwares em contêineres, ambientes de execução independentes. Algo como máquinas virtuais, mas sem o mesmo overhead da virtualização de hardware e sem necessidade de outro kernel sendo executado.
Isso permite que os desenvolvedores tenham um maior controle sobre versões de dependências como bibliotecas e outros programas com que o software interage, independente da distribuição Linux onde o software vai ser executado.
Isso também facilita a implantação, já que muita coisa no ambiente não precisará ser configurada após a instalação.
Portainer é uma ferramenta para gerenciamento e monitoramento de contêineres Docker, podendo também gerenciar Podman e Kubernetes. É distribuído também como um contêiner Docker.
Começando pela instalação do Docker pelas fontes oficiais, nesse caso para o Ubuntu Server 24.04, é necessário primeiro importar a chave do repositório do Docker:
# curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
Adicione o repositório Docker em um arquivo /etc/apt/sources.list.d/docker.list:
deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu noble stable
Atualize os repositórios e instale os pacotes do Docker:
# apt update
# apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Verifique que o serviço está sendo executado:
$ systemctl status docker.service
Adicione seu usuário ao grupo docker para que não seja necessário usar os comandos com sudo.
# usermod -aG docker daniel
Você talvez precise sair do shell atual e abrir outro, ou fazer logout e login novamente.
Então, crie um volume a ser usado para informações do Portainer:
$ docker volume create portainer_data
Isso cria uma pasta em /var/lib/docker/volumes/portainer_data.
E em seguida, baixe a imagem e execute o Portainer com:
$ docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:lts
- O parâmetro -p é usado para mapear uma porta do host para uma porta do contêiner – docker usa iptables e isso pode contornar o firewall do sistema operacional.
- O parâmetro -v é usado para mapear um volume docker ou um /caminho/no/seu/sistema para um caminho dentro do contêiner.
A porta 9443 é usada para acesso à interface web via HTTPS. Por padrão são gerados certificados autoassinados e, enquanto é possível especificar seus certificados já no comando “docker run”, também é possível alterá-los pelas configurações na própria interface web.
A porta 8000 é usada pela funcionalidade Edge computing, que permite gerenciamento e implantação de contêineres em dispositivos remotos através de um túnel TCP.
Verifique que o Portainer está sendo executado com:
$ docker ps
Então, acesse-o pelo navegador através da porta 9443 com protocolo HTTPS e siga a configuração pela página web.
Hora de instalar um contêiner: existem alguns templates mas a seção Containers permite que qualquer imagem seja baixada do Docker Hub e o contêiner construído a partir dela, com os parâmetros de configuração escolhidos.

Um software interessante que é distribuído como um contêiner docker é o Metabase: uma plataforma livre e aberta para análise de dados e Business Intelligence.
De acordo com o site oficial, a instalação como contêiner docker pode ser feita pelo seguinte comando:
$ docker run -d -p 3000:3000 --name metabase metabase/metabase
O que, pelo Portainer, fica:

Após inicializado, basta acessar o servidor na porta 3000 via HTTP.
O comando “docker run” é tipicamente usado para softwares ou sistemas que são distribuídos como um único contêiner. Alguns sistemas são compostos de múltiplos contêineres que trabalham em conjunto.
Nesses casos, em vez de usar o comando “docker run” passando os parâmetros de configuração como argumentos, o comando “docker compose” é usado com um arquivo docker-compose.yml que armazena esses parâmetros de configuração. A configuração do Metabase nesse formato, por exemplo, ficaria:
services:
metabase:
image: metabase
container_name: metabase
ports:
- "3000:3000"
Outro sistema interessante de ser instalado é o GLPI: um sistema de gerenciamento de Helpdesk e ativos de TI. A instalação usa um arquivo docker-compose.yml, que pode ser encontrado no Docker Hub: https://hub.docker.com/r/glpi/glpi, e especifica dois contêineres: um com o GLPI empacotado com o servidor web e PHP e outro com o banco de dados MySQL. O exemplo abaixo teve alguns parâmetros adaptados:
volumes:
glpi:
glpi_mysql:
services:
glpi:
image: "glpi/glpi:latest"
restart: "unless-stopped"
volumes:
- glpi:/var/glpi
env_file: stack.env
ports:
- "8080:80"
db:
image: "mysql"
restart: "unless-stopped"
volumes:
- glpi_mysql:/var/lib/mysql
env_file: stack.env
expose:
- "3306"
Como a configuração especifica um arquivo com variáveis de ambiente, também precisamos dele, o stack.env, com o conteúdo abaixo.
O Portainer espera que o arquivo seja especificado com esse nome no yml, porque é o nome do arquivo que ele forma a partir das variáveis que são fornecidas. O arquivo para upload pode ter qualquer nome.
GLPI_DB_HOST=db
GLPI_DB_PORT=3306
GLPI_DB_NAME=glpi_db
GLPI_DB_USER=glpi_operator
GLPI_DB_PASSWORD=senhaNoPost-it
MYSQL_RANDOM_ROOT_PASSWORD=yes
MYSQL_DATABASE=glpi_db
MYSQL_USER=glpi_operator
MYSQL_PASSWORD=senhaNoPost-it
Adaptações feitas:
- Todas as variáveis estão no stack.env. O Portainer não resolve variáveis no arquivo .yml, então todas precisam ser especificadas no stack.env ou no próprio .yml. Isso levou a variáveis com valores redundantes no stack.env
- Pela mesma questão acima, o teste do banco de dados foi removido.
- Volumes docker foram especificados em vez de caminhos para pastas no host.
Para uma implantação desse tipo no Portainer, vá na seção Stacks. Lá é possível fazer upload dos arquivos ou colar o conteúdo no editor web.

O GLPI leva um tempo após a inicialização do contêiner para ser instalado e ficar disponível na porta mapeada, nesse caso 8080. O MySQL gera uma senha aleatória para o usuário root, que você pode obter com:
$ docker logs <nome_do_conteiner_mysql> | grep GENERATED
Para acompanhar a instalação, verifique os logs do contêiner do GLPI via linha de comando ou no Portainer.
Após concluida, basta fazer login na interface web com o usuário e senha padrão, especificado no log do contêiner:
- Usuário: glpi
- Senha: glpi
Na interface web, o GLPI sugere remover o arquivo install/install.php, o que pode ser feito com:
$ docker exec -it <nome_do_conteiner_glpi> rm /var/www/glpi/install/install.php
Voltando ao Metabase: a implantação do Metabase abordada armazena as configurações em um banco de dados H2, no volume do próprio contêiner, sem nenhum volume persistente configurado. Ou seja, ao fazer uma atualização – que é feita por remover e adicionar um novo contêiner, todas as configurações, dashboards e conexões com bancos de dados seriam excluídos.
Para uso em produção, o metabase precisa ser combinado com um banco de dados para produção, como PostgreSQL. Abaixo, um exemplo de configuração em formato .yml para implantação:
volumes:
metabase_config:
services:
metabase:
image: metabase/metabase:latest
container_name: metabase
hostname: metabase
restart: "unless-stopped"
volumes:
- /dev/urandom:/dev/random:ro
ports:
- 3000:3000
environment:
MB_DB_TYPE: postgres
MB_DB_DBNAME: metabase_db
MB_DB_PORT: 5432
MB_DB_USER: metabase_operator
MB_DB_PASS: senhaNoBlocoDeNotas.txt
MB_DB_HOST: meta_postgres
networks:
- metanet1
healthcheck:
test: curl --fail -I http://localhost:3000/api/health || exit 1
interval: 15s
timeout: 5s
retries: 5
postgres:
image: postgres:latest
container_name: postgres
hostname: meta_postgres
restart: "unless-stopped"
volumes:
- metabase_config:/var/lib/postgresql/data
environment:
POSTGRES_USER: metabase_operator
POSTGRES_DB: metabase_db
POSTGRES_PASSWORD: senhaNoBlocoDeNotas.txt
networks:
- metanet1
networks:
metanet1:
driver: bridge