Portainer: gerenciar Docker pela web

Portainer é a interface web mais popular para gerenciar Docker, visualize containers rodando, faça deploy de stacks via docker-compose.yml, acesse logs em tempo real e gerencie volumes e redes sem digitar um único comando. Indispensável para VPS compartilhadas com equipe ou para quem prefere uma interface visual ao terminal.

Instalar Portainer com Docker

Portainer roda como container e gerencia o próprio Docker engine:

bash
# Criar volume para persistir dados do Portainer
docker volume create portainer_data

# Instalar Portainer Community Edition (gratuito):
docker run -d \
  --name portainer \
  --restart always \
  -p 127.0.0.1:9443:9443 \
  -p 127.0.0.1:8000:8000 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v portainer_data:/data \
  portainer/portainer-ce:latest

# Verificar que está rodando:
docker ps | grep portainer

# Acessar localmente: https://127.0.0.1:9443
# (com certificado auto-assinado — aceitar o aviso de segurança)
# Criar conta admin na primeira inicialização

Configurar Nginx com SSL para o Portainer

Expor o Portainer com HTTPS e acesso restrito por IP:

nginx
# /etc/nginx/conf.d/portainer.conf
server {
    listen 80;
    server_name portainer.seudominio.com.br;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name portainer.seudominio.com.br;

    ssl_certificate     /etc/letsencrypt/live/portainer.seudominio.com.br/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/portainer.seudominio.com.br/privkey.pem;

    # Acesso APENAS do seu IP
    allow 177.10.0.1;
    deny all;

    location / {
        proxy_pass https://127.0.0.1:9443;
        proxy_http_version 1.1;
        proxy_ssl_verify off;           # certificado auto-assinado do Portainer
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 300s;
    }
}

Deploy de stack via interface web

Como fazer deploy de um docker-compose.yml pelo Portainer:

yaml
# No Portainer — Home → Local → Stacks → Add Stack

# Cole o conteúdo do docker-compose.yml:
services:
  minha-api:
    image: ghcr.io/usuario/minha-api:main
    restart: always
    environment:
      DATABASE_URL: postgresql://user:pass@postgres:5432/db
      NODE_ENV: production
    ports:
      - "127.0.0.1:3000:3000"

  postgres:
    image: postgres:16-alpine
    restart: always
    environment:
      POSTGRES_DB: minha_db
      POSTGRES_USER: minha_app
      POSTGRES_PASSWORD: senha
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

# Clicar em "Deploy the stack"
# O Portainer executa docker compose up -d internamente

# Atualizar a stack após novo deploy:
# Stacks → nome-da-stack → Update the stack → Re-pull and redeploy

Funcionalidades principais do Portainer

O que você pode fazer pela interface web:

bash
# Containers:
# - Ver todos os containers (running, stopped, paused)
# - Logs em tempo real (com filtro e download)
# - Console interativo (equivalente ao docker exec -it)
# - Stats de CPU/memória em tempo real
# - Inspecionar configurações do container
# - Reiniciar, parar, deletar containers

# Stacks (docker compose):
# - Deploy de nova stack via YAML ou repositório Git
# - Atualizar stack (pull nova imagem + restart)
# - Ver todos os containers de uma stack

# Imagens:
# - Pull de imagens do Docker Hub ou registry privado
# - Ver tamanho e camadas
# - Limpar imagens não utilizadas (prune)

# Volumes:
# - Ver todos os volumes e seus tamanhos
# - Browse pelos arquivos do volume
# - Criar e deletar volumes

# Redes:
# - Ver topologia das redes
# - Criar e deletar redes customizadas

Atualizar containers automaticamente via Portainer

Configurar webhooks para atualizar containers a partir do CI/CD:

yaml
# No Portainer — Stacks → nome-da-stack → Webhooks

# Ativar webhook para atualização automática:
# Toggle "GitOps updates" ou "Webhook" → copiar URL gerado

# No GitHub Actions — chamar o webhook após o push:
      - name: Atualizar stack via Portainer
        run: |
          curl -X POST "${{ secrets.PORTAINER_WEBHOOK_URL }}"

# O Portainer faz pull da nova imagem e reinicia o container

# Para atualizar via API REST do Portainer:
# 1. Gerar API key: Account → Access tokens
# 2. Chamar a API:
STACK_ID=1
curl -X POST \
  "https://portainer.seudominio.com.br/api/stacks/$STACK_ID/git/redeploy" \
  -H "X-API-Key: SEU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"pullImage": true}'

Não quer configurar manualmente?

Implante o VPS em menos de 5 minutos com a Runstack. Infraestrutura da OPEN Datacenter, com servidores em São Paulo.

Perguntas frequentes

Community (CE): gratuito, suporta um ambiente Docker, funcionalidades básicas completas. Business (BE): gerenciar múltiplos hosts Docker/Kubernetes, controle de acesso por equipe (RBAC), auditoria, registro de imagens integrado. Para VPS única com equipe pequena: Community é mais que suficiente.

Com as devidas precauções: sim. Restrinja o acesso por IP no Nginx (allow apenas seu IP), use senha forte para o admin e ative 2FA. O principal risco é a exposição do /var/run/docker.sock, quem acessa o Portainer tem controle total do Docker host. Nunca deixe o Portainer acessível publicamente sem restrição de IP.

Sim, com Portainer Agent instalado nas outras VPS e registrado no Portainer principal como Environments. Isso permite gerenciar todos os hosts Docker de uma interface centralizada. Com Portainer Business: gerenciamento de Kubernetes também.

Sim, você pode criar múltiplos usuários com diferentes permissões (admin, padrão, readonly). Na versão CE: controle básico por usuário. Na versão BE: RBAC completo com equipes e permissões por recurso (quem pode ver/editar qual stack). Para equipes: crie usuários individuais, nunca compartilhe o admin.

docker exec portainer portainer --admin-password-file /tmp/passwd (gerar o arquivo com htpasswd). Ou: docker stop portainer, docker run ... portainer/portainer-ce --admin-password "senha-nova-bcrypt". Para emergências: docker rm portainer e recriar, os dados estão no volume portainer_data que é preservado.