review: make the devcontainer work on a clean checkout

Track an empty no-op docker-compose.override.yml (with a .gitignore negation)
so devcontainer.json's compose file list resolves without the initializeCommand
hack, which is removed. Add USER_UID/USER_GID build args and drop the sudo
chown from setup.sh. Correct the Elixir pin comment: the OTP suffix pins only
the major, so the Erlang patch may still differ from .tool-versions.
This commit is contained in:
Guarzo
2026-08-08 17:05:42 -04:00
parent 4c9935ad7e
commit d30fce4dc4
8 changed files with 63 additions and 23 deletions
+6 -1
View File
@@ -1,4 +1,9 @@
FROM elixir:1.17-otp-26
# Pins Elixir to the .tool-versions value (1.17.3) instead of the floating
# 1.17 tag, which could drift to a different Elixir patch. This matters because
# _build is shared with the host via the /app bind. Note the OTP suffix pins
# only the major (26); the Erlang patch may still differ from .tool-versions'
# 26.2.5.5, since the official images publish no patch-level tag.
FROM elixir:1.17.3-otp-26
ARG USERNAME=developer
ARG USER_UID=1000
-1
View File
@@ -10,7 +10,6 @@
"remoteUser": "developer",
"containerUser": "developer",
"initializeCommand": "test -f .devcontainer/docker-compose.override.yml || echo 'services: {}' > .devcontainer/docker-compose.override.yml",
"postCreateCommand": "bash .devcontainer/setup.sh",
"postStartCommand": "bash .devcontainer/post-start.sh",
+10
View File
@@ -0,0 +1,10 @@
# Host-specific devcontainer overrides.
#
# This file is intentionally empty and is tracked so that
# `docker compose -f docker-compose.yml -f docker-compose.override.yml ...`
# — the invocation devcontainer.json uses — works on a clean checkout.
#
# Edit it locally for host-specific settings (SSH keys, gh auth, a non-1000
# uid, alternate Postgres port). See docker-compose.override.yml.example for
# ready-to-uncomment snippets. Local edits here are not meant to be committed.
services: {}
@@ -1,13 +1,26 @@
# docker-compose.override.yml.example
#
# Copy this file to docker-compose.override.yml for host-specific settings.
# The override file is gitignored and will be auto-created (empty) by
# devcontainer.json's initializeCommand if missing, so the devcontainer works
# without it.
# Copy this file over docker-compose.override.yml for host-specific settings.
# docker-compose.override.yml is tracked and empty by default (`services: {}`),
# so the devcontainer works without any of this.
#
# Uncomment what you need.
services:
wanderer:
# The container user is created with USER_UID/USER_GID (default 1000) so
# that deps/, _build/ and generated assets written through the /app bind
# mount stay owned by you on the host. If `id -u` on your host is not 1000,
# either export USER_UID/USER_GID before starting the devcontainer:
#
# export USER_UID="$(id -u)" USER_GID="$(id -g)"
#
# or pin them here and rebuild the container.
#
# build:
# args:
# USER_UID: "1001"
# USER_GID: "1001"
# volumes:
# # Host SSH keys (Git over SSH, commit signing)
# - ~/.ssh:/home/developer/.ssh:ro
@@ -15,8 +28,10 @@ services:
# # GitHub CLI auth
# - ~/.config/gh:/home/developer/.config/gh:ro
# Publish Postgres on a different host port if 5432 is already taken.
# (Set on the db service instead — shown here for reference.)
#
# environment:
# SOME_LOCAL_OVERRIDE: "value"
# db:
# # Publish Postgres on a different host port if 5432 is already taken.
# ports:
# - "5433:5432"
+7
View File
@@ -21,6 +21,13 @@ services:
build:
context: .
dockerfile: Dockerfile
args:
# The container user is created with these ids so that files written
# through the /app bind mount (deps/, _build/, generated assets) keep
# host ownership. Hosts whose uid is not 1000 export USER_UID/USER_GID
# (see docker-compose.override.yml.example) before building.
USER_UID: ${USER_UID:-1000}
USER_GID: ${USER_GID:-1000}
environment:
PORT: 4444
DB_HOST: db
-6
View File
@@ -1,12 +1,6 @@
#!/usr/bin/env bash
set -e
echo "→ ensuring build dirs are writable"
# deps/ and _build/ come from the /app bind mount (see docker-compose.yml), so
# they carry host ownership. When the host uid differs from the container user's,
# mix cannot write to them. Best-effort fix; harmless when uids already match.
sudo chown -R "$(id -u):$(id -g)" /app/deps /app/_build 2>/dev/null || true
echo "→ fetching & compiling deps"
mix deps.get
mix compile
+5 -1
View File
@@ -52,7 +52,11 @@ erl_crash.dump
.elixir_ls/
# Devcontainer host-specific files
/.devcontainer/docker-compose.override.yml
# .devcontainer/docker-compose.override.yml is deliberately tracked as an empty
# no-op so devcontainer.json's compose file list resolves on a clean checkout.
# The negation is explicit because a common global/user gitignore rule matches
# docker-compose.override.yml anywhere. Keep local edits to it out of commits.
!/.devcontainer/docker-compose.override.yml
# Editor directories and files
.vscode/*
+13 -7
View File
@@ -53,13 +53,19 @@ Now you can visit [`localhost:8000`](http://localhost:8000) from your browser.
#### Using .devcontainer
- Run devcontainer
- Install additional dependencies inside Dev container
- `root@0d0a785313b6:/app# apt update`
- `root@0d0a785313b6:/app# curl -sL https://deb.nodesource.com/setup_18.x | bash -`
- `root@0d0a785313b6:/app# apt-get install nodejs inotify-tools -y`
- `root@0d0a785313b6:/app# npm install -g yarn`
- `root@0d0a785313b6:/app# mix setup`
- Copy `.env.example` to `.env` and fill in the values
- Open the repository in the dev container ("Reopen in Container")
The image ships Erlang/Elixir pinned to `.tool-versions`, Node.js 18, yarn and
the usual CLI tooling, and runs as the non-root `developer` user. On first
create, `.devcontainer/setup.sh` fetches and compiles deps, creates and migrates
the database, seeds the EVE SDE reference data if it is missing, and installs
and builds the client assets — so there is nothing to install by hand.
- If your host user id is not `1000`, export `USER_UID`/`USER_GID` before
building so files written through the bind mount stay host-owned. See
`.devcontainer/docker-compose.override.yml.example` for this and other
host-specific settings.
- See how to run server in #Run section