32 Crash Course: Dev Container for Python + PostgreSQL
Let’s build a complete dev environment step-by-step.
32.1 Prerequisites
Before starting, ensure you have:
┌──────────────────────────────────────┐
│ ✓ Docker Desktop (running) │
│ ✓ VS Code │
│ ✓ "Dev Containers" extension │
└──────────────────────────────────────┘
Install the extension:
VS Code → Extensions → Search "Dev Containers" → Install
32.2 Final Project Structure
my-python-app/
├── .devcontainer/
│ ├── devcontainer.json # Main config
│ └── docker-compose.yml # Multi-container setup
├── app/
│ └── main.py
├── requirements.txt
└── README.md
32.3 Step 1: Create Project Folder
mkdir my-python-app
cd my-python-app
mkdir -p .devcontainer app32.4 Step 2: Create devcontainer.json
This is the brain of your dev container setup.
.devcontainer/devcontainer.json
{
"name": "Python + PostgreSQL",
// Use docker-compose for multi-container
"dockerComposeFile": "docker-compose.yml",
// Which service is your dev environment
"service": "app",
// Where your code lives inside container
"workspaceFolder": "/workspace",
// VS Code customizations
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-python.pylint",
"mtxr.sqltools",
"mtxr.sqltools-driver-pg"
],
"settings": {
"python.defaultInterpreterPath": "/usr/local/bin/python"
}
}
},
// Run after container is created
"postCreateCommand": "pip install -r requirements.txt",
// Features to add
"features": {
"ghcr.io/devcontainers/features/git:1": {}
}
}32.5 Step 3: Create docker-compose.yml
This defines two containers: your app + PostgreSQL.
.devcontainer/docker-compose.yml
services:
app:
image: mcr.microsoft.com/devcontainers/python:3.11
volumes:
# Mount your project code
- ..:/workspace:cached
# Keep container running
command: sleep infinity
# Connect to database network
depends_on:
- db
environment:
DATABASE_URL: postgresql://postgres:postgres@db:5432/devdb
db:
image: postgres:15
restart: unless-stopped
volumes:
# Persist database data
- postgres-data:/var/lib/postgresql/data
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: devdb
ports:
- "5432:5432"
volumes:
postgres-data:32.5.1 Architecture Diagram
┌─────────────────────────────────────────────────────────────┐
│ Docker Network (auto-created) │
│ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ app (Python) │ │ db (PostgreSQL) │ │
│ │ │ │ │ │
│ │ • Your code here │ ───► │ • Port 5432 │ │
│ │ • VS Code connects │ │ • Data persisted │ │
│ │ │ │ │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │ │
│ │ mounted │
│ ▼ │
│ /workspace ◄──── Your Mac's project folder │
└─────────────────────────────────────────────────────────────┘
32.6 Step 4: Create App Files
requirements.txt
psycopg2-binary
sqlalchemy
fastapi
uvicorn
app/main.py
import os
from sqlalchemy import create_engine, text
DATABASE_URL = os.getenv("DATABASE_URL")
def test_connection():
engine = create_engine(DATABASE_URL)
with engine.connect() as conn:
result = conn.execute(text("SELECT version()"))
version = result.fetchone()[0]
print(f"Connected to: {version}")
if __name__ == "__main__":
test_connection()32.7 Step 5: Open in Dev Container
32.7.1 Method 1: Command Palette
1. Open VS Code
2. File → Open Folder → select "my-python-app"
3. Cmd + Shift + P → "Dev Containers: Reopen in Container"
32.7.2 Method 2: Popup
VS Code will detect .devcontainer and show:
┌────────────────────────────────────────┐
│ Folder contains a Dev Container │
│ configuration file. │
│ │
│ [Reopen in Container] [Cancel] │
└────────────────────────────────────────┘
32.8 Step 6: Wait for Build
First time takes a few minutes:
Building...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100%
✓ Pulling images
✓ Creating containers
✓ Installing extensions
✓ Running postCreateCommand (pip install)
✓ Done!
32.9 Step 7: Test It!
Open terminal in VS Code (now inside container):
# Check Python
python --version
# Python 3.11.x
# Test database connection
python app/main.py
# Connected to: PostgreSQL 15.x ...
# You can also connect directly
psql postgresql://postgres:postgres@db:5432/devdb32.10 Quick Reference Card
32.10.1 Common Commands (inside VS Code)
| Action | Command |
|---|---|
| Rebuild container | Cmd+Shift+P → “Rebuild Container” |
| Reopen locally | Cmd+Shift+P → “Reopen Locally” |
| View logs | Cmd+Shift+P → “Show Log” |
| Attach terminal | Ctrl+` |
32.10.2 Environment Variables Access
import os
# These are set in docker-compose.yml
db_url = os.getenv("DATABASE_URL")32.10.3 Connect to DB from VS Code
SQLTools extension will auto-detect. Or manually:
Host: db
Port: 5432
User: postgres
Password: postgres
Database: devdb
32.11 Bonus: Adding More Services
Need Redis? Add to docker-compose.yml:
services:
app:
# ... existing config ...
depends_on:
- db
- redis # Add this
db:
# ... existing config ...
redis:
image: redis:7
ports:
- "6379:6379"32.12 Troubleshooting
| Problem | Solution |
|---|---|
| Container won’t start | Check Docker Desktop is running |
| Can’t connect to DB | Wait a few seconds for PostgreSQL to initialize |
| Changes not reflected | Rebuild container (Cmd+Shift+P → Rebuild) |
| Slow performance | Ensure :cached on volume mount |
32.13 Summary Cheatsheet
.devcontainer/
├── devcontainer.json ← "What" (extensions, settings, commands)
└── docker-compose.yml ← "How" (services, networks, volumes)
Key devcontainer.json fields:
• service → Which container to develop in
• workspaceFolder → Where code is mounted
• postCreateCommand → Setup script
• customizations → VS Code extensions/settings
Key docker-compose.yml patterns:
• volumes → Mount code & persist data
• environment → Pass config to containers
• depends_on → Service startup order