From 65dddea3bcf4e396c2973228c48437cf9e3a43c2 Mon Sep 17 00:00:00 2001 From: Finn Stutzenstein Date: Wed, 21 Oct 2026 06:25:18 +0000 Subject: [PATCH] initial switch to a devcontainer --- .devcontainer/Dockerfile | 36 ++++++++++++++++++++++++++++ .devcontainer/compose.yml | 29 ++++++++++++++++++++++ .devcontainer/devcontainer-lock.json | 9 +++++++ .devcontainer/devcontainer.json | 22 +++++++++++++++++ Makefile | 3 +++ dc.dev.yml | 2 +- docker-compose.yml | 2 +- scripts/entrypoint-dev.sh | 2 +- 8 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/compose.yml create mode 100644 .devcontainer/devcontainer-lock.json create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..edec4f1 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,36 @@ +# Keep the Python version in sync with Dockerfile.dev +FROM python:3.15-slim-trixie + +ARG USERNAME=dev +ARG USER_UID=1000 +ARG USER_GID=$USER_UID + +# git + openssh-client: git over the host's forwarded SSH agent +# gcc, libc-dev, libpq-dev: build psycopg2 from requirements.txt +# postgresql-client, wait-for-it: scripts/db-setup.sh, scripts/psql.sh +# curl, ca-certificates: Claude Code installer +# vim: personal preferences +RUN apt-get -y update && \ + apt-get install --no-install-recommends -y \ + git openssh-client make curl ca-certificates sudo \ + gcc libc-dev libpq-dev \ + postgresql-client wait-for-it \ + vim && \ + apt-get clean && rm -rf /var/lib/apt/lists/* + +RUN groupadd --gid $USER_GID $USERNAME && \ + useradd --uid $USER_UID --gid $USER_GID -m -s /bin/bash $USERNAME && \ + echo "$USERNAME ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/$USERNAME && \ + chmod 0440 /etc/sudoers.d/$USERNAME + +# Project venv, owned by the dev user so pip works without sudo +ENV VIRTUAL_ENV=/opt/venv +RUN python -m venv $VIRTUAL_ENV && chown -R $USERNAME:$USERNAME $VIRTUAL_ENV +ENV PATH="$VIRTUAL_ENV/bin:$PATH" + +USER $USERNAME + +# Claude Code (native installer, lands in ~/.local). The home dir is a volume +# (see devcontainer.json); Claude then updates itself inside that volume. +RUN curl -fsSL https://claude.ai/install.sh | bash +ENV PATH="/home/$USERNAME/.local/bin:$PATH" diff --git a/.devcontainer/compose.yml b/.devcontainer/compose.yml new file mode 100644 index 0000000..50f2a47 --- /dev/null +++ b/.devcontainer/compose.yml @@ -0,0 +1,29 @@ +services: + dev: + build: + context: . + dockerfile: Dockerfile + command: sleep infinity + volumes: + - ..:/workspaces/max:cached + - home:/home/dev + environment: + - PYTHONPATH=/workspaces/max + - FLASK_APP=max.app + - FLASK_ENV=development + - PGSQL_HOST=postgresql + - PGSQL_PORT=5432 + - PGSQL_USER=max + - PGSQL_PASSWORD=max + - PGSQL_NAME=max + depends_on: + - postgresql + postgresql: + image: postgres:18.6 + environment: + - POSTGRES_USER=max + - POSTGRES_PASSWORD=max + - POSTGRES_DB=max +volumes: + home: + name: max-devcontainer-home diff --git a/.devcontainer/devcontainer-lock.json b/.devcontainer/devcontainer-lock.json new file mode 100644 index 0000000..05b2ad3 --- /dev/null +++ b/.devcontainer/devcontainer-lock.json @@ -0,0 +1,9 @@ +{ + "features": { + "ghcr.io/devcontainers/features/docker-outside-of-docker:1": { + "version": "1.10.1", + "resolved": "ghcr.io/devcontainers/features/docker-outside-of-docker@sha256:698f5900fac471e046c6e9d4333fec88c0e8d952c713494fa0712dce80baeca0", + "integrity": "sha256:698f5900fac471e046c6e9d4333fec88c0e8d952c713494fa0712dce80baeca0" + } + } +} diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..ee75f16 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,22 @@ +{ + "name": "max", + "dockerComposeFile": "compose.yml", + "service": "dev", + "workspaceFolder": "/workspaces/max", + "remoteUser": "dev", + "features": { + // moby=false: Moby packages are not available for Debian trixie, use Docker CE. + "ghcr.io/devcontainers/features/docker-outside-of-docker:1": { + "moby": false + } + }, + // Bind mounts are resolved by the host's daemon, so they need host paths: + // use ${LOCAL_WORKSPACE_FOLDER} instead of paths inside this container. + "remoteEnv": { + "LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}" + }, + "postCreateCommand": "pip install -U pip && pip install -U -r requirements.txt -r requirements-dev.txt", + "forwardPorts": [ + 8000 + ] +} \ No newline at end of file diff --git a/Makefile b/Makefile index 1976943..e5741b5 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,8 @@ # DEVELOPMENT SERVER +seed-dev: + scripts/entrypoint-dev.sh + build-dev: docker build -t max:dev -f Dockerfile.dev . diff --git a/dc.dev.yml b/dc.dev.yml index 9b2c54c..50d7637 100644 --- a/dc.dev.yml +++ b/dc.dev.yml @@ -16,7 +16,7 @@ services: networks: - postgresql postgresql: - image: postgres:13 + image: postgres:18.6 environment: - POSTGRES_USER=max - POSTGRES_PASSWORD=max diff --git a/docker-compose.yml b/docker-compose.yml index 8b91f55..7fe3e0b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,7 +14,7 @@ services: - postgresql - uplink postgresql: - image: postgres:13 + image: postgres:18.6 environment: - POSTGRES_USER=max - POSTGRES_PASSWORD=max diff --git a/scripts/entrypoint-dev.sh b/scripts/entrypoint-dev.sh index 4ba6921..472c72c 100755 --- a/scripts/entrypoint-dev.sh +++ b/scripts/entrypoint-dev.sh @@ -2,7 +2,7 @@ set -e -source db-setup.sh +source "$(dirname "$0")/db-setup.sh" flask add-domain finn.st flask add-domain stutzenste.in