From a02839bbc6ca1a84f3af19d5ae08fa91e91c8d5a Mon Sep 17 00:00:00 2001 From: chriscarrollsmith Date: Sat, 29 Nov 2025 10:56:10 -0500 Subject: [PATCH 1/5] Devcontainer config for developing in codespaces --- .devcontainer/devcontainer.json | 36 +++++++++++++++++++++++++ .devcontainer/docker-compose.yml | 27 +++++++++++++++++++ .devcontainer/ensure-env.sh | 17 ++++++++++++ .devcontainer/init-env.sh | 46 ++++++++++++++++++++++++++++++++ .gitignore | 1 - 5 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 .devcontainer/devcontainer.json create mode 100644 .devcontainer/docker-compose.yml create mode 100644 .devcontainer/ensure-env.sh create mode 100644 .devcontainer/init-env.sh diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..9bb9a97 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,36 @@ +{ + "name": "FastAPI Jinja2 Postgres WebApp", + "workspaceFolder": "/workspaces/fastapi-jinja2-postgres-webapp", + + // Ensure .env exists before Docker Compose processes env_file entries + "initializeCommand": "bash .devcontainer/ensure-env.sh", + + // Start the Postgres sidecar using the existing compose file + "dockerComposeFile": [ + "../docker-compose.yml", + "docker-compose.yml" + ], + "service": "app", + "runServices": ["db"], + "shutdownAction": "stopCompose", + + // Forward common app/db ports + "forwardPorts": [8000, 5432], + "portsAttributes": { + "8000": { "label": "FastAPI", "onAutoForward": "openBrowser" }, + "5432": { "label": "PostgreSQL" } + }, + + // Prepare env, install uv, and sync deps + "postCreateCommand": "bash .devcontainer/init-env.sh && curl -LsSf https://astral.sh/uv/install.sh | sh && ~/.local/bin/uv sync", + + "customizations": { + "vscode": { + "extensions": [ + "ms-python.python", + "ms-python.vscode-pylance" + ] + } + } +} + diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml new file mode 100644 index 0000000..a2528dc --- /dev/null +++ b/.devcontainer/docker-compose.yml @@ -0,0 +1,27 @@ +services: + app: + image: mcr.microsoft.com/devcontainers/python:3.13-bookworm + container_name: fastapi-jinja2-postgres-webapp-app + volumes: + - ..:/workspaces/fastapi-jinja2-postgres-webapp:cached + working_dir: /workspaces/fastapi-jinja2-postgres-webapp + depends_on: + - db + env_file: + - ../.env + command: sleep infinity + + # Override/augment settings for the db service defined in the root compose file + db: + # Avoid requiring a project-level .env during compose evaluation + env_file: [] + environment: + POSTGRES_USER: ${DB_USER:-postgres} + POSTGRES_PASSWORD: ${DB_PASSWORD:-postgres} + POSTGRES_DB: ${DB_NAME:-fastapi-jinja2-postgres-webapp} + ports: + - "5432:5432" + +# Note: The 'db' service is defined in the repository root docker-compose.yml. +# This file is merged with that one via devcontainer.json dockerComposeFile array. + diff --git a/.devcontainer/ensure-env.sh b/.devcontainer/ensure-env.sh new file mode 100644 index 0000000..9acc18b --- /dev/null +++ b/.devcontainer/ensure-env.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Run from repo root +cd "$(dirname "${BASH_SOURCE[0]}")/.." + +# Ensure a .env exists BEFORE docker compose evaluates env_file +if [ ! -f ".env" ]; then + if [ -f ".env.example" ]; then + cp .env.example .env || true + else + touch .env + fi +fi + +echo ".env ensured for compose evaluation." + diff --git a/.devcontainer/init-env.sh b/.devcontainer/init-env.sh new file mode 100644 index 0000000..a12f4cd --- /dev/null +++ b/.devcontainer/init-env.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Run from repo root +cd "$(dirname "${BASH_SOURCE[0]}")/.." + +# Ensure a working .env exists +if [ ! -f ".env" ]; then + if [ -f ".env.example" ]; then + cp .env.example .env || true + else + touch .env + fi +fi + +# Ensure DB_HOST points to the compose service name for in-container access +if grep -q '^DB_HOST=' .env; then + sed -i 's/^DB_HOST=.*/DB_HOST=db/' .env +else + echo 'DB_HOST=db' >> .env +fi + +generate_secret() { + if command -v openssl >/dev/null 2>&1; then + openssl rand -base64 32 + else + python - <<'PY' +import base64, os +print(base64.b64encode(os.urandom(32)).decode('ascii')) +PY + fi +} + +# Ensure SECRET_KEY exists and is non-empty/non-placeholder +if grep -q '^SECRET_KEY=' .env; then + current_secret="$(grep '^SECRET_KEY=' .env | cut -d= -f2-)" + if [ -z "${current_secret}" ] || [ "${current_secret}" = "changeme" ] || [ "${current_secret}" = "REPLACE_ME" ]; then + new_secret="$(generate_secret)" + sed -i "s/^SECRET_KEY=.*/SECRET_KEY=${new_secret}/" .env + fi +else + echo "SECRET_KEY=$(generate_secret)" >> .env +fi + +echo "Environment prepared. DB_HOST set to 'db' and SECRET_KEY ensured." + diff --git a/.gitignore b/.gitignore index d46de6b..521c4c6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -.devcontainer __pycache__ *.pyc .env From b8af75f59d40abf519999159e3253ac7b4271ff0 Mon Sep 17 00:00:00 2001 From: chriscarrollsmith Date: Sat, 29 Nov 2025 22:59:55 -0500 Subject: [PATCH 2/5] fix: devcontainer .env relative path --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 9bb9a97..248b1d6 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -3,7 +3,7 @@ "workspaceFolder": "/workspaces/fastapi-jinja2-postgres-webapp", // Ensure .env exists before Docker Compose processes env_file entries - "initializeCommand": "bash .devcontainer/ensure-env.sh", + "initializeCommand": "cd \"${localWorkspaceFolder}\" && bash .devcontainer/ensure-env.sh", // Start the Postgres sidecar using the existing compose file "dockerComposeFile": [ From 67fd6154a8ae4b3ca505eb97f5d15983ddc4fe7c Mon Sep 17 00:00:00 2001 From: Christopher Carroll Smith <75859865+chriscarrollsmith@users.noreply.github.com> Date: Sun, 30 Nov 2025 04:25:06 +0000 Subject: [PATCH 3/5] Attempt codespaces fix --- .devcontainer/docker-compose.yml | 2 -- docker-compose.yml | 8 ++++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index a2528dc..fd49e73 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -7,8 +7,6 @@ services: working_dir: /workspaces/fastapi-jinja2-postgres-webapp depends_on: - db - env_file: - - ../.env command: sleep infinity # Override/augment settings for the db service defined in the root compose file diff --git a/docker-compose.yml b/docker-compose.yml index 73e2ebb..fa0a960 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,11 +2,11 @@ services: db: image: postgres:latest environment: - POSTGRES_USER: ${DB_USER} - POSTGRES_PASSWORD: ${DB_PASSWORD} - POSTGRES_DB: ${DB_NAME} + POSTGRES_USER: ${DB_USER:-postgres} + POSTGRES_PASSWORD: ${DB_PASSWORD:-postgres} + POSTGRES_DB: ${DB_NAME:-fastapi-jinja2-postgres-webapp} ports: - - "${DB_PORT}:5432" + - "${DB_PORT:-5432}:5432" volumes: - postgres_data:/var/lib/postgresql/data From 06e5b8d063de026227ed246e5c36b5b1cc8da3c4 Mon Sep 17 00:00:00 2001 From: chriscarrollsmith Date: Sun, 30 Nov 2025 00:38:09 -0500 Subject: [PATCH 4/5] Debug codespaces config --- .devcontainer/devcontainer.json | 4 ++-- .devcontainer/docker-compose.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 248b1d6..59c38a1 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,9 +1,9 @@ { "name": "FastAPI Jinja2 Postgres WebApp", - "workspaceFolder": "/workspaces/fastapi-jinja2-postgres-webapp", + "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", // Ensure .env exists before Docker Compose processes env_file entries - "initializeCommand": "cd \"${localWorkspaceFolder}\" && bash .devcontainer/ensure-env.sh", + "initializeCommand": "bash \"${localWorkspaceFolder}/.devcontainer/ensure-env.sh\"", // Start the Postgres sidecar using the existing compose file "dockerComposeFile": [ diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index fd49e73..a93b3e8 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -3,8 +3,8 @@ services: image: mcr.microsoft.com/devcontainers/python:3.13-bookworm container_name: fastapi-jinja2-postgres-webapp-app volumes: - - ..:/workspaces/fastapi-jinja2-postgres-webapp:cached - working_dir: /workspaces/fastapi-jinja2-postgres-webapp + - ..:/workspaces/${localWorkspaceFolderBasename}:cached + working_dir: /workspaces/${localWorkspaceFolderBasename} depends_on: - db command: sleep infinity From 90c89e997c4f6ced9bf47b9727b0a95e734ea98d Mon Sep 17 00:00:00 2001 From: chriscarrollsmith Date: Sun, 30 Nov 2025 17:09:22 -0500 Subject: [PATCH 5/5] fix DOOD config --- .devcontainer/devcontainer.json | 20 ++++++++------------ .devcontainer/docker-compose.yml | 26 ++++++++------------------ .devcontainer/init-env.sh | 8 ++++---- 3 files changed, 20 insertions(+), 34 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 59c38a1..d9f9b1b 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,27 +1,24 @@ { "name": "FastAPI Jinja2 Postgres WebApp", + "image": "mcr.microsoft.com/devcontainers/python:3.13-bookworm", "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", - // Ensure .env exists before Docker Compose processes env_file entries - "initializeCommand": "bash \"${localWorkspaceFolder}/.devcontainer/ensure-env.sh\"", + "features": { + "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {} + }, - // Start the Postgres sidecar using the existing compose file - "dockerComposeFile": [ - "../docker-compose.yml", - "docker-compose.yml" + "runArgs": [ + "--add-host=host.docker.internal:host-gateway" ], - "service": "app", - "runServices": ["db"], - "shutdownAction": "stopCompose", - // Forward common app/db ports "forwardPorts": [8000, 5432], "portsAttributes": { "8000": { "label": "FastAPI", "onAutoForward": "openBrowser" }, "5432": { "label": "PostgreSQL" } }, - // Prepare env, install uv, and sync deps + "initializeCommand": "bash \"${localWorkspaceFolder}/.devcontainer/ensure-env.sh\"", + "postStartCommand": "docker compose -f .devcontainer/docker-compose.yml up -d", "postCreateCommand": "bash .devcontainer/init-env.sh && curl -LsSf https://astral.sh/uv/install.sh | sh && ~/.local/bin/uv sync", "customizations": { @@ -33,4 +30,3 @@ } } } - diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index a93b3e8..48bc1d4 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -1,25 +1,15 @@ services: - app: - image: mcr.microsoft.com/devcontainers/python:3.13-bookworm - container_name: fastapi-jinja2-postgres-webapp-app - volumes: - - ..:/workspaces/${localWorkspaceFolderBasename}:cached - working_dir: /workspaces/${localWorkspaceFolderBasename} - depends_on: - - db - command: sleep infinity - - # Override/augment settings for the db service defined in the root compose file db: - # Avoid requiring a project-level .env during compose evaluation - env_file: [] + image: postgres:16 + restart: unless-stopped + ports: + - "5432:5432" environment: POSTGRES_USER: ${DB_USER:-postgres} POSTGRES_PASSWORD: ${DB_PASSWORD:-postgres} POSTGRES_DB: ${DB_NAME:-fastapi-jinja2-postgres-webapp} - ports: - - "5432:5432" - -# Note: The 'db' service is defined in the repository root docker-compose.yml. -# This file is merged with that one via devcontainer.json dockerComposeFile array. + volumes: + - pgdata:/var/lib/postgresql/data +volumes: + pgdata: diff --git a/.devcontainer/init-env.sh b/.devcontainer/init-env.sh index a12f4cd..909a461 100644 --- a/.devcontainer/init-env.sh +++ b/.devcontainer/init-env.sh @@ -13,11 +13,11 @@ if [ ! -f ".env" ]; then fi fi -# Ensure DB_HOST points to the compose service name for in-container access +# Ensure DB_HOST points to host.docker.internal for DooD sibling container access if grep -q '^DB_HOST=' .env; then - sed -i 's/^DB_HOST=.*/DB_HOST=db/' .env + sed -i 's/^DB_HOST=.*/DB_HOST=host.docker.internal/' .env else - echo 'DB_HOST=db' >> .env + echo 'DB_HOST=host.docker.internal' >> .env fi generate_secret() { @@ -42,5 +42,5 @@ else echo "SECRET_KEY=$(generate_secret)" >> .env fi -echo "Environment prepared. DB_HOST set to 'db' and SECRET_KEY ensured." +echo "Environment prepared. DB_HOST set to 'host.docker.internal' and SECRET_KEY ensured."