mirror of
https://github.com/ThisTine/Snip.git
synced 2026-08-18 23:18:47 +07:00
144 lines
4.6 KiB
YAML
144 lines
4.6 KiB
YAML
# Example compose: one image (built from ./Dockerfile) run as three services,
|
|
# fronted by a gateway that enforces the path rules:
|
|
# /api/* -> api
|
|
# /, /login, /dashboard, … -> frontend (static SPA + assets)
|
|
# everything else -> redirect
|
|
#
|
|
# Bring it up: docker compose up --build
|
|
# Then visit: http://localhost:8080
|
|
#
|
|
# Anonymous flows work out of the box. For login, set GOOGLE_* / OIDC_* below
|
|
# (and add the callback URLs http://localhost:8080/api/v1/auth/<provider>/callback
|
|
# in your provider console).
|
|
|
|
x-backend-env: &backend-env
|
|
STORE: postgres
|
|
DATABASE_URL: postgres://snip:snip@postgres:5432/snip?sslmode=disable
|
|
REDIS_ADDR: redis:6379
|
|
SESSION_SECRET: ${SESSION_SECRET:-change-me-in-prod}
|
|
PUBLIC_URL: ${PUBLIC_URL:-http://localhost:8080}
|
|
SHORT_DOMAIN: ${SHORT_DOMAIN:-localhost:8080}
|
|
POST_LOGIN_REDIRECT: /dashboard
|
|
COOKIE_SECURE: "false"
|
|
GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID:-}
|
|
GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET:-}
|
|
# Generic OIDC points at the bundled mock provider (see mock-oidc service).
|
|
# The issuer host:port must be identical from the browser AND the backend, so
|
|
# we use the docker service name `mock-oidc:8090` for both. To log in from a
|
|
# real browser, add this line to your /etc/hosts: 127.0.0.1 mock-oidc
|
|
OIDC_ISSUER: ${OIDC_ISSUER:-http://mock-oidc:8090/default}
|
|
OIDC_CLIENT_ID: ${OIDC_CLIENT_ID:-snip-web}
|
|
OIDC_CLIENT_SECRET: ${OIDC_CLIENT_SECRET:-snip-secret}
|
|
|
|
services:
|
|
postgres:
|
|
image: postgres:16-alpine
|
|
environment:
|
|
POSTGRES_USER: snip
|
|
POSTGRES_PASSWORD: snip
|
|
POSTGRES_DB: snip
|
|
volumes:
|
|
- pgdata:/var/lib/postgresql/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U snip"]
|
|
interval: 3s
|
|
timeout: 3s
|
|
retries: 10
|
|
|
|
redis:
|
|
image: redis:7-alpine
|
|
command: ["redis-server", "--save", "", "--appendonly", "no"]
|
|
healthcheck:
|
|
test: ["CMD", "redis-cli", "ping"]
|
|
interval: 3s
|
|
timeout: 3s
|
|
retries: 10
|
|
|
|
migrate:
|
|
image: snip:latest # built by the `api` service above
|
|
command: ["migrate"] # runs schema DDL (idempotent) then exits 0
|
|
environment: *backend-env
|
|
depends_on:
|
|
postgres: { condition: service_healthy }
|
|
restart: "no"
|
|
|
|
api:
|
|
build: .
|
|
image: snip:latest
|
|
command: ["api"] # serves /api/v1/* on :8080
|
|
environment: *backend-env
|
|
depends_on:
|
|
migrate: { condition: service_completed_successfully }
|
|
redis: { condition: service_healthy }
|
|
mock-oidc: { condition: service_started }
|
|
healthcheck:
|
|
test: ["CMD", "wget", "-qO-", "http://localhost:8080/api/v1/healthz"]
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 10
|
|
|
|
frontend:
|
|
image: snip:latest # built by the `api` service above
|
|
command: ["frontend"] # serves the SPA on :8081
|
|
environment: *backend-env
|
|
healthcheck:
|
|
test: ["CMD", "wget", "-qO-", "http://localhost:8081/healthz"]
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 10
|
|
|
|
redirect:
|
|
image: snip:latest # built by the `api` service above
|
|
command: ["redirect"] # serves short-code redirects on :8082
|
|
environment: *backend-env
|
|
depends_on:
|
|
migrate: { condition: service_completed_successfully }
|
|
redis: { condition: service_healthy }
|
|
healthcheck:
|
|
test: ["CMD", "wget", "-qO-", "http://localhost:8082/healthz"]
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 10
|
|
|
|
# Mock OpenID Connect provider for local login. It accepts any client and
|
|
# auto-issues a token (no real account needed). The service name + port
|
|
# (mock-oidc:8090) is used as the issuer by BOTH the backend and the browser,
|
|
# which is why /etc/hosts needs `127.0.0.1 mock-oidc` for browser logins.
|
|
mock-oidc:
|
|
image: ghcr.io/navikt/mock-oauth2-server:2.1.10
|
|
ports:
|
|
- "8090:8090"
|
|
environment:
|
|
SERVER_PORT: "8090"
|
|
# Non-interactive: issue a token immediately for a demo identity.
|
|
JSON_CONFIG: >-
|
|
{
|
|
"interactiveLogin": false,
|
|
"tokenCallbacks": [
|
|
{
|
|
"issuerId": "default",
|
|
"requestMappings": [
|
|
{
|
|
"requestParam": "grant_type",
|
|
"match": "authorization_code",
|
|
"claims": { "sub": "demo-user", "email": "[email protected]", "name": "Demo User" }
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
|
|
gateway:
|
|
image: caddy:2-alpine
|
|
ports:
|
|
- "8080:80"
|
|
volumes:
|
|
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
|
depends_on:
|
|
api: { condition: service_healthy }
|
|
frontend: { condition: service_healthy }
|
|
redirect: { condition: service_healthy }
|
|
|
|
volumes:
|
|
pgdata:
|