Voltar ao Glossario
Glossario Python

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.