Imagens Docker: pull, build e push
1. Entendendo o ecossistema de imagens Docker
Imagens Docker são pacotes executáveis imutáveis que contêm tudo necessário para rodar um software: código, runtime, bibliotecas, variáveis de ambiente e arquivos de configuração. Elas são a base para a criação de containers — instâncias em execução dessas imagens.
O ecossistema gira em torno de registries (repositórios centralizados), como Docker Hub, Amazon ECR, Google Container Registry (GCR) e GitHub Container Registry. Cada imagem é identificada por um nome no formato registry/usuario/repo:tag. A tag representa uma versão específica, sendo latest a padrão (mas não recomendada para produção).
Imagens oficiais são mantidas pela Docker ou por comunidades confiáveis (ex: node:18-alpine), enquanto imagens personalizadas são criadas pela equipe de desenvolvimento para atender necessidades específicas do projeto.
2. Pull: baixando imagens do registry
O comando docker pull baixa uma imagem de um registry para o cache local. Sintaxe básica:
docker pull [OPÇÕES] NOME[:TAG|@DIGEST]
Exemplos práticos:
# Baixar imagem oficial do Ubuntu com tag 22.04
docker pull ubuntu:22.04
# Baixar por digest SHA256 (imutável)
docker pull ubuntu@sha256:abcdef1234567890
# Baixar de registry privado (ex: ECR)
docker pull 123456789012.dkr.ecr.us-east-1.amazonaws.com/minha-app:v1
Flags úteis:
- --platform linux/amd64 — especificar arquitetura
- --all-tags — baixar todas as tags de um repositório
Pull por digest é a abordagem mais segura para produção, pois garante que exatamente a mesma imagem será obtida, independente de atualizações na tag.
Para autenticação em registries privados:
# Docker Hub
docker login -u usuario
# Amazon ECR
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com
# Google GCR
gcloud auth configure-docker
3. Build: criando sua própria imagem do zero
O comando docker build constrói uma imagem a partir de um Dockerfile. O contexto de build é o diretório enviado ao daemon do Docker (geralmente o diretório atual).
Dockerfile essencial:
# Imagem base
FROM node:18-alpine
# Define diretório de trabalho
WORKDIR /app
# Copia arquivos de dependências
COPY package*.json ./
# Instala dependências
RUN npm install --production
# Copia código fonte
COPY . .
# Expõe porta
EXPOSE 3000
# Comando de inicialização
CMD ["node", "server.js"]
Comando de build:
docker build -t minha-app:v1 .
Estratégias de otimização:
Multi-stage builds reduzem o tamanho final da imagem:
# Estágio 1: build
FROM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm install && npm run build
# Estágio 2: produção (imagem final)
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Aproveitamento de cache: o Docker reutiliza camadas em cache enquanto o Dockerfile não mudar. Para maximizar isso, coloque instruções que mudam com frequência (como COPY . .) no final do arquivo.
4. Push: publicando imagens para um registry
Após construir a imagem, use docker push para enviá-la a um registry. Antes, é necessário autenticar-se com docker login.
Nomeando corretamente com docker tag:
# Taggear imagem local para push
docker tag minha-app:v1 docker.io/meuusuario/minha-app:v1.2.3
# Enviar ao registry
docker push docker.io/meuusuario/minha-app:v1.2.3
A convenção de nomenclatura é: registry/usuario/repositorio:tag. Para Docker Hub, o registry pode ser omitido.
Políticas de versionamento semântico em produção:
v1.2.3— versão completa (major.minor.patch)v1.2— versão menor (atualizada com patches)v1— versão major (atualizada com minor e patches)latest— evitar em produção, usar apenas para desenvolvimento
Exemplo de pipeline de versionamento:
# Build com tag específica
docker build -t app:${CI_COMMIT_TAG} .
# Push com múltiplas tags
docker tag app:${CI_COMMIT_TAG} registry.example.com/app:${CI_COMMIT_TAG}
docker tag app:${CI_COMMIT_TAG} registry.example.com/app:latest
docker push registry.example.com/app:${CI_COMMIT_TAG}
docker push registry.example.com/app:latest
5. Gerenciamento local de imagens
Comandos essenciais para gerenciar imagens no cache local:
# Listar imagens
docker images
# Inspecionar detalhes (camadas, configurações)
docker inspect ubuntu:22.04
# Remover imagem específica
docker rmi ubuntu:22.04
# Remover todas as imagens não utilizadas
docker image prune -a
# Salvar imagem em arquivo tar (offline)
docker save -o minha-app.tar minha-app:v1
# Carregar imagem de arquivo tar
docker load -i minha-app.tar
O comando docker image prune é essencial para liberar espaço em disco, removendo imagens que não estão associadas a nenhum container.
6. Integração com Kubernetes: o ciclo de vida da imagem
No Kubernetes, o kubelet em cada nó é responsável por baixar as imagens dos containers. A política de pull é controlada pelo campo imagePullPolicy no Pod spec:
apiVersion: v1
kind: Pod
metadata:
name: meu-pod
spec:
containers:
- name: app
image: registry.example.com/app:v1.2.3
imagePullPolicy: IfNotPresent
Políticas disponíveis:
- Always — sempre baixa a imagem, mesmo se já existir localmente
- IfNotPresent — baixa apenas se não estiver em cache (padrão para tags que não são latest)
- Never — nunca baixa, usa apenas imagens locais
Atualização de imagens em Deployments:
# Rolling update com nova imagem
kubectl set image deployment/minha-app app=registry.example.com/app:v1.3.0
# Ou editando o deployment diretamente
kubectl edit deployment minha-app
Autenticação em registries privados no Kubernetes usa imagePullSecrets:
# Criar secret
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=usuario \
--docker-password=senha \
--docker-email=email@example.com
# Usar no Pod
apiVersion: v1
kind: Pod
spec:
imagePullSecrets:
- name: regcred
containers:
- name: app
image: registry.example.com/app:v1
7. Boas práticas e segurança no ciclo pull-build-push
Assinatura de imagens com Docker Content Trust (Notary) garante que a imagem não foi adulterada:
# Ativar trust
export DOCKER_CONTENT_TRUST=1
# Push assinado
docker push meuusuario/minha-app:v1
Scan de vulnerabilidades deve ser parte do pipeline:
# Docker Scout (integrado)
docker scout quickview minha-app:v1
# Trivy (ferramenta externa)
trivy image minha-app:v1
# Snyk
snyk container test minha-app:v1 --file=Dockerfile
Automação com CI/CD — exemplo com GitHub Actions:
name: Build, Push e Deploy
on:
push:
tags:
- 'v*'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Login no Registry
run: echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login registry.example.com -u ${{ secrets.REGISTRY_USER }} --password-stdin
- name: Build e Push
run: |
docker build -t app:${GITHUB_REF_NAME} .
docker tag app:${GITHUB_REF_NAME} registry.example.com/app:${GITHUB_REF_NAME}
docker push registry.example.com/app:${GITHUB_REF_NAME}
- name: Deploy no Kubernetes
run: |
kubectl set image deployment/app app=registry.example.com/app:${GITHUB_REF_NAME}
Boas práticas adicionais:
- Nunca usar latest em produção
- Sempre especificar versão exata ou digest
- Usar imagens base mínimas (Alpine, distroless)
- Escanear vulnerabilidades antes do push
- Implementar políticas de retenção no registry
Referências
- Documentação oficial do Docker: docker pull — Referência completa do comando
docker pullcom todas as opções e exemplos - Documentação oficial do Docker: docker build — Guia detalhado sobre construção de imagens, incluindo multi-stage builds e cache
- Documentação oficial do Docker: docker push — Referência do comando
docker pushcom instruções de autenticação e tagging - Kubernetes: Images — Documentação oficial sobre políticas de pull de imagens, imagePullSecrets e atualização de containers
- Docker Scout: Image Analysis — Ferramenta integrada da Docker para análise de vulnerabilidades e boas práticas de segurança em imagens
- Trivy: Vulnerability Scanner for Containers — Scanner open-source popular para detectar vulnerabilidades em imagens Docker
- GitHub Actions: Publish Docker Container — Tutorial oficial para automatizar build e push de imagens Docker em pipelines CI/CD