mirror of
https://github.com/MarijnDoeve/TijdVoorDeTest.git
synced 2026-07-11 20:38:21 +02:00
Avoid dev port clashes and isolate docker compose per git worktree (#203)
* Avoid dev port clashes and isolate docker compose per git worktree Default dev ports (80/443/5432) clash with other projects' compose stacks. Remap them to 8080/8443/5433+ by default, and add `just init` (auto-run by `just up`) to generate a per-worktree `.env.local` with a unique COMPOSE_PROJECT_NAME, image tag, and free host ports, so multiple worktrees can run `just up` concurrently without sharing containers, volumes, images, or ports. * Pin CI to port 80 for the HTTP reachability check; use 5430 as default Postgres dev port CI runs in an isolated single-purpose runner with no port-clash concern, so pin the HTTP reachability check back to port 80 explicitly rather than changing the dev default. Also move the default dev Postgres port range from 5433 to 5430, since 5433 clashes with other commonly used local projects. * Fix Justfile init: propagate free_port failures and use portable hash free_port exhaustion was swallowed inside a command substitution used as an echo argument, silently writing empty ports to .env.local. shasum is also not guaranteed on stripped-down Linux hosts.
This commit is contained in:
@@ -70,6 +70,8 @@ jobs:
|
|||||||
set: |
|
set: |
|
||||||
*.cache-from=type=gha,scope=${{github.ref}}-devbuild
|
*.cache-from=type=gha,scope=${{github.ref}}-devbuild
|
||||||
- name: Start services
|
- name: Start services
|
||||||
|
env:
|
||||||
|
HTTP_PORT: "80"
|
||||||
run: docker compose up php database --wait --no-build
|
run: docker compose up php database --wait --no-build
|
||||||
- name: Warm up dev cache
|
- name: Warm up dev cache
|
||||||
run: docker compose exec -T php bin/console cache:warmup --env=dev
|
run: docker compose exec -T php bin/console cache:warmup --env=dev
|
||||||
|
|||||||
@@ -40,6 +40,24 @@ just shell # Interactive shell inside the PHP container
|
|||||||
just shell-run # Shell in a fresh one-off container
|
just shell-run # Shell in a fresh one-off container
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Working in git worktrees
|
||||||
|
|
||||||
|
`just up` auto-runs `just init` first, which generates a gitignored `.env.local` per checkout with a unique
|
||||||
|
`COMPOSE_PROJECT_NAME`, `IMAGES_PREFIX`, and free `HTTP_PORT`/`HTTPS_PORT`/`POSTGRES_PORT`/`MAILPIT_PORT`/
|
||||||
|
`SPOTLIGHT_PORT`. This means every worktree gets its own containers, network, volumes, and image tag — running
|
||||||
|
`just up` in two worktrees at the same time does **not** make them share a database, image, or port, even if the
|
||||||
|
worktree directories have the same basename.
|
||||||
|
|
||||||
|
- Run `just ports` to see the ports assigned to the *current* checkout — the app for that worktree is at
|
||||||
|
`https://localhost:<HTTPS_PORT>`, not a fixed port. Never assume port 8080/8443/5432/etc. when working inside a
|
||||||
|
worktree; always check `.env.local` or `just ports` first.
|
||||||
|
- `.env.local` is generated once and reused; it's safe to run `just init`/`just up` repeatedly. Delete `.env.local`
|
||||||
|
and re-run `just init` to force new ports (e.g. if the assigned ones are now taken by something else).
|
||||||
|
- Each worktree's Postgres data, uploaded files, and Caddy state live in per-worktree Docker volumes — nothing is
|
||||||
|
shared with the main checkout or other worktrees. Migrations/fixtures must be (re-)run per worktree.
|
||||||
|
- `just down`/`just clean` in one worktree only ever affects that worktree's own containers/volumes — safe to run
|
||||||
|
without impacting other worktrees.
|
||||||
|
|
||||||
### Database
|
### Database
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -1,9 +1,70 @@
|
|||||||
up *args:
|
# Load per-worktree overrides (project name, image tag, ports) generated by `just init`
|
||||||
|
set dotenv-load := true
|
||||||
|
set dotenv-filename := ".env.local"
|
||||||
|
|
||||||
|
# Generate a per-worktree COMPOSE_PROJECT_NAME, IMAGES_PREFIX and free host ports in .env.local,
|
||||||
|
# so multiple worktrees/checkouts of this repo can run `just up` at the same time without their
|
||||||
|
# containers, volumes, images or ports colliding. Safe to re-run; no-ops if already configured.
|
||||||
|
init:
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
if [ -f .env.local ] && grep -q '^COMPOSE_PROJECT_NAME=' .env.local; then
|
||||||
|
echo ".env.local already configured for this worktree, skipping (delete it to regenerate)."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
free_port() {
|
||||||
|
local port="$1" max="$2"
|
||||||
|
while [ "$port" -le "$max" ]; do
|
||||||
|
if ! (exec 3<>/dev/tcp/127.0.0.1/"$port") 2>/dev/null; then
|
||||||
|
echo "$port"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
exec 3>&- 2>/dev/null || true
|
||||||
|
port=$((port + 1))
|
||||||
|
done
|
||||||
|
echo "no free port found between $1 and $2" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
if command -v sha1sum >/dev/null 2>&1; then
|
||||||
|
hash_cmd=(sha1sum)
|
||||||
|
elif command -v shasum >/dev/null 2>&1; then
|
||||||
|
hash_cmd=(shasum)
|
||||||
|
else
|
||||||
|
hash_cmd=(sha256sum)
|
||||||
|
fi
|
||||||
|
hash=$(pwd | "${hash_cmd[@]}" | cut -c1-8)
|
||||||
|
project="tvdt-${hash}"
|
||||||
|
http_port=$(free_port 8080 8179)
|
||||||
|
https_port=$(free_port 8443 8542)
|
||||||
|
postgres_port=$(free_port 5430 5529)
|
||||||
|
mailpit_port=$(free_port 8025 8124)
|
||||||
|
spotlight_port=$(free_port 8969 9068)
|
||||||
|
{
|
||||||
|
echo "COMPOSE_PROJECT_NAME=${project}"
|
||||||
|
echo "IMAGES_PREFIX=${project}-"
|
||||||
|
echo "HTTP_PORT=${http_port}"
|
||||||
|
echo "HTTPS_PORT=${https_port}"
|
||||||
|
echo "POSTGRES_PORT=${postgres_port}"
|
||||||
|
echo "MAILPIT_PORT=${mailpit_port}"
|
||||||
|
echo "SPOTLIGHT_PORT=${spotlight_port}"
|
||||||
|
} >> .env.local
|
||||||
|
echo "Generated .env.local for this worktree:"
|
||||||
|
cat .env.local
|
||||||
|
|
||||||
|
up *args: init
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -a
|
||||||
|
[ -f .env.local ] && source .env.local
|
||||||
|
set +a
|
||||||
docker compose up -d {{ args }}
|
docker compose up -d {{ args }}
|
||||||
|
|
||||||
down *args:
|
down *args:
|
||||||
docker compose down --remove-orphans {{ args }}
|
docker compose down --remove-orphans {{ args }}
|
||||||
|
|
||||||
|
# Show the host ports assigned to this worktree (see `just init`)
|
||||||
|
ports:
|
||||||
|
@cat .env.local 2>/dev/null || echo "No .env.local yet, run 'just up' or 'just init' first."
|
||||||
|
|
||||||
stop:
|
stop:
|
||||||
docker compose stop
|
docker compose stop
|
||||||
|
|
||||||
|
|||||||
@@ -25,8 +25,13 @@ just migrate # Run pending database migrations
|
|||||||
just fixtures # Load dev fixtures (truncates first)
|
just fixtures # Load dev fixtures (truncates first)
|
||||||
```
|
```
|
||||||
|
|
||||||
The app is available at **https://localhost** (self-signed cert — run
|
`just up` first runs `just init`, which generates a `.env.local` (gitignored)
|
||||||
`just trust-cert` on macOS to trust it).
|
with a unique `COMPOSE_PROJECT_NAME`, image tag and free host ports for this
|
||||||
|
checkout, so multiple worktrees/clones can run at the same time without their
|
||||||
|
containers, volumes, images or ports colliding. Run `just ports` to see the
|
||||||
|
ports assigned to the current checkout — the app is served at
|
||||||
|
`https://localhost:<HTTPS_PORT>` (self-signed cert — run `just trust-cert` on
|
||||||
|
macOS to trust it).
|
||||||
|
|
||||||
### Useful commands
|
### Useful commands
|
||||||
|
|
||||||
|
|||||||
@@ -24,15 +24,15 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
# HTTP
|
# HTTP
|
||||||
- target: 80
|
- target: 80
|
||||||
published: ${HTTP_PORT:-80}
|
published: ${HTTP_PORT:-8080}
|
||||||
protocol: tcp
|
protocol: tcp
|
||||||
# HTTPS
|
# HTTPS
|
||||||
- target: 443
|
- target: 443
|
||||||
published: ${HTTPS_PORT:-443}
|
published: ${HTTPS_PORT:-8443}
|
||||||
protocol: tcp
|
protocol: tcp
|
||||||
# HTTP/3
|
# HTTP/3
|
||||||
- target: 443
|
- target: 443
|
||||||
published: ${HTTP3_PORT:-443}
|
published: ${HTTPS_PORT:-8443}
|
||||||
protocol: udp
|
protocol: udp
|
||||||
sass:
|
sass:
|
||||||
image: ${IMAGES_PREFIX:-}app-php
|
image: ${IMAGES_PREFIX:-}app-php
|
||||||
@@ -56,7 +56,7 @@ services:
|
|||||||
###> doctrine/doctrine-bundle ###
|
###> doctrine/doctrine-bundle ###
|
||||||
database:
|
database:
|
||||||
ports:
|
ports:
|
||||||
- "5432:5432"
|
- "${POSTGRES_PORT:-5430}:5432"
|
||||||
###< doctrine/doctrine-bundle ###
|
###< doctrine/doctrine-bundle ###
|
||||||
|
|
||||||
###> symfony/mailer ###
|
###> symfony/mailer ###
|
||||||
@@ -64,7 +64,7 @@ services:
|
|||||||
image: axllent/mailpit
|
image: axllent/mailpit
|
||||||
ports:
|
ports:
|
||||||
- "1025"
|
- "1025"
|
||||||
- "8025:8025"
|
- "${MAILPIT_PORT:-8025}:8025"
|
||||||
environment:
|
environment:
|
||||||
MP_SMTP_AUTH_ACCEPT_ANY: 1
|
MP_SMTP_AUTH_ACCEPT_ANY: 1
|
||||||
MP_SMTP_AUTH_ALLOW_INSECURE: 1
|
MP_SMTP_AUTH_ALLOW_INSECURE: 1
|
||||||
@@ -73,7 +73,7 @@ services:
|
|||||||
spotlight:
|
spotlight:
|
||||||
image: ghcr.io/getsentry/spotlight:latest
|
image: ghcr.io/getsentry/spotlight:latest
|
||||||
ports:
|
ports:
|
||||||
- "8969:8969"
|
- "${SPOTLIGHT_PORT:-8969}:8969"
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
sass:
|
sass:
|
||||||
|
|||||||
Reference in New Issue
Block a user