Instalação e Configuração Avançada do Portainer com Docker e TLS

Seleção e Obtenção da Imagem

Inicialmente, é necessário identificar a imagem correta no registro do Docker. O projeto possui duas variantes principais:

  • portainer/portainer: Versão legada, descontinuada.
  • portainer/portainer-ce: Edição Comunitária atual, ativamente mantida.

Para baixar a versão mais recente da edição comunitária, execute:

docker pull portainer/portainer-ce:latest

Implantação do Contêiner

A inicialização do serviço requer o mapeamento adequado de portas, volumes e configurações de fuso horário. Abaixo está o comando de execução com parâmetros detalhados:

docker run -d \
  --name portainer-ui \
  --restart=always \
  -p 9443:9443 \
  -p 9000:9000 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /opt/portainer/storage:/data \
  -v /opt/portainer/assets:/public \
  -v /etc/timezone:/etc/timezone:ro \
  -v /etc/localtime:/etc/localtime:ro \
  portainer/portainer-ce:latest

Detalhamento dos parâmetros:

  • -d: Executa o processo em segundo plano (modo detached).
  • -p 9443:9443 e -p 9000:9000: Expõem as portas para acesso HTTPS e HTTP, respectivamente.
  • --restart=always: Garante a ressurreição automática do contêiner em caso de falha ou reinicialização do host.
  • -v /var/run/docker.sock...: Permite que a interface gerencie o daemon do Docker hospedeiro.
  • -v /opt/portainer/storage:/data: Persiste as configurações e o estado da aplicação.
  • -v /etc/localtime:/etc/localtime:ro: Sincroniza o relógio do contêiner com o do host em modo de somente leitura, essencial para registros de log precisos.

Acesso e Configuração Inicial

Após a inicialização, acesse a interface via navegador utilizando o endereço https://SEU_IP:9443. No primeior acesso, o sistema exigirá a criação de uma senha robusta (mínimo de 12 caracteres) para o usuário administrador padrão.

Para adaptar a interface para o idioma local, acesse as configurações de usuário no canto superior direito e altere a preferência de idioma (Language) para Portuguese, caso a versão suporte nativamente, ou utilize os assets montados no diretório /public para injeção de traduções customizadas.

Operações Básicas na Interface

O painel fornece controle granular sobre o ambiente:

  • Ciclo de Vida: Inicie, pare ou reinicie instâncias diretamente pela lista de contêineres.
  • Logs: Visualize a saída padrão (stdout/stderr) em tempo real, com opções de filtro e exportação.
  • Inspeção: Analise metadados, variáveis de ambiente e configurações de rede de cada instância.
  • Métricas: Monitore o consumo de CPU, memória e I/O através da aba de estatísticas.
  • Console: Abra um terminal interativo (exec) dentro do contêiner para depuração.

Orquestração com Docker Compose

Para ambientes mais cmoplexos, o Portainer pode ser integrado a uma pilha de microsserviços. Abaixo, um exemplo de arquivo docker-compose.yml reestruturado:

version: '3.8'

services:
  discovery-node:
    build:
      context: ./services/discovery
      dockerfile: Dockerfile
    ports:
      - "8761:8761"
    volumes:
      - ./data/discovery:/app/logs
    networks:
      - backend_net

  billing-api:
    build:
      context: ./services/billing
      dockerfile: Dockerfile
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=docker
    depends_on:
      - discovery-node
      - relational-db
    networks:
      - backend_net

  cache-db:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    command: redis-server --appendonly yes
    volumes:
      - ./data/redis:/data
    networks:
      - backend_net

  relational-db:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: db_admin
      POSTGRES_PASSWORD: S3cur3P@ssw0rd
      POSTGRES_DB: billing_db
    ports:
      - "5432:5432"
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
    networks:
      - backend_net

  portainer-ui:
    image: portainer/portainer-ce:latest
    ports:
      - "9443:9443"
      - "9000:9000"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_vol:/data
    restart: always
    networks:
      - backend_net

volumes:
  portainer_vol:

networks:
  backend_net:
    driver: bridge

Valide a sintaxe e implante a pilha:

docker compose config -q
docker compose up -d --build

Gerenciamento de Hosts Remotos

Para administrar nós Docker externos, a exposição da API via porta 2375 sem criptografia é uma vulnerabilidade crítica. A abordagem recomendada é utilizar autenticação mútua via TLS.

Geração de Certificados

Crie um script automatizado para gerar a autoridade certificadora (CA) e os pares de chaves para o servidor e cliente:

#!/bin/bash
set -e

# Variáveis de ambiente
TARGET_HOST="203.0.113.50"
CERT_PASS="C0mpl3xP@ss"
CERT_COUNTRY="BR"
CERT_STATE="SaoPaulo"
CERT_CITY="Campinas"
CERT_ORG="TechCorp"
CERT_OU="DevOps"
CERT_EMAIL="admin@techcorp.local"

WORK_DIR="/etc/docker/certs"
mkdir -p $WORK_DIR
cd $WORK_DIR

# Autoridade Certificadora (CA)
openssl genrsa -aes256 -passout pass:$CERT_PASS -out ca-key.pem 4096
openssl req -new -x509 -passin "pass:$CERT_PASS" -days 3650 -key ca-key.pem -sha256 -out ca.pem \
  -subj "/C=$CERT_COUNTRY/ST=$CERT_STATE/L=$CERT_CITY/O=$CERT_ORG/OU=$CERT_OU/CN=$TARGET_HOST/emailAddress=$CERT_EMAIL"

# Certificado do Servidor
openssl genrsa -out server-key.pem 4096
openssl req -subj "/CN=$TARGET_HOST" -new -key server-key.pem -out server.csr
echo "subjectAltName = IP:$TARGET_HOST,IP:127.0.0.1" > extfile.cnf
echo "extendedKeyUsage = serverAuth" >> extfile.cnf
openssl x509 -req -days 3650 -in server.csr -CA ca.pem -CAkey ca-key.pem -passin "pass:$CERT_PASS" -CAcreateserial -out server-cert.pem -extfile extfile.cnf

# Certificado do Cliente
openssl genrsa -out client-key.pem 4096
openssl req -subj '/CN=client' -new -key client-key.pem -out client.csr
echo "extendedKeyUsage = clientAuth" > extfile.cnf
openssl x509 -req -days 3650 -in client.csr -CA ca.pem -CAkey ca-key.pem -passin "pass:$CERT_PASS" -CAcreateserial -out client-cert.pem -extfile extfile.cnf

# Limpeza
rm -f client.csr server.csr extfile.cnf

Execute o script para gerar os artefatos criptográficos:

chmod +x generate_certs.sh
./generate_certs.sh

Configuração do Daemon Remoto

Edite o arquivo de serviço do Docker (/etc/systemd/system/docker.service.d/override.conf ou /lib/systemd/system/docker.service) no host remoto para exigir verificação TLS:

[Service]
ExecStart=
ExecStart=/usr/bin/dockerd \
  --tlsverify \
  --tlscacert=/etc/docker/certs/ca.pem \
  --tlscert=/etc/docker/certs/server-cert.pem \
  --tlskey=/etc/docker/certs/server-key.pem \
  -H tcp://0.0.0.0:2376 \
  -H unix:///var/run/docker.sock

Recarregue o systemd e reinicie o serviço:

systemctl daemon-reload
systemctl restart docker

Conexão no Portainer

No painel do Portainer, navegue até Environments > Add environment > Docker Standalone. Selecione a opção TLS e faça o upload dos arquivos ca.pem, client-cert.pem e client-key.pem gerados anteriormente. Insira o endereço do host remoto utilizando a porta segura 2376 (ex: tcp://203.0.113.50:2376) e finalize a vinculação.

Tags: Portainer Docker docker-compose tls devops

Publicado em 9-17 00:59