Dockerize Seu Blog Flask: Guia Completo + Deploy no Fly.io

Fred· Developer & Technical Writer10 min read

Ultima verificacao: Outubro 2025 | Docker: 24.x | Flask: 3.0.0 | PostgreSQL: 15 | Python: 3.11

Deploy e frustrante. Voce consegue que seu app Flask funcione perfeitamente na sua maquina, depois passa horas lutando com configuracao de servidor, versoes de Python e dependencias faltando quando tenta fazer deploy. Docker resolve isso empacotando tudo que seu app precisa em um container que roda da mesma forma em todo lugar.

Este guia mostra como containerizar um blog Flask e fazer deploy no Fly.io. Todo o processo leva cerca de 15 minutos quando voce sabe o que esta fazendo. Sem configuracao de servidor, sem inferno de dependencias, apenas seu app rodando em producao.

Para Quem e Este Guia

Se voce tem um app Flask que funciona localmente e quer fazer deploy sem as dores de cabeca usuais, isso e para voce. Talvez voce esteja cansado de debugar por que algo funciona no seu laptop mas quebra em producao. Talvez voce queira usar praticas modernas de deployment sem gastar semanas aprendendo DevOps.

Voce vai precisar de conhecimento basico de Python e Flask. Se voce ja construiu um app Flask antes, esta pronto. Voce deve estar confortavel com a linha de comando, e vai precisar do Docker Desktop instalado. So isso.

No final, voce tera desenvolvimento local que corresponde exatamente a producao, deploys que levam minutos em vez de horas, e sem mais conflitos de versao Python.

Por Que Docker Ajuda

Docker tem ma fama por ser complexo, mas a ideia central e simples: e uma caixa para seu codigo. Seu app vai na caixa com tudo que precisa para rodar. Essa caixa roda da mesma forma no seu laptop, em servidores de CI e em producao.

Essa consistencia elimina categorias inteiras de bugs. Sem mais discussoes de "mas funciona na minha maquina". Sem mais descobrir que producao tem Python 3.8 quando voce desenvolveu em 3.11. Sem mais bibliotecas de sistema faltando que voce esqueceu de documentar.

A verdadeira vitoria e a velocidade de deploy. Uma vez que voce tem uma configuracao Docker funcionando, fazer deploy se torna trivial. Push do seu codigo, build da imagem, deploy. Rollbacks sao igualmente faceis: redeploy da imagem anterior e voce volta ao ar em segundos.

O Que Estamos Construindo

Vamos pegar seu blog Flask existente e containeriza-lo corretamente. Voce tera desenvolvimento local com hot reloading para ver mudancas instantaneamente. Usaremos PostgreSQL porque SQLite nao foi feito para producao, nao importa o que ninguem te diga. Depois faremos deploy de tudo no Fly.io porque eles tem um nivel gratuito generoso e rodam seus containers Docker como estao.

Preparando Seu App Flask

Primeiro, vamos arrumar seu requirements.txt. Se o seu apenas diz "Flask" sem numero de versao, voce esta pedindo por problemas. Aqui esta o que voce precisa para producao:

Flask==3.0.0
Flask-SQLAlchemy==3.1.1
Flask-Migrate==4.0.5
psycopg2-binary==2.9.9
python-dotenv==1.0.0
gunicorn==21.2.0

O servidor embutido do Flask e apenas para desenvolvimento. Gunicorn e um servidor WSGI pronto para producao que pode lidar com trafego real. O pacote psycopg2-binary permite comunicar com PostgreSQL. Tudo tem numeros de versao porque "Flask" sem versao significa que voce pode pegar versoes diferentes em ambientes diferentes, o que derrota todo o proposito.

Crie um arquivo wsgi.py como ponto de entrada da sua aplicacao:

from app import create_app
import os

app = create_app()

if __name__ == "__main__":
    app.run(
        host="0.0.0.0",
        port=int(os.environ.get("PORT", 8080))
    )

Aquele host="0.0.0.0" e importante. Significa "escutar em todas as interfaces de rede." O padrao 127.0.0.1 so escuta localmente, o que nao funciona dentro de um container. Esse detalhe minusculo causou horas de debugging para muitos desenvolvedores.

Seu config.py deve usar variaveis de ambiente para qualquer coisa sensivel:

import os
from dotenv import load_dotenv

basedir = os.path.abspath(os.path.dirname(__file__))
load_dotenv(os.path.join(basedir, '.env'))

class Config:
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'dev-secret-key-change-in-production'

    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
        f'sqlite:///{os.path.join(basedir, "app.db")}'

    SQLALCHEMY_TRACK_MODIFICATIONS = False

    # Alguns servicos usam postgres:// mas SQLAlchemy precisa postgresql://
    if SQLALCHEMY_DATABASE_URI.startswith("postgres://"):
        SQLALCHEMY_DATABASE_URI = SQLALCHEMY_DATABASE_URI.replace(
            "postgres://", "postgresql://", 1
        )

Nunca hardcode secrets. Use variaveis de ambiente. Seu eu futuro vai agradecer quando voce nao commitar acidentalmente sua senha de banco de producao no GitHub.

Escrevendo um Dockerfile que Funciona

Aqui esta um Dockerfile que funciona em producao:

FROM python:3.11-slim as base

# Buffer do Python pode causar problemas em containers
ENV PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    PIP_NO_CACHE_DIR=1 \
    PIP_DISABLE_PIP_VERSION_CHECK=1

WORKDIR /app

# Instalar dependencias do sistema
RUN apt-get update && apt-get install -y \
    gcc \
    postgresql-client \
    && rm -rf /var/lib/apt/lists/*

# Copiar requirements primeiro para melhor cache
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

# Criar usuario nao-root para seguranca
RUN useradd -m -u 1000 flaskuser && \
    chown -R flaskuser:flaskuser /app
USER flaskuser

EXPOSE 8080

CMD ["gunicorn", "--bind", "0.0.0.0:8080", "--workers", "2", "wsgi:app"]

A ordem importa aqui. Copiar requirements.txt antes de copiar seu codigo significa que Docker pode cachear a camada de pip install. Quando voce muda seu codigo mas nao suas dependencias, Docker reutiliza a camada cacheada com todos seus pacotes ja instalados. Isso transforma um rebuild de 5 minutos em um de 10 segundos.

Rodar como usuario nao-root e uma melhor pratica de seguranca. Se alguem comprometer seu app, nao tera acesso root ao container.

Docker Compose para Desenvolvimento Local

Docker Compose permite rodar multiplos containers juntos. Aqui esta um docker-compose.yml que configura seu app Flask com PostgreSQL:

version: '3.8'

services:
  web:
    build: .
    ports:
      - "8080:8080"
    environment:
      - DATABASE_URL=postgresql://postgres:postgres@db:5432/flask_blog
      - SECRET_KEY=dev-secret-key
      - FLASK_ENV=development
    volumes:
      - .:/app  # Monta seu codigo para hot reloading
    depends_on:
      - db
    command: flask run --host=0.0.0.0 --port=8080 --reload

  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=flask_blog
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

A montagem de volume (.:/app) significa que mudancas no seu codigo sao refletidas imediatamente sem reconstruir o container. O volume postgres_data garante que seu banco persiste mesmo quando voce para os containers.

Aquele depends_on apenas controla ordem de inicializacao. Ele nao espera PostgreSQL estar pronto, entao seu app Flask pode crashar na primeira inicializacao. Apenas reinicie; isso e normal e so acontece uma vez.

Rodando Tudo

Build sua imagem primeiro:

docker-compose build

O primeiro build demora um pouco pois baixa imagens base e instala pacotes. Builds subsequentes sao muito mais rapidos gracas ao cache de camadas do Docker.

Inicie o banco de dados:

docker-compose up -d db

Inicialize suas migrations de banco se ainda nao fez:

docker-compose run --rm web flask db init
docker-compose run --rm web flask db migrate -m "Initial migration"
docker-compose run --rm web flask db upgrade

Agora inicie tudo:

docker-compose up

Visite localhost:8080 e seu blog deve estar rodando. Se algo estiver errado, os logs vao te dizer exatamente o que. Docker mostra tudo, o que e muito melhor do que falhas misteriosas em producao sem mensagens de erro.

Para ver apenas os logs do seu app sem o barulho do PostgreSQL, use docker-compose logs -f web.

Fazendo Deploy no Fly.io

Fly.io roda seu container Docker real, nao alguma versao interpretada dele. Eles tem um nivel gratuito que nao requer cartao de credito, o que e revigorante em 2025. Para uma analise mais profunda das capacidades e limitacoes do nivel gratuito do Fly.io, incluindo comparacoes de performance e estrategias de escala, confira nosso guia completo.

Instale a CLI deles primeiro.

No Mac:

brew install flyctl

No Windows, baixe o instalador do site deles ou use PowerShell:

pwsh -Command "iwr https://fly.io/install.ps1 -useb | iex"

No Linux:

curl -L https://fly.io/install.sh | sh

Voce pode precisar adicionar flyctl ao seu PATH. O instalador vai te dizer se isso for necessario e mostrar o comando exato para rodar.

Lance seu app com flyctl launch. Quando perguntar, de um nome ao seu app (ou deixe gerar um), escolha uma regiao proxima de voce ou seus usuarios, diga sim ao PostgreSQL (escolha development para o nivel gratuito), e diga nao para fazer deploy imediatamente porque precisamos configurar secrets primeiro.

Isso cria um arquivo fly.toml que configura seu deployment:

app = "your-app-name"
primary_region = "iad"

[build]

[env]
  PORT = "8080"

[http_service]
  internal_port = 8080
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 0

[[vm]]
  cpu_kind = "shared"
  cpus = 1
  memory_mb = 256

A configuracao auto_stop_machines para seu app quando ninguem esta usando, o que ajuda voce a ficar dentro dos limites do nivel gratuito. Ele inicia novamente automaticamente quando alguem visita.

Configure sua secret key:

flyctl secrets set SECRET_KEY=$(openssl rand -hex 32)

Faca deploy do seu app:

flyctl deploy

Isso build sua imagem Docker e faz deploy. Leva cerca de 2 minutos. Quando terminar, rode suas migrations de banco:

flyctl ssh console -C "flask db upgrade"

Abra seu app deployado com flyctl open. Voce agora tem um app Flask em producao com HTTPS, restarts automaticos e backups de banco de dados. Nenhuma configuracao de servidor necessaria.

Problemas Comuns e Solucoes

Quando voce ve "Port already in use", provavelmente tem outro container rodando. Rode docker-compose down para parar tudo, ou apenas mude a porta. As vezes Docker Desktop fica confuso e um restart resolve.

Erros de conexao de banco na inicializacao geralmente significam que Flask esta tentando conectar antes do PostgreSQL estar pronto. Apenas reinicie o container Flask. Voce poderia adicionar logica de retry ao seu codigo de conexao de banco, mas para desenvolvimento local, um simples restart funciona bem.

Se Docker Desktop diz que nao consegue conectar ao daemon Docker, reinicie Docker Desktop. Se isso nao funcionar, reinicie seu computador. Docker Desktop tem seus quirks.

O nivel gratuito do Fly.io da 256MB de RAM. Se seu app precisar de mais, rode flyctl scale memory 512. Ou otimize seu app; voce provavelmente nao precisa carregar tudo na memoria de uma vez.

Quando mudancas nao estao aparecendo localmente, verifique aquela montagem de volume no docker-compose.yml. Em producao, voce precisa rebuildar e fazer deploy com flyctl deploy. Docker nao detecta automaticamente mudancas de codigo em producao.

Dicas que Economizam Tempo

Imagens Docker podem ficar enormes. Use imagens base slim e adicione um arquivo .dockerignore:

__pycache__
*.pyc
.git
.env
venv/
node_modules/
*.db
.DS_Store

Adicione logging adequado ao seu app. Quando algo quebra em producao, logs sao sua unica janela para o que aconteceu:

import logging
logging.basicConfig(level=logging.INFO)
app.logger.info('App starting up')

A configuracao Docker que voce acabou de criar e a mesma que muitas empresas usam em producao. Isso nao e uma configuracao de brinquedo; e deployment de nivel profissional que por acaso e gratis.

Voce Conseguiu

Voce containerizou com sucesso uma aplicacao Flask com um banco de dados de producao, hot reloading local e deploy com um comando. Seu ambiente de desenvolvimento agora corresponde a producao exatamente, eliminando uma classe inteira de bugs de deployment.

Esse e o mesmo fluxo de trabalho que equipes profissionais usam. O mesmo Docker, o mesmo processo de deployment, o mesmo tudo. A lacuna entre projetos hobby e aplicacoes de producao e menor do que a maioria das pessoas pensa. E principalmente apenas saber as ferramentas certas.

Construa Sua Aplicacao Flask Primeiro

Ainda nao tem um blog Flask para dockerizar? Comece aqui:

Cada tutorial inclui prompts de IA passo a passo para guia-lo na construcao de aplicacoes Flask prontas para producao. Depois de construir seu app, volte a este guia para dockerizar e fazer deploy.

Agora va construir algo legal.

Fred

Fred

AUTHOR

Full-stack developer with 10+ years building production applications. I've containerized dozens of production applications and learned these lessons the hard way.

Need a developer who gets it?

POC builds, vibe-coded fixes, and real engineering. Let's talk.

Hire Me →