📘 Manual de Introdução

Docker — Contentorização

Containers · Images · Volumes · Networks · Docker Compose · Registry

Aprende a empacotar, distribuir e executar aplicações em contentores Docker — do desenvolvimento local ao deploy em produção, sempre com o mesmo ambiente.

01

O que é o Docker?

Conceitos fundamentais antes de começar

📦

Container

Um processo isolado que corre no teu sistema operativo, com o seu próprio sistema de ficheiros, rede e dependências. Leve, rápido e portátil — não é uma máquina virtual.

Processo isolado
🖼️

Image (Imagem)

Um template imutável e em camadas que define tudo o que um container precisa — sistema de base, dependências, código e configurações. As imagens são partilhadas via registos como o Docker Hub.

Template imutável
📜

Dockerfile

Ficheiro de texto com instruções para construir uma imagem Docker passo a passo. Define a base, copia ficheiros, instala dependências e configura o comando de arranque.

Receita de construção
🏪

Registry

Repositório de imagens Docker. O Docker Hub é o registo público por defeito. Existem também registos privados como o GitHub Container Registry, AWS ECR ou um registo próprio.

Docker Hub · GHCR
🗄️

Volume

Mecanismo para persistir dados fora do ciclo de vida do container. Os dados num volume sobrevivem a paragens e remoções do container — essencial para bases de dados e ficheiros de utilizador.

Persistência de dados
🌐

Network

Rede virtual que liga containers entre si. Por defeito, containers no mesmo docker-compose comunicam pelo nome do serviço. Isola comunicações por projecto.

Comunicação entre containers
Arquitectura Docker — visão geral HOST MACHINE (Linux / macOS / Windows) ┌──────────────────────────────────────────────────────────┐ DOCKER ENGINE (daemon) │ ┌────────────────┐ ┌────────────────┐ ┌────────────┐ │ │ Container A │ │ Container B │ │ Container C │ │ nginx:1.25 │ │ node:20 │ │ postgres:16 │ │ port 80:80 │ │ port 3000:3000 │ │ vol: pgdata │ └────────────────┘ └────────────────┘ └────────────┘ │ └─────────────────┴──────────────────┘ app-network └──────────────────────────────────────────────────────────┘
02

Instalação e Primeiros Passos

Colocar o Docker a funcionar no teu sistema

verificar instalação e testar
# Verificar versão do Docker $ docker --version Docker version 26.1.0, build 9714adc ▸ verificar se o daemon está activo $ docker info $ docker version ▸ primeiro container — o clássico "Hello World" $ docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world Hello from Docker! This message shows that your installation appears to be working correctly. ▸ correr um servidor nginx em segundos $ docker run -d -p 8080:80 --name meu-nginx nginx # Abre http://localhost:8080 no browser
Instalação: Descarrega o Docker Desktop em docker.com/products/docker-desktop — inclui Docker Engine, Docker CLI, Docker Compose e interface gráfica para Windows e macOS. Em Linux, instala o Docker Engine via gestor de pacotes: apt install docker.io ou segue as instruções oficiais em docs.docker.com.
03

Gestão de Imagens

Descarregar, listar, inspecionar e remover imagens

ComandoO que faz
🔍 Pesquisar e Descarregar
docker search nginxPesquisa imagens no Docker Hub pelo nome indicado.
docker pull nginxDescarrega a imagem nginx:latest do Docker Hub sem criar um container.
docker pull nginx:1.25Descarrega uma versão específica usando a tag. Prefere sempre tags concretas em produção.
📋 Listar e Inspecionar
docker imagesLista todas as imagens descarregadas localmente — nome, tag, ID, tamanho e data.
docker image lsEquivalente moderno de docker images. Usa -a para mostrar imagens intermédias.
docker inspect nginxDevolve metadados completos da imagem em JSON — camadas, variáveis de ambiente, portas expostas.
docker history nginxMostra as camadas da imagem e os comandos usados para as criar.
🗑️ Remover
docker rmi nginxRemove uma imagem local. Falha se existirem containers (mesmo parados) a usá-la.
docker image pruneRemove todas as imagens sem tags (dangling). Adiciona -a para remover todas as não utilizadas.
🔨 Construir
docker build -t nome:tag .Constrói uma imagem a partir do Dockerfile na directoria actual. O ponto final é o contexto de build.
docker build -f caminho/Dockerfile .Usa um Dockerfile com um nome ou localização diferente do padrão.
trabalhar com imagens
# Listar imagens locais $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest a72860cb95fd 2 days ago 187MB node 20 b3b0f8b7a5cd 5 days ago 1.1GB postgres 16 c262a7d1e82a 1 week ago 432MB ▸ construir e etiquetar imagem própria $ docker build -t minha-app:1.0 . Step 1/5 : FROM node:20-alpine Step 2/5 : WORKDIR /app Successfully built 3f4a2b1c9d8e Successfully tagged minha-app:1.0 ▸ limpar imagens não utilizadas $ docker image prune -a
04

Dockerfile — Construir Imagens

Escrever Dockerfiles eficientes e seguros

Dockerfile — aplicação Node.js (exemplo completo)
# ── Fase 1: build ────────────────────────────────────────── FROM node:20-alpine AS builder # Definir directoria de trabalho dentro do container WORKDIR /app # Copiar manifesto de dependências primeiro (aproveita cache) COPY package*.json ./ RUN npm ci --only=production # Copiar o resto do código fonte COPY . . RUN npm run build # ── Fase 2: produção (imagem final mais pequena) ──────────── FROM node:20-alpine AS production # Não correr como root — boa prática de segurança RUN addgroup -S appgroup && adduser -S appuser -G appgroup USER appuser WORKDIR /app COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules # Variável de ambiente com valor por defeito ENV NODE_ENV=production ENV PORT=3000 # Expor a porta (documentação — não abre a porta no host) EXPOSE 3000 # Comando de arranque do container CMD ["node", "dist/server.js"]
InstruçãoO que faz
FROM <imagem>Define a imagem base. Deve ser a primeira instrução. Usa imagens alpine para reduzir o tamanho.
WORKDIR <path>Define a directoria de trabalho dentro do container. Cria-a se não existir.
COPY <src> <dest>Copia ficheiros do contexto de build para o sistema de ficheiros da imagem.
RUN <comando>Executa um comando durante a construção da imagem. Cada RUN cria uma nova camada — agrupa comandos com &&.
ENV <chave>=<valor>Define variáveis de ambiente persistentes na imagem e nos containers derivados.
ARG <nome>Define variáveis disponíveis apenas durante o build — não ficam na imagem final.
EXPOSE <porta>Documenta as portas que o container irá usar. Não as abre automaticamente no host.
VOLUME <path>Declara um ponto de montagem para volume — garante persistência de dados nesse caminho.
USER <utilizador>Define o utilizador para RUN, CMD e ENTRYPOINT seguintes. Evita correr como root.
CMD ["cmd", "arg"]Comando padrão ao iniciar o container. Pode ser substituído na linha de comandos.
ENTRYPOINT ["cmd"]Ponto de entrada fixo do container — não pode ser substituído facilmente. Combina com CMD para argumentos por defeito.
⚠️ .dockerignore: Cria sempre um ficheiro .dockerignore na raiz do projecto para excluir node_modules/, .git/, ficheiros .env, logs e outros ficheiros desnecessários do contexto de build. Reduz drasticamente o tamanho da imagem e o tempo de construção.
05

Gestão de Containers

Criar, iniciar, parar, inspecionar e remover containers

ComandoO que faz
▶️ Criar e Executar
docker run <imagem>Cria e inicia um container a partir de uma imagem. Se a imagem não existir localmente, é descarregada.
docker run -d <imagem>Corre em modo detached (background) — o terminal fica livre.
docker run -it <imagem> bashModo interactivo com terminal — ideal para explorar o interior de um container.
docker run -p 8080:80 <imagem>Mapeia a porta 80 do container para a porta 8080 do host.
docker run --name meu-app <imagem>Atribui um nome ao container para facilitar a sua gestão.
docker run -e VAR=valor <imagem>Define variáveis de ambiente no container.
docker run --rm <imagem>Remove o container automaticamente quando este terminar.
📋 Listar e Monitorizar
docker psLista apenas os containers em execução.
docker ps -aLista todos os containers — em execução, parados e terminados.
docker logs <nome>Mostra os logs do container. Usa -f para seguir em tempo real.
docker statsMostra o consumo de CPU, memória, rede e disco de todos os containers activos em tempo real.
docker inspect <nome>Metadados completos do container em JSON — IPs, volumes, variáveis de ambiente, etc.
⏯️ Controlar
docker start <nome>Inicia um container parado.
docker stop <nome>Para um container graciosamente (envia SIGTERM, aguarda 10s, depois SIGKILL).
docker restart <nome>Para e inicia novamente um container.
docker exec -it <nome> bashAbre um terminal dentro de um container em execução — muito útil para depuração.
docker rm <nome>Remove um container parado. Usa -f para forçar a remoção de um container activo.
docker container pruneRemove todos os containers parados de uma vez.
ciclo de vida de um container
# Correr container Node.js com porta e variável de ambiente $ docker run -d --name api -p 3000:3000 -e NODE_ENV=production minha-app:1.0 9f3e2a1b4c5d6e7f8a9b0c1d2e3f4a5b ▸ verificar que está a correr e ver logs $ docker ps CONTAINER ID IMAGE STATUS PORTS NAMES 9f3e2a1b4c5d minha-app:1.0 Up 2 minutes 0.0.0.0:3000->3000/tcp api $ docker logs -f api Server running on port 3000 ▸ entrar no container para depuração $ docker exec -it api sh /app # ls dist node_modules package.json /app # exit ▸ parar e remover $ docker stop api && docker rm api
06

Volumes e Redes

Persistir dados e conectar containers

🗄️ Volumes

ComandoDescrição
docker volume create myvolCria um volume gerido pelo Docker.
docker volume lsLista todos os volumes.
docker volume inspect myvolDetalhes e localização do volume no host.
docker volume rm myvolRemove um volume não utilizado.
docker volume pruneRemove todos os volumes sem containers associados.
-v myvol:/app/dataMonta o volume myvol em /app/data no container.
-v $(pwd):/appMonta a directoria actual do host (bind mount) — útil em desenvolvimento.

🌐 Redes (Networks)

ComandoDescrição
docker network create mynetCria uma rede bridge personalizada.
docker network lsLista todas as redes Docker.
docker network inspect mynetDetalhes da rede e containers ligados.
docker network rm mynetRemove uma rede.
--network mynetLiga um container a uma rede específica.
--network hostUsa a rede do host directamente (sem isolamento).
--network noneContainer sem acesso à rede.
base de dados com volume persistente
# Criar volume para os dados do PostgreSQL $ docker volume create pgdata ▸ criar rede para comunicação entre containers $ docker network create app-net ▸ correr postgres com volume e rede $ docker run -d --name db \ -v pgdata:/var/lib/postgresql/data \ -e POSTGRES_PASSWORD=segredo \ --network app-net \ postgres:16 ▸ ligar a app à mesma rede — pode resolver "db" pelo nome $ docker run -d --name api --network app-net -e DB_HOST=db minha-app:1.0
07

Docker Compose

Orquestrar múltiplos containers com um único ficheiro YAML

docker-compose.yml — stack completa (web + api + db + cache)
version: '3.9' services: nginx: # servidor web / reverse proxy image: nginx:1.25-alpine ports: - "80:80" volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro depends_on: - api api: # aplicação Node.js build: context: ./api dockerfile: Dockerfile environment: NODE_ENV: production DB_HOST: db REDIS_HOST: cache depends_on: - db - cache restart: unless-stopped db: # base de dados PostgreSQL image: postgres:16-alpine environment: POSTGRES_DB: appdb POSTGRES_USER: user POSTGRES_PASSWORD: ${DB_PASSWORD} # via .env volumes: - pgdata:/var/lib/postgresql/data cache: # Redis para cache e sessões image: redis:7-alpine command: redis-server --appendonly yes volumes: - redisdata:/data volumes: # volumes geridos pelo Docker pgdata: redisdata:
ComandoO que faz
docker compose upInicia todos os serviços definidos no docker-compose.yml. Adiciona -d para background.
docker compose up --buildReconstrói as imagens antes de iniciar — necessário após alterações ao Dockerfile.
docker compose downPara e remove todos os containers e redes criados. Adiciona -v para remover também os volumes.
docker compose psLista o estado de todos os serviços do projecto.
docker compose logs -fMostra os logs de todos os serviços em tempo real. Especifica um serviço: docker compose logs api.
docker compose exec api shAbre um terminal no container do serviço api.
docker compose restart apiReinicia apenas o serviço indicado sem afectar os restantes.
docker compose pullActualiza todas as imagens dos serviços que usam imagens do registry.
docker compose configValida e mostra a configuração final do docker-compose.yml.
08

Fluxo de Trabalho Completo

Do desenvolvimento local ao deploy em produção

📜

Dockerfile

Definir a receita da imagem

🔨

Build

Construir a imagem localmente

🧪

Testar

Correr e validar localmente

☁️

Push

Enviar para o registry

🚀

Deploy

Puxar e correr em produção

1
Criar o Dockerfile

Define a imagem base, copia o código, instala dependências e configura o comando de arranque. Usa imagens alpine para reduzir o tamanho e multi-stage builds para imagens de produção mais pequenas.

Dockerfile  ·  .dockerignore
2
Construir a imagem

Executa o Dockerfile e cria uma imagem local. Usa tags com versão semântica (1.0.0) e também latest. O Docker aproveita o cache de camadas para builds mais rápidos.

docker build -t minha-app:1.0 .
3
Testar localmente com Docker Compose

Usa um docker-compose.yml para subir a stack completa (app + base de dados + cache) com um só comando. Valida que todos os serviços comunicam correctamente.

docker compose up --build
4
Fazer push para o registry

Autentica no Docker Hub (ou outro registry), faz tag da imagem com o nome completo do repositório e envia.

docker push utilizador/minha-app:1.0
5
Deploy em produção

No servidor de produção, faz pull da nova imagem e recria os containers. Usa --pull always para garantir a versão mais recente. Em ambientes orquestrados (Kubernetes, Docker Swarm), o processo de actualização é automático.

docker pull utilizador/minha-app:1.0  ·  docker compose up -d
6
Monitorizar e manter

Acompanha os logs, monitoriza o consumo de recursos, actualiza imagens regularmente para receber correcções de segurança e remove imagens e volumes não utilizados para libertar espaço.

docker stats  ·  docker logs -f  ·  docker system prune
💡 Automatização com GitHub Actions: Integra o build e push da imagem Docker no teu pipeline CI/CD. A cada push para main, o GitHub Actions constrói automaticamente a imagem, executa os testes e faz push para o Docker Hub ou GHCR — sem intervenção manual.
09

Registry e Comandos Úteis

Publicar imagens e manter o sistema limpo

publicar imagem no Docker Hub
# Autenticar no Docker Hub $ docker login Username: o-teu-utilizador Password: •••••••••• Login Succeeded ▸ etiquetar a imagem com o nome completo do repositório $ docker tag minha-app:1.0 utilizador/minha-app:1.0 $ docker tag minha-app:1.0 utilizador/minha-app:latest ▸ fazer push para o Docker Hub $ docker push utilizador/minha-app:1.0 The push refers to repository [docker.io/utilizador/minha-app] 1.0: digest: sha256:abc123... size: 1234 ▸ usar GitHub Container Registry (alternativa) $ docker tag minha-app:1.0 ghcr.io/utilizador/minha-app:1.0 $ docker push ghcr.io/utilizador/minha-app:1.0

Comandos de Manutenção e Limpeza

prune
docker system pruneRemove containers, imagens e redes não utilizados
prune
docker system prune -aRemove tudo o que não está em uso activo (com cuidado!)
df
docker system dfMostra o espaço usado por imagens, containers e volumes
top
docker top <nome>Lista os processos a correr dentro de um container
cp
docker cp src container:/destCopia ficheiros entre o host e um container
save
docker save / docker loadExporta e importa imagens como ficheiros .tar
scan
docker scout cves <imagem>Analisa vulnerabilidades de segurança na imagem
--rm
docker run --rmRemove o container automaticamente ao terminar

Boas Práticas de Segurança

Segurança

Nunca correr como root

Usa sempre USER no Dockerfile para criar e usar um utilizador sem privilégios. A instrução RUN adduser cria o utilizador dedicado à aplicação.

Segurança

Secrets via variáveis de ambiente

Nunca incluas passwords ou tokens directamente no Dockerfile. Usa .env (nunca commites), Docker Secrets ou variáveis do CI/CD.

Performance

Aproveitar o cache de camadas

Copia os ficheiros de dependências (package.json) antes do código fonte. Assim, o npm install só corre quando as dependências mudam.

Performance

Multi-stage builds

Usa múltiplas fases no Dockerfile para separar o ambiente de build do de produção — a imagem final fica mais pequena e sem ferramentas de desenvolvimento desnecessárias.

Manutenção

Actualizar imagens base

Reconstrui as tuas imagens regularmente com bases actualizadas para receber correcções de segurança. Usa o Docker Scout para detectar vulnerabilidades.

Manutenção

Tags específicas em produção

Nunca uses :latest em produção — usa sempre versões específicas (:1.2.3) para garantir reproducibilidade e evitar actualizações inesperadas.