Back to Course|Build a Production REST API: From Zero to Deployed with FastAPI
Lab

Initialize the TaskFlow Project

30 min
Intermediate
Unlimited free attempts

Instructions

In this lab, you'll set up the complete foundation for the TaskFlow API. By the end, you'll have a running Docker Compose stack with FastAPI, PostgreSQL 18, and Redis — all connected and verified via a health check endpoint.

Step 1: Create the Project Directory Structure

Create the following directory structure for the TaskFlow project:

mkdir -p taskflow/app/{api/v1,models,schemas,core,tests}
cd taskflow

Create __init__.py files in every Python package directory:

touch app/__init__.py
touch app/api/__init__.py
touch app/api/v1/__init__.py
touch app/models/__init__.py
touch app/schemas/__init__.py
touch app/core/__init__.py
touch app/tests/__init__.py

Step 2: Create the Requirements File

Create requirements.txt with pinned dependencies:

# Web framework
fastapi>=0.128.0,<0.129.0
uvicorn[standard]>=0.34.0,<0.35.0

# Database
sqlalchemy>=2.0.46,<2.1.0
psycopg2-binary>=2.9.10,<3.0.0
alembic>=1.18.4,<1.19.0

# Validation & Settings
pydantic>=2.12.0,<3.0.0
pydantic-settings>=2.8.0,<3.0.0

# Authentication
python-jose[cryptography]>=3.3.0,<4.0.0
passlib[bcrypt]>=1.7.4,<2.0.0

# Caching
redis>=7.1.1,<8.0.0

# Testing
pytest>=9.0.2,<10.0.0
pytest-asyncio>=0.25.0,<1.0.0
httpx>=0.28.0,<1.0.0

# Utilities
python-dotenv>=1.0.1,<2.0.0
python-multipart>=0.0.20,<1.0.0

Step 3: Create the Environment Configuration

Create a .env file at the project root:

# Application
APP_NAME=TaskFlow
APP_VERSION=0.1.0
DEBUG=true

# Database
POSTGRES_USER=taskflow
POSTGRES_PASSWORD=taskflow_secret_2026
POSTGRES_DB=taskflow
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
DATABASE_URL=postgresql://taskflow:taskflow_secret_2026@postgres:5432/taskflow

# Redis
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_URL=redis://redis:6379/0

# JWT (generate your own secret in production!)
JWT_SECRET_KEY=dev-secret-key-change-in-production
JWT_ALGORITHM=HS256
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=30

Step 4: Create the Configuration Module

Create app/core/config.py:

from pydantic_settings import BaseSettings


class Settings(BaseSettings):
    app_name: str = "TaskFlow"
    app_version: str = "0.1.0"
    debug: bool = False

    # Database
    database_url: str = "postgresql://taskflow:taskflow_secret_2026@postgres:5432/taskflow"

    # Redis
    redis_url: str = "redis://redis:6379/0"

    # JWT
    jwt_secret_key: str = "dev-secret-key-change-in-production"
    jwt_algorithm: str = "HS256"
    jwt_access_token_expire_minutes: int = 30

    class Config:
        env_file = ".env"
        env_file_encoding = "utf-8"


settings = Settings()

Step 5: Create the FastAPI Application

Create app/main.py:

from fastapi import FastAPI
from app.core.config import settings

app = FastAPI(
    title=settings.app_name,
    version=settings.app_version,
    docs_url="/docs",
    redoc_url="/redoc",
)


@app.get("/health")
async def health_check():
    return {
        "status": "healthy",
        "app": settings.app_name,
        "version": settings.app_version,
    }

Step 6: Create the Dockerfile

Create a Dockerfile with a multi-stage build:

# ---- Stage 1: Builder ----
FROM python:3.12-slim AS builder

WORKDIR /build

COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt

# ---- Stage 2: Runtime ----
FROM python:3.12-slim AS runtime

WORKDIR /app

# Copy installed packages from builder
COPY --from=builder /install /usr/local

# Copy application code
COPY . .

EXPOSE 8000

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]

Step 7: Create Docker Compose Configuration

Create docker-compose.yml:

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8000:8000"
    volumes:
      - .:/app
    env_file:
      - .env
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    restart: unless-stopped

  postgres:
    image: postgres:18
    environment:
      POSTGRES_USER: ${POSTGRES_USER:-taskflow}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-taskflow_secret_2026}
      POSTGRES_DB: ${POSTGRES_DB:-taskflow}
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U taskflow -d taskflow"]
      interval: 5s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 5s
      retries: 5
    restart: unless-stopped

volumes:
  postgres_data:
  redis_data:

Step 8: Build and Run

Start the entire stack:

docker compose up --build -d

Verify the health check:

curl http://localhost:8000/health

You should see:

{
  "status": "healthy",
  "app": "TaskFlow",
  "version": "0.1.0"
}

Check the auto-generated API docs by visiting http://localhost:8000/docs in your browser.

Step 9: Verify All Services

Check that all containers are running:

docker compose ps

All three services (app, postgres, redis) should show status Up (healthy).

What to Submit

The editor already has 6 file sections pre-filled with TODO comments. Replace each TODO with your actual code. The AI grader will evaluate each file section against the rubric.

Grading Rubric

Project structure is correct with all required directories (app/api/v1, app/models, app/schemas, app/core, app/tests) and __init__.py files15 points
requirements.txt includes all required packages (FastAPI, SQLAlchemy, Alembic, Pydantic, Redis, pytest, uvicorn) with properly pinned version ranges15 points
FastAPI application (app/main.py) is properly configured with a working /health endpoint that returns JSON with status, app name, and version. Configuration module (app/core/config.py) uses pydantic-settings to load from .env25 points
Dockerfile uses multi-stage build (builder + runtime stages), starts from python:3.12-slim, copies only installed packages to the runtime stage, and exposes port 800020 points
docker-compose.yml defines three services (app, postgres with image postgres:18, redis with image redis:7-alpine) with health checks, named volumes for data persistence, depends_on with health conditions, and proper environment variable configuration25 points

Checklist

0/6

Your Solution

Unlimited free attempts