Docker e Docker Compose no Ubuntu Server: guia passo a passo
|

Docker e Docker Compose no Ubuntu Server: guia passo a passo

Instalar Docker com apt install docker.io traz uma versão desatualizada do repositório padrão do Ubuntu e nenhum dos plugins oficiais — nem Buildx, nem Compose v2. O método correto usa o repositório próprio da Docker Inc. e leva sete comandos até o primeiro container rodando. Este guia cobre a instalação completa no Ubuntu Server 24.04/26.04 LTS e as duas armadilhas que pegam quem já roda UFW ou firewalld no servidor.

Por que não usar o pacote docker.io do Ubuntu

O repositório universe do Ubuntu empacota o Docker Engine com atraso — às vezes meses atrás da versão estável — e não inclui o plugin docker-compose-plugin nem o docker-buildx-plugin na mesma origem, forçando a misturar fontes de pacote. Isso gera conflito de dependência quando o Docker lança correção de segurança. O repositório oficial resolve isso: uma única fonte, assinada com a chave GPG da Docker, com Engine, CLI, containerd e os dois plugins sempre em versões compatíveis entre si.

Pré-requisitos

Ubuntu Server 22.04, 24.04 ou 26.04 LTS, 64 bits, com acesso root ou sudo. Se o servidor já teve Docker instalado por outro caminho — docker.io, Snap, ou uma instalação antiga — remova antes para evitar conflito de binário:

sudo apt remove docker.io docker-compose docker-compose-v2 docker-doc docker-buildx podman-docker containerd runc

Não tem problema o comando avisar que nenhum pacote estava instalado — é o caminho normal em servidor novo.

Passo a passo

1. Adicionar o repositório oficial e a chave GPG

sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

A chave fica em /etc/apt/keyrings, não no chaveiro global do apt — é o padrão atual do Debian/Ubuntu para pacotes de terceiros, evita que uma chave comprometida valide pacotes de outros repositórios.

2. Registrar a fonte do apt

sudo tee /etc/apt/sources.list.d/docker.sources <

O trecho $(. /etc/os-release && echo ...) detecta sozinho se o servidor é Noble (24.04), Resolute (26.04) ou Jammy (22.04) — não precisa editar o codinome manualmente, o que evita o erro clássico de colar o comando de um tutorial para outra versão do Ubuntu.

3. Instalar Docker Engine, CLI, containerd e os plugins

sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Isso traz tudo: o daemon (docker-ce), o cliente de linha de comando, o runtime de containers (containerd.io), o builder multi-plataforma e o Compose v2 — que hoje é subcomando (docker compose), não o binário Python separado (docker-compose) descontinuado em 2023.

4. Confirmar que o serviço subiu

sudo systemctl status docker
sudo docker run hello-world

Se o serviço não estiver ativo, sudo systemctl start docker resolve. O container hello-world baixa uma imagem mínima, imprime uma confirmação e sai sozinho — é o teste padrão de que o daemon aceita conexões pelo socket Unix.

5. Liberar um usuário sem sudo para rodar Docker

sudo usermod -aG docker $USER
newgrp docker

Pense duas vezes antes de rodar isso em servidor de produção multiusuário: pertencer ao grupo docker equivale a ter root na máquina, porque qualquer container pode montar / do host com -v /:/mnt. Em servidor de uso único isso é aceitável; em servidor compartilhado, prefira manter sudo docker ou configurar modo rootless.

6. Corrigir o firewall antes de expor qualquer porta

Este é o passo que mais gente pula e mais gente lamenta depois. O Docker manipula as regras do iptables diretamente para rotear tráfego de container — e faz isso antes das regras do UFW ou do firewalld na cadeia do kernel. Resultado prático: um docker run -p 3306:3306 mysql expõe a porta 3306 para a internet mesmo com ufw deny 3306 ativo, porque o Docker insere a regra de NAT em um ponto que o UFW não enxerga.

A correção oficial não é desativar o Docker de mexer no iptables — quebraria a rede de containers. É adicionar as regras de bloqueio na chain própria que o Docker respeita:

sudo iptables -I DOCKER-USER -i eth0 ! -s 10.0.0.0/8 -j DROP

Ajuste eth0 para a interface pública real e a faixa de IP liberada para a sua rede interna. Qualquer regra na chain DOCKER-USER é avaliada antes do roteamento do Docker — é o único ponto de controle confiável para portas de container. Vale lembrar também que o Docker só é compatível com iptables-legacy ou iptables-nft; regras criadas só com nft puro não são respeitadas pelo daemon.

7. Subir o primeiro serviço com Docker Compose

mkdir ~/meu-servico && cd ~/meu-servico
cat > docker-compose.yml <<'EOF'
services:
  web:
    image: nginx:stable
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:80"
EOF
docker compose up -d

Repare no 127.0.0.1:8080:80 em vez de só 8080:80: publicar amarrado ao loopback impede exposição direta à internet enquanto não houver proxy reverso com TLS na frente — a mesma lógica do passo 6, aplicada sem precisar mexer em firewall. restart: unless-stopped garante que o container volte sozinho depois de reboot ou crash do daemon, sem reiniciar o que você parou manualmente.

Limitar o log dos containers

Por padrão, o driver json-file do Docker não tem limite de tamanho — um container barulhento pode encher o disco em produção sem aviso. Defina o limite globalmente em /etc/docker/daemon.json:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
sudo systemctl restart docker

Isso mantém no máximo 30 MB de log por container (3 arquivos de 10 MB, rotacionados), aplicado a todo container criado depois da mudança.

Perguntas frequentes

Docker Compose "não é reconhecido" mesmo depois de instalado?
O comando mudou de docker-compose (com hífen, binário separado) para docker compose (subcomando, plugin). Scripts antigos precisam ser atualizados.

Preciso do Docker Desktop no servidor?
Não. Docker Desktop é para máquina de desenvolvimento com interface gráfica. Em servidor Linux, o Docker Engine por linha de comando é o caminho — é o que este guia instala.

Container exposto mesmo com UFW ativo — por quê?
Porque o Docker injeta regras de NAT antes da cadeia que o UFW controla. É o comportamento coberto no passo 6 — a correção é regra na chain DOCKER-USER, não desativar o roteamento do Docker.

Docker e Podman fazem a mesma coisa?
Ambos rodam containers OCI, mas o Podman dispensa daemon central e roda rootless por padrão. O Docker tem ecossistema maior de imagens e integrações — para a maioria dos servidores em produção hoje, ainda é a escolha mais compatível.

Como desinstalar tudo, se precisar?
sudo apt purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin remove os pacotes; sudo rm -rf /var/lib/docker /var/lib/containerd apaga imagens, volumes e containers — sem volta.

Conclusão

A instalação em si leva menos de cinco minutos; o que separa um servidor Docker seguro de um vulnerável é o passo 6. Antes de publicar qualquer porta com -p, confirme que ela está na chain DOCKER-USER ou amarrada ao loopback como no exemplo do Compose. Com isso resolvido, o próximo passo natural é colocar um proxy reverso na frente dos containers para TLS — o guia de Nginx com Let's Encrypt do PulseIT cobre exatamente essa etapa.

Gostou? Compartilhe.

Posts Similares

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *