15%

Poupe 15% em todos os serviços

Teste as suas habilidades e obtenha Desconto em qualquer plano

Utilizar o código:

Skills
Começar a trabalhar
08.10.2024

Docker no Ubuntu: Guia Completo de Instalação e Uso

Docker é uma plataforma de contentorização de código aberto que empacota aplicações e as suas dependências em unidades isoladas e portáteis chamadas contentores. Ao contrário das máquinas virtuais, os contentores partilham o kernel do SO anfitrião, tornando-os significativamente mais leves, mais rápidos a iniciar e mais eficientes em termos de recursos — uma distinção crítica para quem executa cargas de trabalho num ambiente de VPS Hosting onde os recursos de computação afetam diretamente o custo e o desempenho.

Este guia abrange o processo completo de instalação do Docker no Ubuntu 20.04, 22.04 e 24.04 LTS, incluindo proteção pós-instalação, fluxos de trabalho do Docker Compose e padrões de comandos relevantes para produção que a maioria dos tutoriais omite.

Pré-requisitos e Requisitos do Sistema

Antes de executar um único comando, verifique o seguinte:

  • Versão do Ubuntu: 20.04 LTS (Focal), 22.04 LTS (Jammy) ou 24.04 LTS (Noble). O comando `lsb_release -cs` utilizado durante a configuração do repositório detetará automaticamente o seu codinome.
  • Arquitetura: `amd64`, `arm64` ou `armhf` são todas suportadas pelo repositório oficial do Docker.
  • Versão do kernel: O Docker requer o kernel Linux 3.10 ou superior. Execute `uname -r` para confirmar.
  • Privilégios de utilizador: `sudo` ou acesso root é obrigatório para instalação e gestão do daemon.
  • Espaço em disco: No mínimo 2 GB livres na partição que aloja `/var/lib/docker`, que é onde o Docker armazena imagens, contentores, volumes e cache de compilação. Em sistemas de produção, monte este diretório numa partição ou volume dedicado.

Passo crítico de pré-instalação: Se instalou anteriormente o Docker a partir do repositório `apt` predefinido do Ubuntu (o pacote `docker.io`), remova-o primeiro para evitar conflitos com os pacotes oficiais do Docker CE:

“`bash

sudo apt remove docker docker-engine docker.io containerd runc

“`

Passo 1: Atualizar os Pacotes do Sistema

Atualize o índice de pacotes e os pacotes instalados para as suas versões mais recentes antes de adicionar qualquer novo repositório:

“`bash

sudo apt update

sudo apt upgrade -y

“`

Isto garante que o resolvedor de dependências do `apt` funciona com metadados de pacotes atuais e que as bibliotecas do sistema base não estão desatualizadas — uma fonte comum de erros de execução subtis com aplicações contentorizadas.

Passo 2: Instalar o Docker Engine a partir do Repositório Oficial

Os repositórios `apt` predefinidos do Ubuntu incluem um pacote chamado `docker.io`, que é mantido pela Canonical e normalmente fica várias versões atrás do lançamento oficial do Docker. Para uso em produção, instale sempre a partir do repositório próprio do Docker.

2.1 Instalar Dependências de Transporte e Verificação

“`bash

sudo apt install apt-transport-https ca-certificates curl software-properties-common gnupg lsb-release -y

“`

Porquê `gnupg`? A partir do Ubuntu 22.04, o `gpg` nem sempre está presente por predefinição. Incluí-lo explicitamente evita que a importação da chave GPG falhe silenciosamente.

2.2 Adicionar a Chave GPG Oficial do Docker

“`bash

sudo install -m 0755 -d /usr/share/keyrings

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg –dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

sudo chmod a+r /usr/share/keyrings/docker-archive-keyring.gpg

“`

O passo `chmod a+r` é frequentemente ignorado nos tutoriais, mas é necessário em sistemas onde o `apt` é executado num contexto de utilizador restrito — sem ele, o gestor de pacotes não consegue ler o chaveiro e apresentará um erro `NO_PUBKEY` durante o `apt update`.

2.3 Adicionar o Repositório Estável do Docker

“`bash

echo

"deb [arch=$(dpkg –print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg]

https://download.docker.com/linux/ubuntu

$(lsb_release -cs) stable" |

sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

“`

A substituição `arch=$(dpkg –print-architecture)` é essencial em servidores baseados em ARM. Codificar `amd64` aqui é um erro comum que causa falhas silenciosas na resolução de pacotes em instâncias ARM.

2.4 Instalar o Docker Engine, CLI e Plugins

“`bash

sudo apt update

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

“`

Descrição dos pacotes:

PacoteFunção
`docker-ce`Daemon do Docker Engine (`dockerd`)
`docker-ce-cli`CLI do cliente (comando `docker`)
`containerd.io`Runtime de contentores de baixo nível (compatível com OCI)
`docker-buildx-plugin`Capacidades de compilação alargadas (multiplataforma, BuildKit)
`docker-compose-plugin`Compose V2 integrado como plugin CLI do Docker

Nota sobre `containerd.io`: Este não é o mesmo que o pacote `containerd` no repositório predefinido do Ubuntu. O `containerd.io` do Docker é uma versão específica e testada do runtime containerd. Misturar os dois é uma causa conhecida de falhas na inicialização do daemon.

Passo 3: Verificar a Instalação

Confirme que o daemon está ativo e configurado para iniciar no arranque:

“`bash

sudo systemctl status docker

sudo systemctl enable docker

“`

Verifique a versão instalada:

“`bash

sudo docker –version

sudo docker info

“`

`docker info` é mais informativo do que `–version` isoladamente — revela o driver de armazenamento em uso (normalmente `overlay2`), o driver cgroup (`systemd` vs `cgroupfs`) e o número de CPUs e memória a que o Docker pode aceder.

Execute o teste de verificação canónico:

“`bash

sudo docker run hello-world

“`

Uma execução bem-sucedida imprime uma mensagem “Hello from Docker!” e confirma que o daemon do Docker, a extração de imagens do Docker Hub e a execução de contentores estão todos a funcionar corretamente.

Passo 4: Configurar o Docker para Acesso Sem Root

Por predefinição, o socket do Docker (`/var/run/docker.sock`) é propriedade do `root` e do grupo `docker`. Qualquer utilizador que não esteja no grupo `docker` deve usar `sudo` para cada comando Docker.

“`bash

sudo usermod -aG docker $USER

“`

Aplique a associação ao grupo sem terminar sessão:

“`bash

newgrp docker

“`

Verifique:

“`bash

docker run hello-world

“`

Aviso de segurança: A associação ao grupo `docker` é efetivamente equivalente a `sudo` sem palavra-passe. Um utilizador no grupo `docker` pode facilmente montar o sistema de ficheiros do anfitrião num contentor e escapar a todos os controlos de acesso ao nível do sistema de ficheiros. Em sistemas multi-inquilino ou servidores partilhados, considere usar o Docker rootless:

“`bash

dockerd-rootless-setuptool.sh install

“`

O modo rootless executa o daemon do Docker e os contentores sob um espaço de nomes de utilizador sem privilégios, reduzindo drasticamente a superfície de ataque. É a configuração recomendada para qualquer ambiente onde múltiplos utilizadores partilham o mesmo anfitrião.

Passo 5: Referência de Comandos Essenciais do Docker

Gestão de Imagens

“`bash

Pull a specific image version from Docker Hub

docker pull nginx:1.27-alpine

List locally cached images

docker images

Remove a specific image

docker rmi nginx:1.27-alpine

Remove all dangling (untagged) images to reclaim disk space

docker image prune

Remove all unused images (not just dangling)

docker image prune -a

“`

Dica de produção: Utilize sempre tags com versão (ex.: `nginx:1.27-alpine`) em vez de `latest` em qualquer fluxo de trabalho automatizado ou de produção. A tag `latest` é mutável — pode apontar para uma imagem diferente após um push no registo, comprometendo a reprodutibilidade.

Ciclo de Vida dos Contentores

“`bash

Run a container interactively with a pseudo-TTY

docker run -it ubuntu:22.04 /bin/bash

Run a container in detached mode with port mapping and a name

docker run -d -p 8080:80 –name my-nginx nginx:1.27-alpine

List running containers

docker ps

List all containers (including stopped)

docker ps -a

Stop a running container gracefully (SIGTERM, then SIGKILL after timeout)

docker stop my-nginx

Start a stopped container

docker start my-nginx

Remove a stopped container

docker rm my-nginx

Force-remove a running container (sends SIGKILL immediately)

docker rm -f my-nginx

View real-time logs

docker logs -f my-nginx

Execute a command inside a running container

docker exec -it my-nginx /bin/sh

“`

Inspeção de Recursos e do Sistema

“`bash

Display real-time resource usage statistics

docker stats

Inspect detailed container metadata (JSON)

docker inspect my-nginx

Display disk usage by Docker objects

docker system df

Remove all stopped containers, unused networks, dangling images, and build cache

docker system prune

“`

`docker system prune` é um dos comandos de manutenção mais importantes para servidores de longa duração. Sem limpeza periódica, a cache de compilação do Docker e os contentores parados podem consumir dezenas de gigabytes num anfitrião de desenvolvimento ou CI ativo.

Passo 6: Docker Compose — Orquestração de Aplicações Multi-Contentor

O Docker Compose V2 (o `docker-compose-plugin` instalado anteriormente) é invocado como `docker compose` (com espaço), não o legado `docker-compose` (com hífen). Ambas as sintaxes funcionam se tiver o plugin instalado, mas V2 é o padrão atual.

6.1 Compreender a Estrutura do Ficheiro Compose

Crie um diretório de projeto e um ficheiro `compose.yml` (o nome de ficheiro preferido no Compose V2; `docker-compose.yml` continua suportado para compatibilidade retroativa):

“`bash

mkdir ~/my-web-app && cd ~/my-web-app

nano compose.yml

“`

Um exemplo realista para produção com Nginx e um serviço de backend:

“`yaml

services:

web:

image: nginx:1.27-alpine

ports:

  • "8080:80"

volumes:

  • ./nginx.conf:/etc/nginx/nginx.conf:ro
  • ./html:/usr/share/nginx/html:ro

depends_on:

  • app

restart: unless-stopped

app:

image: node:20-alpine

working_dir: /usr/src/app

volumes:

  • ./app:/usr/src/app

command: node server.js

environment:

  • NODE_ENV=production

restart: unless-stopped

“`

Explicação das diretivas chave do Compose:

  • `restart: unless-stopped` — O contentor reinicia automaticamente após uma falha ou reinício do sistema, a menos que tenha sido explicitamente parado pelo operador. Esta é a política correta para serviços de longa duração; `always` reiniciará mesmo contentores intencionalmente parados.
  • `depends_on` — Controla a ordem de arranque, mas não aguarda que o serviço esteja *pronto* (ex.: uma base de dados a aceitar ligações). Para controlo de prontidão, use `healthcheck` combinado com `condition: service_healthy`.
  • `volumes` com `:ro` — Montar ficheiros de configuração como só de leitura impede que um processo de contentor comprometido modifique a sua própria configuração.

6.2 Comandos do Fluxo de Trabalho do Compose

“`bash

Start all services in detached mode

docker compose up -d

View logs for all services

docker compose logs -f

View logs for a specific service

docker compose logs -f web

List running Compose services

docker compose ps

Scale a specific service to multiple replicas

docker compose up -d –scale app=3

Stop services without removing containers

docker compose stop

Stop and remove containers, networks, and volumes

docker compose down –volumes

Rebuild images before starting (useful after code changes)

docker compose up -d –build

“`

6.3 Verificar o Serviço em Execução

“`bash

curl -I http://localhost:8080

“`

Uma resposta `200 OK` confirma que o Nginx está a servir corretamente. Para serviços em execução numa instância remota de VPS Hosting, substitua `localhost` pelo endereço IP público do seu servidor e certifique-se de que a porta relevante está aberta na sua firewall (`ufw allow 8080/tcp`).

Passo 7: Fundamentos de Rede do Docker

Compreender o modelo de rede do Docker é essencial para construir aplicações multi-contentor que comunicam de forma segura.

Drivers de rede predefinidos:

DriverCaso de Uso
`bridge`Predefinição para contentores autónomos; espaço de nomes de rede isolado no anfitrião
`host`O contentor partilha a pilha de rede do anfitrião; desempenho máximo, zero isolamento
`none`Sem acesso à rede; útil para processamento em lote ou cargas de trabalho sensíveis à segurança
`overlay`Rede multi-anfitrião para clusters Docker Swarm
`macvlan`Atribui um endereço MAC ao contentor; aparece como um dispositivo físico na rede

Criar e utilizar uma rede bridge personalizada:

“`bash

Create an isolated network

docker network create my-app-network

Run containers attached to the custom network

docker run -d –name db –network my-app-network postgres:16-alpine

docker run -d –name api –network my-app-network my-api-image

Containers on the same custom bridge network can resolve each other by name

Inside 'api', you can connect to 'db' using the hostname 'db'

“`

As redes bridge personalizadas fornecem resolução DNS automática entre contentores pelo nome do contentor. A rede `bridge` predefinida não o faz — esta é uma distinção crítica que causa falhas de ligação quando os programadores assumem que os contentores na rede predefinida se podem alcançar mutuamente pelo nome.

Passo 8: Dados Persistentes com Volumes Docker

Os contentores são efémeros por design. Quaisquer dados escritos no sistema de ficheiros de um contentor são perdidos quando o contentor é removido. Para armazenamento persistente, use volumes ou bind mounts.

“`bash

Create a named volume

docker volume create pgdata

Use the volume with a container

docker run -d

–name postgres-db

-e POSTGRES_PASSWORD=securepassword

-v pgdata:/var/lib/postgresql/data

postgres:16-alpine

List volumes

docker volume ls

Inspect a volume (shows mount point on host)

docker volume inspect pgdata

Remove unused volumes

docker volume prune

“`

Volumes vs. bind mounts:

FuncionalidadeVolume NomeadoBind Mount
Gerido pelo DockerSimNão
Caminho do anfitrião necessárioNãoSim
Portátil entre anfitriõesSim (com drivers de volume)Não
Melhor paraDados de base de dados, estado da aplicaçãoCódigo de desenvolvimento, ficheiros de configuração
Mecanismo de cópia de segurança`docker run –volumes-from`Ferramentas padrão do sistema de ficheiros

Passo 9: Manter o Docker Atualizado

O repositório oficial do Docker trata as atualizações através do mecanismo `apt` padrão:

“`bash

sudo apt update

sudo apt upgrade -y

“`

Para atualizar apenas os pacotes relacionados com o Docker sem atualizar o sistema inteiro:

“`bash

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

“`

Consulte as notas de lançamento do Docker antes de atualizações de versões principais, particularmente para alterações ao driver de armazenamento, tratamento da versão cgroup ou versões de API descontinuadas que possam afetar os ficheiros `compose.yml` existentes.

Docker vs. Abordagens Alternativas de Contentorização

FuncionalidadeDocker EnginePodmanLXC/LXDcontainerd (autónomo)
Arquitetura do daemonDaemon centralizadoSem daemonBaseado em daemonBaseado em daemon
Suporte rootlessSim (v20+)NativoLimitadoSim
Suporte Docker ComposeNativoVia `podman-compose`NãoNão
Conformidade OCISimSimNão (formato LXC)Sim
Integração KubernetesVia shim CRI-dockerdCRI nativoNãoCRI nativo
Suporte Windows/macOSDocker DesktopLimitadoNãoNão
Melhor paraDesenvolvimento geral e produçãoFocado em segurança, rootlessContentores de sistema, VMsNós Kubernetes

Para equipas que executam cargas de trabalho contentorizadas em escala em bare metal, um ambiente de Servidores Dedicados dá-lhe controlo total sobre os parâmetros do kernel, o agendamento de I/O de armazenamento e a configuração de rede — todos os quais afetam diretamente a densidade e o desempenho dos contentores.

Lista de Verificação de Proteção para Produção

Antes de executar o Docker num ambiente de produção, resolva o seguinte:

Configuração do daemon (`/etc/docker/daemon.json`):

“`json

{

"log-driver": "json-file",

"log-opts": {

"max-size": "10m",

"max-file": "3"

},

"storage-driver": "overlay2",

"userns-remap": "default",

"live-restore": true,

"no-new-privileges": true

}

“`

  • `log-opts` com `max-size` e `max-file`: Sem rotação de registos, os ficheiros de registo JSON do Docker encherão o seu disco. Esta é uma das causas mais comuns de interrupções inesperadas do servidor em anfitriões contentorizados.
  • `userns-remap: "default"`: Ativa o remapeamento de espaço de nomes de utilizador, para que o root do contentor (UID 0) mapeie para um UID sem privilégios no anfitrião.
  • `live-restore: true`: Permite que os contentores continuem a funcionar se o daemon do Docker falhar ou for reiniciado durante uma atualização — crítico para manutenção sem tempo de inatividade.
  • `no-new-privileges: true`: Impede que os processos do contentor obtenham privilégios adicionais através de binários `setuid` ou `setgid`.

Considerações sobre rede e firewall:

O Docker manipula o `iptables` diretamente e ignora as regras do `ufw` por predefinição. Um contentor com uma porta publicada (`-p 8080:80`) será acessível a partir da internet mesmo que `ufw deny 8080` esteja definido. Para aplicar regras do `ufw` sobre a manipulação do `iptables` pelo Docker, adicione `"iptables": false` ao `daemon.json` e gira o encaminhamento manualmente, ou use as redes `–network host` do Docker com regras `ufw` explícitas.

Para projetos que requerem terminação HTTPS, combine a sua aplicação contentorizada com um proxy reverso devidamente configurado (Nginx ou Traefik) e um certificado válido. Os Certificados SSL são um pré-requisito para qualquer serviço web de produção a executar por detrás de uma pilha contentorizada.

Se a sua carga de trabalho envolve inferência de machine learning, serviço de modelos ou processamento de dados acelerado por GPU dentro de contentores, o NVIDIA Container Toolkit integra-se diretamente com o Docker Engine. O GPU Hosting fornece o hardware subjacente necessário para estas cargas de trabalho.

Para equipas que gerem múltiplos projetos com gestão de contentores baseada na web, o VPS com cPanel oferece um ambiente de painel de controlo gerido que pode complementar as implementações baseadas em Docker para pilhas de aplicações mais simples.

Principais Conclusões Técnicas e Matriz de Decisão

Quando usar Docker num VPS vs. num servidor dedicado:

  • Use um VPS para ambientes de desenvolvimento, staging e cargas de trabalho de produção de tráfego baixo a médio onde a densidade de contentores é de 10 a 50 contentores.
  • Use um servidor dedicado quando a densidade de contentores exceder 50 instâncias, quando precisar de desempenho de I/O previsível (sem efeito de vizinho barulhento) ou quando for necessário ajuste de parâmetros do kernel (`sysctl`) para a sua carga de trabalho.

Lista de verificação operacional antes de entrar em produção:

  • Configurar a rotação de registos em `daemon.json` (`max-size`, `max-file`)
  • Ativar `live-restore` para sobreviver a reinícios do daemon sem tempo de inatividade dos contentores
  • Usar volumes nomeados, não bind mounts, para dados de serviços com estado
  • Fixar versões de imagens em todos os ficheiros `compose.yml` — nunca usar `latest` em produção
  • Ativar `userns-remap` ou executar Docker rootless em anfitriões multi-inquilino
  • Auditar as regras `iptables` após a instalação do Docker para confirmar que a política de firewall não é contornada
  • Definir `restart: unless-stopped` em todos os serviços de longa duração
  • Executar `docker system prune` numa tarefa cron agendada para evitar o esgotamento do disco
  • Usar redes bridge personalizadas para toda a comunicação entre contentores — nunca depender da bridge predefinida para descoberta de serviços

FAQ

O Docker no Ubuntu usa `systemd` ou `cgroupfs` como driver cgroup por predefinição?

Desde o Docker Engine 20.10, o driver cgroup predefinido em sistemas baseados em `systemd` (incluindo todas as versões modernas do Ubuntu LTS) é `systemd`. Isto alinha-se com os requisitos do Kubernetes e evita a instabilidade causada pela execução simultânea de dois gestores cgroup. Pode verificar com `docker info | grep -i cgroup`.

Qual é a diferença entre `docker compose down` e `docker compose stop`?

`docker compose stop` para os contentores em execução, mas preserva-os a eles e às suas redes associadas. `docker compose down` para os contentores e depois remove-os juntamente com as redes criadas pelo Compose. Adicionar `–volumes` ao `down` também remove os volumes nomeados definidos no ficheiro Compose — use este sinalizador com cautela em produção, pois elimina permanentemente os dados persistentes.

Porque é que o Docker ignora as regras de firewall do `ufw` no Ubuntu?

O Docker insere as suas próprias regras `iptables` nas cadeias `DOCKER` e `DOCKER-USER`, que são avaliadas antes das regras da cadeia `INPUT` do `ufw`. Isto significa que uma porta publicada com `-p` é acessível a partir da internet independentemente da política do `ufw`. A mitigação correta é adicionar regras diretamente à cadeia `DOCKER-USER`, ou vincular as portas publicadas a uma interface específica (ex.: `-p 127.0.0.1:8080:80`) quando o acesso externo não é necessário.

Como limito a CPU e a memória que um contentor Docker pode consumir?

Use sinalizadores de restrição de recursos em tempo de execução: `docker run –memory="512m" –cpus="1.5" my-image`. No Compose, defina-os sob a chave `deploy.resources` (Compose V2) ou as chaves de nível superior `mem_limit` e `cpus`. Sem limites, um único contentor descontrolado pode esgotar os recursos do anfitrião e derrubar todos os outros contentores no mesmo anfitrião.

Posso executar Docker dentro de um contentor Docker (Docker-in-Docker)?

Sim, mas é fortemente desaconselhado para uso em produção. O padrão comum para pipelines de CI é montar o socket Docker do anfitrião (`-v /var/run/docker.sock:/var/run/docker.sock`) no contentor de CI, o que dá ao contentor controlo total sobre o daemon Docker do anfitrião — um risco de segurança significativo. Uma alternativa mais segura é usar o sinalizador `–allow security.insecure` do BuildKit ou ferramentas criadas especificamente para este fim, como Kaniko ou Buildah, que constroem imagens OCI sem necessitar de um daemon Docker.

15%

Poupe 15% em todos os serviços

Teste as suas habilidades e obtenha Desconto em qualquer plano

Utilizar o código:

Skills
Começar a trabalhar