Docker: O que É e Como Funciona | Python Brasil
Aprenda a usar Docker com Python: containers, Dockerfile, docker-compose, imagens otimizadas e boas praticas para empacotar aplicacoes Python.
O que e Docker?
Docker e uma plataforma de containerizacao que permite empacotar uma aplicacao junto com todas as suas dependencias em um container — uma unidade leve, portatil e isolada que funciona de forma identica em qualquer ambiente. Para desenvolvedores Python, Docker resolve o classico problema “funciona na minha maquina” ao garantir que a aplicacao roda com a mesma versao de Python, as mesmas bibliotecas e as mesmas configuracoes em desenvolvimento, testes e producao.
Containers sao diferentes de maquinas virtuais: eles compartilham o kernel do sistema operacional hospedeiro, tornando-os muito mais leves e rapidos para iniciar.
Dockerfile para Python
O Dockerfile e o arquivo que define como construir a imagem do container.
# Dockerfile
FROM python:3.12-slim
# Evitar criacao de arquivos .pyc e buffer de saida
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
# Diretorio de trabalho
WORKDIR /app
# Copiar dependencias primeiro (aproveita cache do Docker)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copiar codigo da aplicacao
COPY . .
# Expor porta
EXPOSE 8000
# Comando para iniciar a aplicacao
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Construindo e Executando
# Construir a imagem
# docker build -t minha-api .
# Executar o container
# docker run -d -p 8000:8000 --name api minha-api
# Ver containers em execucao
# docker ps
# Ver logs
# docker logs api
# Parar e remover
# docker stop api
# docker rm api
Docker Compose
O docker-compose.yml permite definir e orquestrar multiplos containers.
# docker-compose.yml
# version: '3.8' (obsoleto em versoes recentes)
# services:
# web:
# build: .
# ports:
# - "8000:8000"
# environment:
# - DATABASE_URL=postgresql://user:pass@db:5432/app
# - REDIS_URL=redis://redis:6379/0
# depends_on:
# - db
# - redis
# volumes:
# - .:/app
#
# db:
# image: postgres:16
# environment:
# POSTGRES_USER: user
# POSTGRES_PASSWORD: pass
# POSTGRES_DB: app
# volumes:
# - postgres_data:/var/lib/postgresql/data
#
# redis:
# image: redis:7-alpine
#
# volumes:
# postgres_data:
Otimizacao de Imagens
# Dockerfile otimizado com multi-stage build
# Estagio 1: Build
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
# Estagio 2: Runtime
FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /install /usr/local
COPY . .
# Criar usuario nao-root
RUN adduser --disabled-password --no-create-home appuser
USER appuser
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
.dockerignore
# .dockerignore
# Funciona como .gitignore para o contexto de build do Docker
# __pycache__
# *.pyc
# *.pyo
# .git
# .gitignore
# .env
# .venv
# venv/
# *.md
# tests/
# .pytest_cache
# .mypy_cache
Docker com Poetry
# Dockerfile com Poetry
FROM python:3.12-slim
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /app
# Instalar Poetry
RUN pip install poetry
RUN poetry config virtualenvs.create false
# Copiar apenas arquivos de dependencias
COPY pyproject.toml poetry.lock ./
RUN poetry install --no-dev --no-interaction --no-ansi
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Script Python para Interagir com Docker
# Exemplo: health check em Python
import urllib.request
import sys
def health_check():
"""Verifica se a aplicacao esta respondendo."""
try:
response = urllib.request.urlopen('http://localhost:8000/health')
if response.status == 200:
sys.exit(0)
except Exception:
pass
sys.exit(1)
if __name__ == '__main__':
health_check()
Adicionar no Dockerfile:
# HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
# CMD python health_check.py
Desenvolvimento Local com Docker
# docker-compose.dev.yml para desenvolvimento
# services:
# web:
# build:
# context: .
# dockerfile: Dockerfile.dev
# volumes:
# - .:/app # monta codigo local para hot-reload
# ports:
# - "8000:8000"
# command: uvicorn main:app --host 0.0.0.0 --port 8000 --reload
# environment:
# - DEBUG=true
Erros Comuns
O erro mais frequente e copiar todo o codigo antes de instalar dependencias, invalidando o cache do Docker a cada mudanca no codigo. Sempre copie requirements.txt e instale dependencias antes de copiar o codigo fonte. Outro erro e executar a aplicacao como root dentro do container, o que e um risco de seguranca. Tambem e comum esquecer o .dockerignore, incluindo arquivos desnecessarios como .git, __pycache__ e ambientes virtuais na imagem, aumentando drasticamente seu tamanho. Usar imagens base pesadas como python:3.12 em vez de python:3.12-slim tambem gera imagens muito maiores.
Boas Praticas
Use imagens slim ou alpine como base. Aproveite o cache de camadas copiando dependencias antes do codigo. Crie um usuario nao-root para executar a aplicacao. Use multi-stage builds para reduzir o tamanho da imagem final. Configure variaves de ambiente para configuracao, nunca codifique segredos no Dockerfile. Use health checks para monitoramento. Mantenha um .dockerignore completo.
Quando Usar
Docker e recomendado para qualquer projeto Python que precise de reproducibilidade entre ambientes, integracao com servicos externos como bancos de dados e caches, deploy em plataformas de nuvem, ou trabalho em equipe onde cada membro precisa do mesmo ambiente de desenvolvimento.