Add a Docker-based development environment - #858
Open
krejko wants to merge 1 commit into
Open
Conversation
Adds Dockerfile.dev, docker-compose.dev.yml and docker/dev-entrypoint.sh, so a
contributor can run the stack with:
docker compose -f docker-compose.dev.yml up -d
Source is bind-mounted rather than copied, and dotnet watch plus vite run inside
the container, so hot reload behaves as it does natively.
Both servers share one container so vite's proxy to http://localhost:4545 keeps
working unchanged; splitting them would require editing vite.config.ts to point
at a service name.
Named volumes mask every obj/ and bin/ directory and both node_modules trees.
Host build output is targeted at the host RID (osx-arm64, osx-x64, ...) and
would otherwise be read by the Linux build, and node_modules may contain
platform-native binaries. A separate volume backs .env so the container keeps
its own database and never competes with a native instance.
The image installs ffmpeg from apt, which gives the container a working ffprobe
without relying on the runtime downloader.
Both files are new rather than edits to the production Dockerfile, so this
carries no merge risk for release builds.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an optional containerised dev environment:
Source is bind-mounted rather than copied, with
dotnet watchand vite running inside the container, so hot reload behaves as it does natively.Why this is worth having
macOS filesystem scanning does not currently work — and that's not hypothetical.
UnixOpenFlags.EnsureMacOSArchitectureSupportedrejects anything but x64, and on x64 the rawfstatP/Invoke misclassifies every regular file (see #855). Until both are resolved, a macOS contributor cannot exercise the scan path at all. Running Linux in a container sidesteps the entire class of problem, on the platform CI actually builds and tests.It also removes the .NET SDK and Node version-matching step from onboarding, and gives the container a working
ffprobefrom apt rather than the runtime downloader (which is itself broken on macOS — see #854).Changes
Added
Dockerfile.dev— SDK 10 + Node 24 + ffmpeg. Nothing isCOPYed in.docker-compose.dev.yml— bind-mounted source, published ports 4545/5173.docker/dev-entrypoint.sh— installs deps, then runs both servers underconcurrently.Design notes
One container, not two. Both servers share a container so vite's proxy to
http://localhost:4545works unchanged. Splitting them would mean editingvite.config.tsto target a service name — a source change to support tooling, which seemed like the wrong trade.Masking volumes. Named volumes cover every
obj/andbin/directory and bothnode_modulestrees. Host build output is targeted at the host RID (osx-arm64,osx-x64, …) and would otherwise be read by the Linux build;node_modulesmay hold platform-native binaries. A separate volume backs.envso the container keeps its own database and never competes with a native instance.Entrypoint in a file. The
concurrentlyinvocation needs nested quoting that YAML folding mangles — the script avoids that.Polling watchers.
DOTNET_USE_POLLING_FILE_WATCHER=1, since FSEvents/inotify don't propagate through bind mounts on macOS.Testing
Verified on macOS (Apple Silicon, Docker Desktop, VirtioFS), scanning a real 11-book library:
Native
arm64Linux, so no emulation: restore 5.8s, incremental build ~16s,ffprobeat/usr/bin/ffprobe.Storage capability check on the bind mount, since the scanner depends on it:
0x1fff)Bind mounts land in path-only mode — the existing
HasDurableGenerationProofbranch handles this and scanning works. Contributors wanting full generation proof can point the library mount at a named volume.Notes
Both files are new rather than edits to the production
Dockerfile, so there's no merge risk for release builds. The library mount is parameterised viaLISTENARR_DEV_LIBRARY(defaults to./dev-library).Not wired into CI — purely local tooling.
🤖 Generated with Claude Code