Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Version control
.git
.gitignore
.worktrees

# Environment secrets — NEVER include in build context
.env
Expand All @@ -19,7 +20,8 @@ node_modules
*.swp
*.swo

# Documentation and tests (not needed in production image)
# Documentation and tests (not needed in built images)
# Note: test/ is synced into the dev container at runtime via `docker compose watch`.
docs/
test/
*.md
Expand Down
3 changes: 2 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
*.toml text eol=lf

# Shell scripts — LF
*.sh text eol=lf
*.sh text eol=lf
.husky/* text eol=lf

# Windows scripts — CRLF
*.bat text eol=crlf
Expand Down
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
#!/bin/sh
mix compile --warnings-as-errors && mix format --check-formatted && mix credo --strict
7 changes: 6 additions & 1 deletion Dockerfile.dev
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Development Dockerfile — source code is bind-mounted, not copied
# Development Dockerfile — source is baked in at build time; changes are synced
# at runtime via `docker compose watch` (avoids slow Windows bind-mount I/O).
FROM elixir:1.18-otp-28-alpine

RUN apk add --no-cache git build-base inotify-tools nodejs npm
Expand All @@ -7,6 +8,10 @@ WORKDIR /app

RUN mix local.hex --force && mix local.rebar --force

# Bake source into the image layer. deps/_build/node_modules are excluded by
# .dockerignore and will be populated into named volumes at container start.
COPY . .

EXPOSE 4000

CMD ["mix", "phx.server"]
7 changes: 5 additions & 2 deletions config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -104,5 +104,8 @@ config :phoenix_live_view,
# Changing this configuration will require mix clean and a full recompile.
debug_heex_annotations: true,
debug_attributes: true,
# Enable helpful, but potentially expensive runtime checks
enable_expensive_runtime_checks: true
# Enable helpful, but potentially expensive runtime checks.
# Set PHX_EXPENSIVE_CHECKS=false (e.g. in docker-compose.dev.yml) to turn
# these off in constrained environments like Docker on Windows where they
# noticeably slow down LiveView renders.
enable_expensive_runtime_checks: System.get_env("PHX_EXPENSIVE_CHECKS", "true") == "true"
48 changes: 47 additions & 1 deletion docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,20 +58,66 @@ services:
DB_PORT: "5432"
SMTP_HOST: mailpit
PHX_IP: "0.0.0.0"
# Disable BEAM scheduler busy-waiting. By default idle schedulers spin on
# their vCPU rather than sleeping, starving other threads in WSL2's shared
# VM environment and adding latency to every request.
ERL_FLAGS: "+sbwt none +sbwtdcpu none +sbwtdio none"
# Disable expensive LiveView runtime checks (assign validation, slot checks,
# etc.) which add overhead on every render cycle — too costly in Docker on Windows.
PHX_EXPENSIVE_CHECKS: "false"
volumes:
- .:/app
# No Windows bind-mount for source — use `docker compose watch` instead.
# deps/_build/node_modules stay as named volumes for fast recompilation.
- deps:/app/deps
- build:/app/_build
- node_modules:/app/assets/node_modules
develop:
watch:
# Sync Elixir source, config, migrations, and static assets into the
# container via Docker's internal protocol — bypasses the slow WSL2↔Windows
# filesystem bridge that makes `- .:/app` bind-mounts sluggish on Windows.
- action: sync
path: lib
target: /app/lib
- action: sync
path: config
target: /app/config
- action: sync
path: priv
target: /app/priv
ignore:
# Tailwind/esbuild compile into priv/static/assets/ inside the
# container. Syncing the host copy (which may be stale or absent)
# would overwrite freshly-built CSS/JS with wrong files.
- static/assets/
- action: sync
path: test
target: /app/test
- action: sync
path: assets
target: /app/assets
ignore:
- node_modules/
# Dependency or tooling changes require a full image rebuild.
- action: rebuild
path: mix.exs
- action: rebuild
path: mix.lock
- action: rebuild
path: assets/package.json
- action: rebuild
path: assets/package-lock.json
depends_on:
postgres:
condition: service_healthy
command: >
sh -c "
mix deps.get &&
mix assets.vendor &&
cd assets && npm install && cd .. &&
mix tailwind.install --if-missing &&
mix esbuild.install --if-missing &&
mix assets.build &&
mix ecto.create &&
mix ecto.migrate &&
exec mix phx.server
Expand Down
Loading