Develop: Predictable host ports, split TRAEFIK_/SERVICES_ bind hosts #5590

This commit is contained in:
Michael Mayer 2026-05-19 13:31:28 +00:00
parent 1647cbfe88
commit 5462828516
2 changed files with 56 additions and 87 deletions

View file

@ -1,57 +1,26 @@
# PhotoPrism Development Environment — Override Template
#
# Copy this file to ".env" in the same directory as compose.yaml and uncomment
# the variables you want to customize. Commented entries keep the defaults
# defined inline in compose.yaml. Variables are picked up by Docker Compose
# automatically during file rendering.
## Build & Test Environment Overrides
##
## Copy this file to ".env" in the same directory as compose.yaml and uncomment
## the variables you want to customize.
# ----------------------------------------------------------------------------
# Network and project naming
# ----------------------------------------------------------------------------
# Bridge-network name. Override to run multiple parallel dev environments
# without colliding on the shared "photoprism" network.
# CUSTOM_NETWORK_NAME=photoprism
# Compose project name (built into Docker, not a CUSTOM_* knob). Isolates
# container names, named volumes, and the auto-prefixed default network
# across parallel checkouts of this repo.
# Isolates container names, named volumes, and the auto-prefixed default network
# across parallel checkouts of this repo. To run multiple environments side-by-
# side, set this together with COMPOSE_NETWORK_NAME below.
# COMPOSE_PROJECT_NAME=photoprism
# ----------------------------------------------------------------------------
# Site URL
# ----------------------------------------------------------------------------
# Bridge-network name. Override together with COMPOSE_PROJECT_NAME to run
# multiple parallel dev environments without colliding on the shared network.
# COMPOSE_NETWORK_NAME=photoprism
# Public base URL PhotoPrism advertises in share links, OIDC redirect URIs,
# the PWA manifest, etc. The server normalizes the value (strips default
# ports, query strings, fragments) so the trailing slash is optional.
#
# Changing this away from "https://app.localssl.dev/" only affects URLs
# emitted by PhotoPrism itself.
# Network interfaces to which Traefik and other services bind on the host.
# Defaults expose Traefik on every interface (so *.localssl.dev is reachable
# from the LAN) and keep direct service ports on loopback only.
# TRAEFIK_BIND_HOST=0.0.0.0
# SERVICES_BIND_HOST=127.0.0.1
# Host ports for Traefik's HTTP and HTTPS entrypoints.
# TRAEFIK_HTTP_PORT=80
# TRAEFIK_HTTPS_PORT=443
# Public base URL PhotoPrism advertises in share links, OIDC & PWA URIs.
# PHOTOPRISM_SITE_URL=https://app.localssl.dev/
# ----------------------------------------------------------------------------
# Host binding and port mappings
# ----------------------------------------------------------------------------
# Network interface published ports bind to. Use "127.0.0.1" to restrict
# access to the local machine; "0.0.0.0" exposes ports on every interface.
# CUSTOM_BIND_HOST=0.0.0.0
# Host ports for Traefik's HTTP and HTTPS entrypoints. When unset, Docker
# picks the first free port from 80-380 and 443-743 respectively. Set
# explicitly to get a predictable port (and let Docker fail loudly on
# conflict).
# CUSTOM_HTTP_PORT=80
# CUSTOM_HTTPS_PORT=443
# Host port for MariaDB; default range 4001-4999.
# CUSTOM_MARIADB_PORT=4001
# Host port for PostgreSQL; only effective when you uncomment the postgres
# ports block in compose.yaml. Default range 5432-5999.
# CUSTOM_POSTGRES_PORT=5432
# Host port for the dummy LDAP server; only effective when you uncomment
# the dummy-ldap ports block in compose.yaml. Default range 389-442.
# CUSTOM_LDAP_PORT=389

View file

@ -2,7 +2,7 @@
## Setup: https://docs.photoprism.app/developer-guide/setup/ ##
services:
## PhotoPrism (Development Environment)
## PhotoPrism Build & Test Environment
photoprism:
build: .
image: photoprism/photoprism:develop
@ -14,13 +14,13 @@ services:
security_opt:
- seccomp:unconfined
- apparmor:unconfined
## Publish the dev environment's HTTP, TLS, and debugger ports on the host (Docker
## picks the first free port from the range if the default is already in use):
## Publish the dev environment's HTTP, TLS, and debugger ports on the host
## (bound to 127.0.0.1 by default; override SERVICES_BIND_HOST to change):
ports:
- "${CUSTOM_BIND_HOST:-0.0.0.0}:2342-2999:2342" # HTTP (default)
- "${CUSTOM_BIND_HOST:-0.0.0.0}:2443-2999:2443" # TLS (default)
- "${CUSTOM_BIND_HOST:-0.0.0.0}:2343-2999:2343" # HTTP (acceptance tests)
- "${CUSTOM_BIND_HOST:-0.0.0.0}:40000-40999:40000" # Go debugger
- "${SERVICES_BIND_HOST:-127.0.0.1}:2342:2342" # HTTP (default)
- "${SERVICES_BIND_HOST:-127.0.0.1}:2443:2443" # TLS (default)
- "${SERVICES_BIND_HOST:-127.0.0.1}:2343:2343" # HTTP (acceptance tests)
- "${SERVICES_BIND_HOST:-127.0.0.1}:40000:40000" # Go debugger
shm_size: "2gb"
## Set links and labels for use with Traefik reverse proxy
links:
@ -33,7 +33,7 @@ services:
- "traefik:dummy-webdav.localssl.dev"
labels:
- "traefik.enable=true"
- "traefik.docker.network=${CUSTOM_NETWORK_NAME:-photoprism}"
- "traefik.docker.network=${COMPOSE_NETWORK_NAME:-photoprism}"
- "traefik.http.services.photoprism.loadbalancer.server.port=2342"
- "traefik.http.services.photoprism.loadbalancer.server.scheme=http"
- "traefik.http.routers.photoprism.entrypoints=websecure"
@ -167,11 +167,11 @@ services:
stop_grace_period: 15s
security_opt:
- no-new-privileges:true
## Publish Traefik's HTTP and HTTPS entrypoints on the host (Docker picks the first free
## port from the range if the default is already in use):
## Publish Traefik's HTTP and HTTPS entrypoints on the host (bound to every interface
## by default; override TRAEFIK_BIND_HOST, TRAEFIK_HTTP_PORT, or TRAEFIK_HTTPS_PORT):
ports:
- "${CUSTOM_BIND_HOST:-0.0.0.0}:${CUSTOM_HTTP_PORT:-80-380}:80" # HTTP (redirects to HTTPS)
- "${CUSTOM_BIND_HOST:-0.0.0.0}:${CUSTOM_HTTPS_PORT:-443-743}:443" # HTTPS (required)
- "${TRAEFIK_BIND_HOST:-0.0.0.0}:${TRAEFIK_HTTP_PORT:-80}:80" # HTTP (redirects to HTTPS)
- "${TRAEFIK_BIND_HOST:-0.0.0.0}:${TRAEFIK_HTTPS_PORT:-443}:443" # HTTPS (required)
labels:
- "traefik.enable=true"
volumes:
@ -189,9 +189,9 @@ services:
command: --port=4001 --innodb-strict-mode=1 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
expose:
- "4001" # 3306 isn't used intentionally to avoid conflicts and confuse port scanners
## Publish the MariaDB port on the host for direct access from outside the compose network:
## Publish the MariaDB port on the host for direct access from the host:
ports:
- "${CUSTOM_BIND_HOST:-0.0.0.0}:${CUSTOM_MARIADB_PORT:-4001-4999}:4001" # MariaDB
- "${SERVICES_BIND_HOST:-127.0.0.1}:4001:4001" # MariaDB
volumes:
- "mariadb:/var/lib/mysql"
- "./scripts/sql/mariadb-init.sql:/docker-entrypoint-initdb.d/init.sql"
@ -210,9 +210,9 @@ services:
image: postgres:18-alpine
expose:
- "5432"
## Optionally publish the PostgreSQL port on the host for direct access from outside the compose network:
# ports:
# - "${CUSTOM_BIND_HOST:-0.0.0.0}:${CUSTOM_POSTGRES_PORT:-5432-5999}:5432" # PostgreSQL
## Publish the PostgreSQL port on the host for direct access from the host:
ports:
- "${SERVICES_BIND_HOST:-127.0.0.1}:5432:5432" # PostgreSQL
volumes:
- "postgres:/var/lib/postgresql"
- "./scripts/sql/postgresql-init.sql:/docker-entrypoint-initdb.d/init.sql"
@ -236,7 +236,7 @@ services:
- "traefik:vision.localssl.dev"
labels:
- "traefik.enable=true"
- "traefik.docker.network=${CUSTOM_NETWORK_NAME:-photoprism}"
- "traefik.docker.network=${COMPOSE_NETWORK_NAME:-photoprism}"
- "traefik.http.services.qdrant.loadbalancer.server.port=6333"
- "traefik.http.services.qdrant.loadbalancer.server.scheme=http"
- "traefik.http.routers.qdrant.entrypoints=websecure"
@ -265,10 +265,10 @@ services:
profiles: [ "all", "ollama", "vision" ]
## Optionally publish the Ollama API on the host (no built-in auth — private/internal networks only):
# ports:
# - "${CUSTOM_BIND_HOST:-0.0.0.0}:11434-11999:11434" # Ollama API
# - "${SERVICES_BIND_HOST:-127.0.0.1}:11434:11434" # Ollama API
labels:
- "traefik.enable=true"
- "traefik.docker.network=${CUSTOM_NETWORK_NAME:-photoprism}"
- "traefik.docker.network=${COMPOSE_NETWORK_NAME:-photoprism}"
- "traefik.http.services.ollama.loadbalancer.server.port=11434"
- "traefik.http.routers.ollama.rule=Host(`ollama.localssl.dev`)"
- "traefik.http.routers.ollama.entrypoints=websecure"
@ -314,12 +314,12 @@ services:
## Only starts this service if the "all", "ollama", "open-webui", or "vision" profile is specified::
## docker compose --profile ollama up -d
profiles: [ "all", "ollama", "open-webui", "vision" ]
## Optionally publish Open WebUI on the host (default access is via https://chat.localssl.dev/ through Traefik):
# ports:
# - "${CUSTOM_BIND_HOST:-0.0.0.0}:8080-8999:8080" # Open WebUI
## Publish Open WebUI on the host (default access is via https://chat.localssl.dev/ through Traefik):
ports:
- "${SERVICES_BIND_HOST:-127.0.0.1}:8080:8080" # Open WebUI
labels:
- "traefik.enable=true"
- "traefik.docker.network=${CUSTOM_NETWORK_NAME:-photoprism}"
- "traefik.docker.network=${COMPOSE_NETWORK_NAME:-photoprism}"
- "traefik.http.services.open-webui.loadbalancer.server.port=8080"
- "traefik.http.routers.open-webui.rule=Host(`chat.localssl.dev`) || Host(`open-webui.localssl.dev`) || Host(`ollama-ui.localssl.dev`)"
- "traefik.http.routers.open-webui.entrypoints=websecure"
@ -349,7 +349,7 @@ services:
- "traefik:qdrant.localssl.dev"
labels:
- "traefik.enable=true"
- "traefik.docker.network=${CUSTOM_NETWORK_NAME:-photoprism}"
- "traefik.docker.network=${COMPOSE_NETWORK_NAME:-photoprism}"
- "traefik.http.services.vision.loadbalancer.server.port=5000"
- "traefik.http.services.vision.loadbalancer.server.scheme=http"
- "traefik.http.routers.vision.entrypoints=websecure"
@ -375,7 +375,7 @@ services:
WEBDAV_PASSWORD: photoprism
labels:
- "traefik.enable=true"
- "traefik.docker.network=${CUSTOM_NETWORK_NAME:-photoprism}"
- "traefik.docker.network=${COMPOSE_NETWORK_NAME:-photoprism}"
- "traefik.http.services.dummy-webdav.loadbalancer.server.port=80"
- "traefik.http.routers.dummy-webdav.entrypoints=websecure"
- "traefik.http.routers.dummy-webdav.rule=Host(`dummy-webdav.localssl.dev`)"
@ -390,7 +390,7 @@ services:
stop_grace_period: 5s
labels:
- "traefik.enable=true"
- "traefik.docker.network=${CUSTOM_NETWORK_NAME:-photoprism}"
- "traefik.docker.network=${COMPOSE_NETWORK_NAME:-photoprism}"
- "traefik.http.services.dummy-oidc.loadbalancer.server.port=9998"
- "traefik.http.routers.dummy-oidc.entrypoints=websecure"
- "traefik.http.routers.dummy-oidc.rule=Host(`dummy-oidc.localssl.dev`)"
@ -404,12 +404,12 @@ services:
dummy-ldap:
image: glauth/glauth-plugins:latest
stop_grace_period: 5s
## Optionally publish the dummy-ldap port on the host (default access is via "dummy-ldap:389" within the compose network):
# ports:
# - "${CUSTOM_BIND_HOST:-0.0.0.0}:${CUSTOM_LDAP_PORT:-389-442}:389" # LDAP
## Publish the dummy-ldap port on the host (default access is via "dummy-ldap:389" within the compose network):
ports:
- "${SERVICES_BIND_HOST:-127.0.0.1}:389:389" # LDAP
labels:
- "traefik.enable=true"
- "traefik.docker.network=${CUSTOM_NETWORK_NAME:-photoprism}"
- "traefik.docker.network=${COMPOSE_NETWORK_NAME:-photoprism}"
- "traefik.http.services.dummy-ldap.loadbalancer.server.port=5555"
- "traefik.http.routers.dummy-ldap.entrypoints=websecure"
- "traefik.http.routers.dummy-ldap.rule=Host(`dummy-ldap.localssl.dev`)"
@ -433,7 +433,7 @@ services:
- "traefik:app.localssl.dev"
labels:
- "traefik.enable=true"
- "traefik.docker.network=${CUSTOM_NETWORK_NAME:-photoprism}"
- "traefik.docker.network=${COMPOSE_NETWORK_NAME:-photoprism}"
- "traefik.http.services.keycloak.loadbalancer.server.port=8080"
- "traefik.http.routers.keycloak.entrypoints=websecure"
- "traefik.http.routers.keycloak.rule=Host(`keycloak.localssl.dev`)"
@ -463,7 +463,7 @@ services:
profiles: [ "all", "auth", "prometheus" ]
labels:
- "traefik.enable=true"
- "traefik.docker.network=${CUSTOM_NETWORK_NAME:-photoprism}"
- "traefik.docker.network=${COMPOSE_NETWORK_NAME:-photoprism}"
- "traefik.http.services.prometheus.loadbalancer.server.port=9090"
- "traefik.http.routers.prometheus.entrypoints=websecure"
- "traefik.http.routers.prometheus.rule=Host(`prometheus.localssl.dev`)"
@ -484,8 +484,8 @@ volumes:
driver: local
## Create a shared bridge network for connecting with services in other compose.yaml files.
## Override CUSTOM_NETWORK_NAME to run multiple parallel environments without colliding on the default name.
## Override COMPOSE_NETWORK_NAME to run multiple parallel environments without colliding on the default name.
networks:
default:
name: ${CUSTOM_NETWORK_NAME:-photoprism}
name: ${COMPOSE_NETWORK_NAME:-photoprism}
driver: bridge