chore: initialize from backend template 0a6dd0e
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
# =============================================================================
|
||||
# feature-container-runtime-contract — base docker-compose service definition
|
||||
#
|
||||
# Usage:
|
||||
# docker compose up # base only
|
||||
# docker compose -f docker-compose.yml -f docker-compose.dev.yml up # dev override
|
||||
# docker compose -f docker-compose.yml -f docker-compose.local.yml up # local override
|
||||
#
|
||||
# Graceful-shutdown sync table (feature-container-runtime-contract D5):
|
||||
# App shutdown timeout : 30s (APP_SERVER_SHUTDOWN_TIMEOUT — SSOT: docs/registries/
|
||||
# env-keys.yaml, owner feature-env-driven-runtime-configuration)
|
||||
# Container preStop : 5s (handled by the orchestrator / stop_grace_period offset)
|
||||
# stop_grace_period : 40s (30s app drain + 5s preStop + 5s safety margin)
|
||||
#
|
||||
# Ownership: env-driven-config owns the app shutdown *value* (30s); this contract owns the
|
||||
# *relationship* (stop_grace_period >= app timeout + preStop + margin). The grace is therefore
|
||||
# sized UP to the env-keys SSOT value (30s) — you do not shrink the app drain window to fit an
|
||||
# arbitrary grace. This resolves the earlier 20s/35s drift, which had assumed an app-timeout
|
||||
# value this branch does not own (env-keys.yaml is the SSOT and sets 30s).
|
||||
#
|
||||
# Memory limit (D4):
|
||||
# The container memory limit MUST be set for -XX:MaxRAMPercentage=75 to be meaningful.
|
||||
# Default 512m suits a small service; adjust per deployment.
|
||||
# =============================================================================
|
||||
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
context: src/
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
RELEASE_VERSION: "${RELEASE_VERSION:-0.0.1}"
|
||||
BUILD_VERSION: "${BUILD_VERSION:-0.0.1+0000000}"
|
||||
GIT_SHA: "${GIT_SHA:-0000000}"
|
||||
SOURCE_URL: "${SOURCE_URL:-https://example.invalid/ca-tmpl}"
|
||||
image: caskeleton:${BUILD_VERSION:-0.0.1_local_0000000}
|
||||
ports:
|
||||
- "${APP_SERVER_PORT:-8080}:8080"
|
||||
- "9001:9001"
|
||||
environment:
|
||||
TZ: "UTC"
|
||||
LANG: "C.UTF-8"
|
||||
LC_ALL: "C.UTF-8"
|
||||
# Graceful shutdown — fallback matches the env-keys.yaml SSOT default (30s).
|
||||
# Override via .env or docker compose --env-file if you need a different value.
|
||||
APP_SERVER_SHUTDOWN_TIMEOUT: "${APP_SERVER_SHUTDOWN_TIMEOUT:-30s}"
|
||||
APP_SERVER_SHUTDOWN: "graceful"
|
||||
# ---- Read-only root filesystem (D2) -------------------------------------
|
||||
# The application must write only to the tmpfs mounts declared below.
|
||||
# /tmp — Tomcat basedir (see -Dserver.tomcat.basedir=/tmp in Dockerfile).
|
||||
# /var/tmp/heap — heap dump landing zone (see -XX:HeapDumpPath=/var/tmp/heap).
|
||||
read_only: true
|
||||
tmpfs:
|
||||
- /tmp:mode=1777,size=128m
|
||||
- /var/tmp/heap:mode=1777,size=512m
|
||||
# ---- Fileserver storage volume ------------------------------------------
|
||||
# A named volume, not a tmpfs and not the read-only root. The Fileserver platform's default
|
||||
# storage root is /var/lib/backend/files, and with a read-only root and no mount there was
|
||||
# nowhere on the image it could legally write: enabling the capability failed on its first
|
||||
# upload rather than at startup. The volume is declared unconditionally because a volume
|
||||
# nobody writes to costs nothing, while a missing one costs an outage.
|
||||
#
|
||||
# Ownership: the image runs as uid/gid 1000 (see src/Dockerfile). Docker initialises a fresh
|
||||
# named volume from the image path's ownership, so the directory is created in the image with
|
||||
# that owner; a pre-existing volume or a host bind mount must be chowned to 1000:1000 by the
|
||||
# operator, or every write is refused with a permission error the application reports as
|
||||
# STORAGE_UNAVAILABLE.
|
||||
volumes:
|
||||
- fileserver-data:/var/lib/backend/files
|
||||
# ---- Memory limit (D4) --------------------------------------------------
|
||||
# Must be set so -XX:MaxRAMPercentage=75 can compute a meaningful heap bound.
|
||||
mem_limit: 512m
|
||||
memswap_limit: 512m
|
||||
# ---- Graceful shutdown (D5) ---------------------------------------------
|
||||
# stop_grace_period = app drain (30s, env-keys SSOT) + preStop (5s) + margin (5s) = 40s.
|
||||
stop_grace_period: 40s
|
||||
# ---- Health check -------------------------------------------------------
|
||||
# Targets the actuator readiness probe on the management port (9001).
|
||||
# CROSS-FEATURE COUPLING: /actuator/health/readiness is implemented by the
|
||||
# parallel runtime-health + actuator branches. This healthcheck will report
|
||||
# UNHEALTHY in this worktree until those branches are merged.
|
||||
healthcheck:
|
||||
test:
|
||||
- "CMD"
|
||||
- "wget"
|
||||
- "--no-verbose"
|
||||
- "--tries=1"
|
||||
- "--spider"
|
||||
- "http://localhost:9001/actuator/health/readiness"
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
start_period: 60s
|
||||
retries: 3
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
# Survives container replacement, which is the point: published content outlives the process
|
||||
# that wrote it. Back this with real storage in any deployment that keeps files.
|
||||
fileserver-data:
|
||||
Reference in New Issue
Block a user