fix: devcontainer build and setup on fresh clones
This commit is contained in:
parent
1e8050611c
commit
c2125f063b
7 changed files with 70 additions and 15 deletions
|
|
@ -11,12 +11,16 @@
|
||||||
},
|
},
|
||||||
"mounts": [
|
"mounts": [
|
||||||
"source=${localEnv:USERPROFILE}/.ssh,target=/mnt/host-ssh,type=bind,readonly",
|
"source=${localEnv:USERPROFILE}/.ssh,target=/mnt/host-ssh,type=bind,readonly",
|
||||||
"source=/var/run/docker.sock,target=/var/run/docker-host.sock,type=bind",
|
|
||||||
"source=kirche-opencode-share,target=/home/vscode/.local/share/opencode,type=volume",
|
"source=kirche-opencode-share,target=/home/vscode/.local/share/opencode,type=volume",
|
||||||
"source=kirche-opencode-config,target=/home/vscode/.config/opencode,type=volume"
|
"source=kirche-opencode-config,target=/home/vscode/.config/opencode,type=volume"
|
||||||
],
|
],
|
||||||
"features": {
|
"features": {
|
||||||
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
|
// moby:false — python:3.12-slim is Debian trixie now, whose repos have
|
||||||
|
// no moby-cli (feature default). false installs the upstream Docker CE
|
||||||
|
// CLI instead, which supports trixie.
|
||||||
|
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {
|
||||||
|
"moby": false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"overrideCommand": false,
|
"overrideCommand": false,
|
||||||
"postCreateCommand": "sudo -E bash .devcontainer/setup.sh",
|
"postCreateCommand": "sudo -E bash .devcontainer/setup.sh",
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,19 @@
|
||||||
# Dev-only setup (runs via postCreateCommand in the attached `api` container).
|
# Dev-only setup (runs via postCreateCommand in the attached `api` container).
|
||||||
# Production needs none of this: images carry their dependencies and the
|
# Production needs none of this: images carry their dependencies and the
|
||||||
# api entrypoint migrates on every start.
|
# api entrypoint migrates on every start.
|
||||||
set -e
|
set -eo pipefail
|
||||||
|
|
||||||
REPO=/srv/kirche-einfach
|
REPO=/srv/kirche-einfach
|
||||||
|
|
||||||
|
# Run a command as vscode with the current environment intact.
|
||||||
|
# (`su vscode -c` resets the environment, which used to drop
|
||||||
|
# UV_PROJECT_ENVIRONMENT/UV_PYTHON_INSTALL_DIR plus every compose-provided
|
||||||
|
# variable — uv then created a project-local backend/.venv in the bind-mount
|
||||||
|
# instead of using /opt/venv, and sync_flows.py ran without its settings.)
|
||||||
|
as_vscode() {
|
||||||
|
sudo -u vscode -E bash -c "$*"
|
||||||
|
}
|
||||||
|
|
||||||
# Venv lives outside the bind-mount (see backend/Dockerfile).
|
# Venv lives outside the bind-mount (see backend/Dockerfile).
|
||||||
export UV_PYTHON_INSTALL_DIR=/opt/python UV_PROJECT_ENVIRONMENT=/opt/venv
|
export UV_PYTHON_INSTALL_DIR=/opt/python UV_PROJECT_ENVIRONMENT=/opt/venv
|
||||||
|
|
||||||
|
|
@ -33,22 +42,26 @@ chown -R vscode:vscode "$REPO/backend/data" \
|
||||||
# the editor; uv resolves at setup time, no lockfile is committed).
|
# the editor; uv resolves at setup time, no lockfile is committed).
|
||||||
echo "--- Installing Python dependencies ---"
|
echo "--- Installing Python dependencies ---"
|
||||||
cd "$REPO/backend"
|
cd "$REPO/backend"
|
||||||
su vscode -c "uv sync"
|
as_vscode "uv sync"
|
||||||
|
|
||||||
# opencode CLI (dev tooling; intentionally not baked into the image).
|
# opencode CLI (dev tooling; intentionally not baked into the image).
|
||||||
if [ ! -x /home/vscode/.opencode/bin/opencode ]; then
|
if [ ! -x /home/vscode/.opencode/bin/opencode ]; then
|
||||||
echo "--- Installing opencode ---"
|
echo "--- Installing opencode ---"
|
||||||
su vscode -c "curl -fsSL https://opencode.ai/install | bash"
|
as_vscode "curl -fsSL https://opencode.ai/install | bash"
|
||||||
ln -sf /home/vscode/.opencode/bin/opencode /usr/local/bin/opencode
|
ln -sf /home/vscode/.opencode/bin/opencode /usr/local/bin/opencode
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Compose services (langflow, lfx) must be up; fail loudly otherwise.
|
# Compose services (langflow, lfx) must be up; fail loudly otherwise.
|
||||||
# (api/frontend are starting alongside this script.)
|
# (api/frontend are starting alongside this script.)
|
||||||
echo "--- Waiting for compose services ---"
|
# Fresh clones have no `.env` (gitignored) and compose `env_file` is
|
||||||
|
# optional, so provision one from the example instead of failing setup.
|
||||||
|
# Fill in real secrets afterwards; empty SMTP_* means the API logs mail.
|
||||||
if [ ! -f "$REPO/.env" ]; then
|
if [ ! -f "$REPO/.env" ]; then
|
||||||
echo "ERROR: $REPO/.env is missing. Copy .env.example to .env and fill in secrets." >&2
|
echo "WARN: $REPO/.env missing — copying .env.example (fill in secrets)."
|
||||||
exit 1
|
cp "$REPO/.env.example" "$REPO/.env"
|
||||||
|
chown vscode:vscode "$REPO/.env" 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
|
echo "--- Waiting for compose services ---"
|
||||||
python3 - <<'EOF'
|
python3 - <<'EOF'
|
||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -79,7 +92,7 @@ EOF
|
||||||
# entrypoint on every start).
|
# entrypoint on every start).
|
||||||
echo "--- Syncing canonical flows ---"
|
echo "--- Syncing canonical flows ---"
|
||||||
cd "$REPO/backend"
|
cd "$REPO/backend"
|
||||||
su vscode -c "uv run python scripts/sync_flows.py --sync" || echo "WARN: flow sync failed (check backend/flows and LFX)"
|
as_vscode "uv run python scripts/sync_flows.py --sync" || echo "WARN: flow sync failed (check backend/flows and LFX)"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "=== Setup complete ==="
|
echo "=== Setup complete ==="
|
||||||
|
|
|
||||||
9
backend/.dockerignore
Normal file
9
backend/.dockerignore
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Keep the build context lean: only pyproject/alembic/entrypoint plus
|
||||||
|
# app/migrations/scripts are COPYed. Local venvs, databases and caches must
|
||||||
|
# never enter the context (slow builds, root-owned file leaks).
|
||||||
|
.venv/
|
||||||
|
data/
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
.pytest_cache/
|
||||||
|
uv.lock
|
||||||
|
|
@ -16,9 +16,10 @@ ENV PATH="/opt/venv/bin:$PATH"
|
||||||
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
|
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
|
||||||
|
|
||||||
# Foundational, inert in prod: non-root user for the editor, sudo for setup,
|
# Foundational, inert in prod: non-root user for the editor, sudo for setup,
|
||||||
# openssh-client for the devcontainer post-start hook.
|
# openssh-client for the devcontainer post-start hook, curl for the opencode
|
||||||
|
# installer in setup.sh, git for the VS Code source-control view.
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y --no-install-recommends sudo openssh-client \
|
&& apt-get install -y --no-install-recommends sudo openssh-client curl git ca-certificates \
|
||||||
&& rm -rf /var/lib/apt/lists/* \
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
&& useradd -m -s /bin/bash vscode \
|
&& useradd -m -s /bin/bash vscode \
|
||||||
&& echo "vscode ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/vscode \
|
&& echo "vscode ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/vscode \
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,12 @@ fi
|
||||||
|
|
||||||
/opt/venv/bin/alembic upgrade head
|
/opt/venv/bin/alembic upgrade head
|
||||||
|
|
||||||
|
# Migrate ran as root: hand the (possibly just created) DB files back to
|
||||||
|
# vscode so editor-run commands stay writable.
|
||||||
|
if id vscode >/dev/null 2>&1; then
|
||||||
|
chown -R vscode:vscode data 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "${APP_ENV:-prod}" = "dev" ]; then
|
if [ "${APP_ENV:-prod}" = "dev" ]; then
|
||||||
exec /opt/venv/bin/uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
|
exec /opt/venv/bin/uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,11 @@ services:
|
||||||
context: ./backend
|
context: ./backend
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
# Optional: fresh clones and CI checkouts have no `.env` (gitignored);
|
||||||
|
# containers must still create so `config`/`build` work everywhere.
|
||||||
|
# Runtime secrets come from `.env` when present (see setup.sh).
|
||||||
|
- path: .env
|
||||||
|
required: false
|
||||||
volumes:
|
volumes:
|
||||||
# No venv volume by design: the venv lives at /opt/venv (image-local,
|
# No venv volume by design: the venv lives at /opt/venv (image-local,
|
||||||
# see backend/Dockerfile). A named volume here used to shadow the image
|
# see backend/Dockerfile). A named volume here used to shadow the image
|
||||||
|
|
@ -43,7 +47,11 @@ services:
|
||||||
context: ./frontend
|
context: ./frontend
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
# Optional: fresh clones and CI checkouts have no `.env` (gitignored);
|
||||||
|
# containers must still create so `config`/`build` work everywhere.
|
||||||
|
# Runtime secrets come from `.env` when present (see setup.sh).
|
||||||
|
- path: .env
|
||||||
|
required: false
|
||||||
environment:
|
environment:
|
||||||
# Dev default (HMR); prod .env sets `preview` (build + serve bundle).
|
# Dev default (HMR); prod .env sets `preview` (build + serve bundle).
|
||||||
FRONTEND_MODE: ${FRONTEND_MODE:-dev}
|
FRONTEND_MODE: ${FRONTEND_MODE:-dev}
|
||||||
|
|
@ -65,7 +73,11 @@ services:
|
||||||
# .env.example) together with Dockerfile.lfx + backend `lfx~=` pin.
|
# .env.example) together with Dockerfile.lfx + backend `lfx~=` pin.
|
||||||
image: langflowai/langflow:${LANGFLOW_VERSION:-1.12.0}
|
image: langflowai/langflow:${LANGFLOW_VERSION:-1.12.0}
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
# Optional: fresh clones and CI checkouts have no `.env` (gitignored);
|
||||||
|
# containers must still create so `config`/`build` work everywhere.
|
||||||
|
# Runtime secrets come from `.env` when present (see setup.sh).
|
||||||
|
- path: .env
|
||||||
|
required: false
|
||||||
environment:
|
environment:
|
||||||
# Static values only; secrets/URLs come from .env via env_file.
|
# Static values only; secrets/URLs come from .env via env_file.
|
||||||
LANGFLOW_CONFIG_DIR: /app/langflow
|
LANGFLOW_CONFIG_DIR: /app/langflow
|
||||||
|
|
@ -104,7 +116,11 @@ services:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile.lfx
|
dockerfile: Dockerfile.lfx
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
# Optional: fresh clones and CI checkouts have no `.env` (gitignored);
|
||||||
|
# containers must still create so `config`/`build` work everywhere.
|
||||||
|
# Runtime secrets come from `.env` when present (see setup.sh).
|
||||||
|
- path: .env
|
||||||
|
required: false
|
||||||
volumes:
|
volumes:
|
||||||
- lfx-data:/flows
|
- lfx-data:/flows
|
||||||
ports:
|
ports:
|
||||||
|
|
|
||||||
6
frontend/.dockerignore
Normal file
6
frontend/.dockerignore
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
# Never bake host build output into the Linux image: the host checkout runs
|
||||||
|
# on Windows, so a copied node_modules would shadow the image install with
|
||||||
|
# wrong-platform binaries and diverge from package-lock.json.
|
||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
*.tsbuildinfo
|
||||||
Loading…
Add table
Add a link
Reference in a new issue