#!/bin/sh set -eu ROOT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd) cd "$ROOT_DIR" assert_file() { if [ ! -f "$1" ]; then echo "缺少文件: $1" >&2 exit 1 fi } assert_contains() { file=$1 expected=$2 if ! grep -Fq -- "$expected" "$file"; then echo "$file 缺少配置: $expected" >&2 exit 1 fi } assert_file Dockerfile assert_file compose.yaml assert_file docker/entrypoint.sh assert_file .dockerignore assert_contains Dockerfile "FROM node:20" assert_contains Dockerfile "FROM maven:3.9" assert_contains Dockerfile "COPY --from=frontend-build /build/frontend/dist" assert_contains Dockerfile 'ENTRYPOINT ["/app/entrypoint.sh"]' assert_contains compose.yaml "./data:/app/data" assert_contains compose.yaml 'image: emoon-okr:${APP_IMAGE_TAG:-latest}' assert_contains compose.yaml "SPRING_DATASOURCE_URL: jdbc:sqlite:/app/data/okr-performance.db" assert_contains compose.yaml "APP_BACKUP_DIR: /app/data/backups" assert_contains compose.yaml 'APP_JWT_SECRET: ${APP_JWT_SECRET:?' assert_contains compose.yaml 'APP_SUPER_ADMIN_PASSWORD: ${APP_SUPER_ADMIN_PASSWORD:?' assert_contains compose.yaml 'APP_CORS_ORIGINS: ${APP_CORS_ORIGINS:?' assert_contains docker/entrypoint.sh 'mkdir -p "$DATA_DIR" "$BACKUP_DIR"' assert_contains docker/entrypoint.sh '数据库目录不可写' assert_contains docker/entrypoint.sh 'APP_JWT_SECRET 长度必须至少 32 字符' assert_contains .dockerignore "data/" assert_contains .dockerignore "**/target/" assert_contains .dockerignore "**/node_modules/" echo "Docker 配置契约检查通过"