Dockerisieren Sie Ihren Flask-Blog: Kompletter Guide + Fly.io Deployment

Fred· Developer & Technical Writer9 min read

Zuletzt verifiziert: Oktober 2025 | Docker: 24.x | Flask: 3.0.0 | PostgreSQL: 15 | Python: 3.11

Deployment ist frustrierend. Sie bekommen Ihre Flask-App auf Ihrem Rechner perfekt zum Laufen, dann verbringen Sie Stunden damit, mit Server-Konfiguration, Python-Versionen und fehlenden Abhaengigkeiten zu kaempfen, wenn Sie versuchen, sie zu deployen. Docker behebt das, indem es alles, was Ihre App braucht, in einen Container packt, der ueberall gleich laeuft.

Dieser Guide zeigt Ihnen, wie Sie einen Flask-Blog containerisieren und auf Fly.io deployen. Der gesamte Prozess dauert etwa 15 Minuten, sobald Sie wissen, was Sie tun. Keine Server-Konfiguration, keine Abhaengigkeits-Hoelle, nur Ihre App, die in Produktion laeuft.

Fuer wen dieser Guide ist

Wenn Sie eine Flask-App haben, die lokal funktioniert, und Sie sie ohne die ueblichen Kopfschmerzen deployen moechten, ist dies fuer Sie. Vielleicht sind Sie es leid zu debuggen, warum etwas auf Ihrem Laptop funktioniert, aber in Produktion kaputtgeht. Vielleicht moechten Sie moderne Deployment-Praktiken nutzen, ohne Wochen damit zu verbringen, DevOps zu lernen.

Sie benoetigen grundlegende Python- und Flask-Kenntnisse. Wenn Sie schon einmal eine Flask-App gebaut haben, sind Sie bereit. Sie sollten mit der Kommandozeile vertraut sein, und Sie benoetigen Docker Desktop installiert. Das ist alles.

Am Ende haben Sie lokale Entwicklung, die der Produktion genau entspricht, Deployments, die Minuten statt Stunden dauern, und keine Python-Versionskonflikte mehr.

Warum Docker hilft

Docker hat einen schlechten Ruf dafuer, komplex zu sein, aber die Kernidee ist einfach: Es ist eine Box fuer Ihren Code. Ihre App geht in die Box mit allem, was sie zum Laufen braucht. Diese Box laeuft gleich auf Ihrem Laptop, auf CI-Servern und in Produktion.

Diese Konsistenz eliminiert ganze Kategorien von Bugs. Keine "aber es funktioniert auf meinem Rechner"-Diskussionen mehr. Kein Entdecken mehr, dass Produktion Python 3.8 hat, waehrend Sie auf 3.11 entwickelt haben. Keine fehlenden System-Bibliotheken mehr, die Sie vergessen haben zu dokumentieren.

Der echte Gewinn ist die Deployment-Geschwindigkeit. Sobald Sie ein funktionierendes Docker-Setup haben, wird Deployen trivial. Code pushen, Image bauen, deployen. Rollbacks sind genauso einfach: das vorherige Image erneut deployen und Sie sind in Sekunden wieder im Geschaeft.

Was wir bauen

Wir werden Ihren bestehenden Flask-Blog nehmen und ihn richtig containerisieren. Sie bekommen lokale Entwicklung mit Hot Reloading, damit Sie Aenderungen sofort sehen koennen. Wir verwenden PostgreSQL, weil SQLite nicht fuer Produktion gedacht ist, egal was jemand Ihnen sagt. Dann deployen wir das Ganze auf Fly.io, weil sie einen grosszuegigen Free Tier haben und Ihre Docker-Container unveraendert ausfuehren.

Ihre Flask-App vorbereiten

Zuerst korrigieren wir Ihre requirements.txt. Wenn Ihre nur "Flask" ohne Versionsnummer sagt, bitten Sie um Aerger. Hier ist, was Sie fuer Produktion brauchen:

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

Flasks eingebauter Server ist nur fuer Entwicklung. Gunicorn ist ein produktionsreifer WSGI-Server, der echten Traffic handhaben kann. Das psycopg2-binary-Paket laesst Sie mit PostgreSQL kommunizieren. Alles hat Versionsnummern, weil "Flask" ohne Version bedeutet, dass Sie moeglicherweise verschiedene Versionen in verschiedenen Umgebungen bekommen, was den ganzen Sinn verfehlt.

Erstellen Sie eine wsgi.py-Datei als Anwendungs-Einstiegspunkt:

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))
    )

Das host="0.0.0.0" ist wichtig. Es bedeutet "auf allen Netzwerkschnittstellen lauschen." Das Standard-127.0.0.1 lauscht nur lokal, was innerhalb eines Containers nicht funktioniert. Dieses winzige Detail hat vielen Entwicklern Stunden des Debuggens beschert.

Ihre config.py sollte Umgebungsvariablen fuer alles Sensible verwenden:

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

    # Manche Services nutzen postgres:// aber SQLAlchemy braucht postgresql://
    if SQLALCHEMY_DATABASE_URI.startswith("postgres://"):
        SQLALCHEMY_DATABASE_URI = SQLALCHEMY_DATABASE_URI.replace(
            "postgres://", "postgresql://", 1
        )

Hardcoden Sie niemals Secrets. Verwenden Sie Umgebungsvariablen. Ihr zukuenftiges Ich wird Ihnen danken, wenn Sie nicht versehentlich Ihr Produktions-Datenbankpasswort auf GitHub committen.

Ein Dockerfile schreiben, das funktioniert

Hier ist ein Dockerfile, das in Produktion funktioniert:

FROM python:3.11-slim as base

# Python-Pufferung kann Probleme in Containern verursachen
ENV PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    PIP_NO_CACHE_DIR=1 \
    PIP_DISABLE_PIP_VERSION_CHECK=1

WORKDIR /app

# System-Abhaengigkeiten installieren
RUN apt-get update && apt-get install -y \
    gcc \
    postgresql-client \
    && rm -rf /var/lib/apt/lists/*

# Requirements zuerst kopieren fuer besseres Caching
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

# Non-Root-Benutzer fuer Sicherheit erstellen
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"]

Die Reihenfolge ist hier wichtig. Das Kopieren von requirements.txt vor dem Kopieren Ihres Codes bedeutet, dass Docker die pip-Install-Schicht cachen kann. Wenn Sie Ihren Code aendern, aber nicht Ihre Abhaengigkeiten, verwendet Docker die gecachte Schicht mit all Ihren bereits installierten Paketen wieder. Das verwandelt einen 5-minuetigen Rebuild in einen 10-Sekunden-Rebuild.

Als Non-Root-Benutzer zu laufen ist eine Sicherheits-Best-Practice. Wenn jemand Ihre App kompromittiert, hat er keinen Root-Zugang zum Container.

Docker Compose fuer lokale Entwicklung

Docker Compose laesst Sie mehrere Container zusammen ausfuehren. Hier ist eine docker-compose.yml, die Ihre Flask-App mit PostgreSQL einrichtet:

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  # Ihren Code fuer Hot Reloading mounten
    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:

Das Volume-Mount (.:/app) bedeutet, dass Aenderungen an Ihrem Code sofort reflektiert werden, ohne den Container neu zu bauen. Das postgres_data-Volume stellt sicher, dass Ihre Datenbank persistiert, auch wenn Sie die Container stoppen.

Das depends_on kontrolliert nur die Startreihenfolge. Es wartet nicht darauf, dass PostgreSQL bereit ist, also koennte Ihre Flask-App beim ersten Start abstuerzen. Starten Sie sie einfach neu; das ist normal und passiert nur einmal.

Alles ausfuehren

Bauen Sie zuerst Ihr Image:

docker-compose build

Der erste Build dauert eine Weile, waehrend Base-Images heruntergeladen und Pakete installiert werden. Nachfolgende Builds sind dank Dockers Layer-Caching viel schneller.

Starten Sie die Datenbank:

docker-compose up -d db

Initialisieren Sie Ihre Datenbank-Migrationen, falls Sie das noch nicht getan haben:

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

Starten Sie jetzt alles:

docker-compose up

Besuchen Sie localhost:8080 und Ihr Blog sollte laufen. Wenn etwas nicht stimmt, werden Ihnen die Logs genau sagen, was. Docker zeigt Ihnen alles, was viel besser ist als mysteriöse Produktionsfehler ohne Fehlermeldungen.

Um nur Ihre App-Logs ohne PostgreSQL-Rauschen zu sehen, verwenden Sie docker-compose logs -f web.

Auf Fly.io deployen

Fly.io fuehrt Ihren tatsaechlichen Docker-Container aus, keine interpretierte Version davon. Sie haben einen Free Tier, der keine Kreditkarte erfordert, was erfrischend ist in 2025. Fuer einen tieferen Einblick in Fly.ios Free-Tier-Faehigkeiten und -Einschraenkungen, einschliesslich Performance-Vergleichen und Skalierungsstrategien, schauen Sie sich unseren kompletten Guide an.

Installieren Sie zuerst ihre CLI.

Auf Mac:

brew install flyctl

Auf Windows laden Sie den Installer von ihrer Website herunter oder verwenden Sie PowerShell:

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

Auf Linux:

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

Sie muessen moeglicherweise flyctl zu Ihrem PATH hinzufuegen. Der Installer wird Ihnen sagen, ob das noetig ist und Ihnen den genauen Befehl zeigen.

Starten Sie Ihre App mit flyctl launch. Wenn es fragt, geben Sie Ihrer App einen Namen (oder lassen Sie einen generieren), waehlen Sie eine Region nah bei Ihnen oder Ihren Nutzern, sagen Sie ja zu PostgreSQL (waehlen Sie Development fuer Free Tier), und sagen Sie nein zum sofortigen Deployen, weil wir zuerst Secrets setzen muessen.

Das erstellt eine fly.toml-Datei, die Ihr Deployment konfiguriert:

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

Die auto_stop_machines-Einstellung stoppt Ihre App, wenn niemand sie nutzt, was Ihnen hilft, innerhalb der Free-Tier-Grenzen zu bleiben. Sie startet automatisch wieder, wenn jemand besucht.

Setzen Sie Ihren Secret Key:

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

Deployen Sie Ihre App:

flyctl deploy

Das baut Ihr Docker-Image und deployed es. Dauert etwa 2 Minuten. Wenn es fertig ist, fuehren Sie Ihre Datenbank-Migrationen aus:

flyctl ssh console -C "flask db upgrade"

Oeffnen Sie Ihre deployede App mit flyctl open. Sie haben jetzt eine Produktions-Flask-App mit HTTPS, automatischen Neustarts und Datenbank-Backups. Keine Server-Konfiguration erforderlich.

Haeufige Probleme und Loesungen

Wenn Sie "Port already in use" sehen, haben Sie wahrscheinlich einen anderen Container laufen. Fuehren Sie docker-compose down aus, um alles zu stoppen, oder aendern Sie einfach den Port. Manchmal wird Docker Desktop verwirrt und ein Neustart behebt es.

Datenbankverbindungsfehler beim Start bedeuten normalerweise, dass Flask versucht, sich zu verbinden, bevor PostgreSQL bereit ist. Starten Sie einfach den Flask-Container neu. Sie koennten Retry-Logik zu Ihrem Datenbankverbindungscode hinzufuegen, aber fuer lokale Entwicklung funktioniert ein einfacher Neustart gut.

Wenn Docker Desktop sagt, es kann sich nicht mit dem Docker-Daemon verbinden, starten Sie Docker Desktop neu. Wenn das nicht funktioniert, starten Sie Ihren Computer neu. Docker Desktop hat Eigenheiten.

Der Fly.io Free Tier gibt Ihnen 256MB RAM. Wenn Ihre App mehr braucht, fuehren Sie flyctl scale memory 512 aus. Oder optimieren Sie Ihre App; Sie muessen wahrscheinlich nicht alles auf einmal in den Speicher laden.

Wenn Aenderungen lokal nicht angezeigt werden, ueberpruefen Sie das Volume-Mount in docker-compose.yml. In Produktion muessen Sie mit flyctl deploy neu bauen und deployen. Docker erkennt nicht automatisch Code-Aenderungen in Produktion.

Tipps, die Zeit sparen

Docker-Images koennen riesig werden. Verwenden Sie Slim-Base-Images und fuegen Sie eine .dockerignore-Datei hinzu:

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

Fuegen Sie ordentliches Logging zu Ihrer App hinzu. Wenn etwas in Produktion kaputtgeht, sind Logs Ihr einziges Fenster in das, was passiert ist:

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

Das Docker-Setup, das Sie gerade erstellt haben, ist dasselbe, das viele Unternehmen in Produktion verwenden. Das ist kein Spielzeug-Setup; es ist professionelles Deployment, das zufaellig kostenlos ist.

Geschafft

Sie haben erfolgreich eine Flask-Anwendung mit einer Produktions-Datenbank, lokalem Hot Reloading und Ein-Befehl-Deployment containerisiert. Ihre Entwicklungsumgebung entspricht jetzt genau der Produktion und eliminiert eine ganze Klasse von Deployment-Bugs.

Das ist derselbe Workflow, den professionelle Teams verwenden. Dasselbe Docker, derselbe Deployment-Prozess, dasselbe alles. Die Luecke zwischen Hobby-Projekten und Produktionsanwendungen ist kleiner, als die meisten Leute denken. Es geht meistens nur darum, die richtigen Tools zu kennen.

Bauen Sie zuerst Ihre Flask-Anwendung

Haben Sie noch keinen Flask-Blog zum Dockerisieren? Beginnen Sie hier:

Jedes Tutorial enthaelt Schritt-fuer-Schritt-KI-Prompts, die Sie durch den Bau produktionsreifer Flask-Anwendungen fuehren. Sobald Sie Ihre App gebaut haben, kommen Sie zu diesem Guide zurueck, um sie zu dockerisieren und zu deployen.

Jetzt gehen Sie los und bauen Sie etwas Cooles.

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 →