diff --git a/.github/workflows/build-image-openflare-agent.yml b/.github/workflows/build-image-openflare-agent.yml index 7397bd31..984ee335 100644 --- a/.github/workflows/build-image-openflare-agent.yml +++ b/.github/workflows/build-image-openflare-agent.yml @@ -18,7 +18,7 @@ permissions: env: IMAGE_NAME: openflare-agent - DOCKERFILE: docker/Dockerfile.agent + DOCKERFILE: manifest/docker/Dockerfile.agent jobs: build: diff --git a/.github/workflows/build-image-openflare-relay.yml b/.github/workflows/build-image-openflare-relay.yml index 289685dc..c479e65e 100644 --- a/.github/workflows/build-image-openflare-relay.yml +++ b/.github/workflows/build-image-openflare-relay.yml @@ -18,7 +18,7 @@ permissions: env: IMAGE_NAME: openflare-relay - DOCKERFILE: docker/Dockerfile.relay + DOCKERFILE: manifest/docker/Dockerfile.relay jobs: build: diff --git a/.github/workflows/build-image-openflare.yml b/.github/workflows/build-image-openflare.yml index 27d4e818..9eb21c05 100644 --- a/.github/workflows/build-image-openflare.yml +++ b/.github/workflows/build-image-openflare.yml @@ -24,7 +24,7 @@ permissions: env: IMAGE_NAME: openflare - DOCKERFILE: docker/Dockerfile + DOCKERFILE: manifest/docker/Dockerfile jobs: # Resolve version / registries once. No checkout: triggers alone determine the tag. diff --git a/.github/workflows/build-image-openflared.yml b/.github/workflows/build-image-openflared.yml index 753b75b6..af0f2345 100644 --- a/.github/workflows/build-image-openflared.yml +++ b/.github/workflows/build-image-openflared.yml @@ -18,7 +18,7 @@ permissions: env: IMAGE_NAME: openflared - DOCKERFILE: docker/Dockerfile.flared + DOCKERFILE: manifest/docker/Dockerfile.flared jobs: build: diff --git a/.gitignore b/.gitignore index 5d8a793c..ddb1171a 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ # config config.yaml +manifest/config/config.yaml .env .env.* !.env.example diff --git a/README_zh.md b/README_zh.md index 11597f6b..ed0b6658 100644 --- a/README_zh.md +++ b/README_zh.md @@ -95,10 +95,10 @@ cd refreshing ### 2. 配置环境 ```bash -cp config.example.yaml config.yaml +cp manifest/config/config.default.yaml manifest/config/config.yaml ``` -编辑 `config.yaml`,配置数据库和 Redis。OIDC 认证源统一在管理后台的系统设置页面运行时配置。 +编辑 `manifest/config/config.yaml`,配置数据库和 Redis。OIDC 认证源统一在管理后台的系统设置页面运行时配置。 ### 3. 初始化数据库 @@ -156,7 +156,7 @@ pnpm dev ## ⚙️ 配置说明 -主要配置项(完整说明请参考 `config.example.yaml`): +主要配置项(完整说明请参考 `manifest/config/config.default.yaml`): | 配置项 | 说明 | 示例 | |--------|------|------| diff --git a/docker-compose.yaml b/docker-compose.yaml deleted file mode 100644 index 88a7300e..00000000 --- a/docker-compose.yaml +++ /dev/null @@ -1,147 +0,0 @@ -# OpenFlare default compose file (`docker compose` / `docker-compose.yaml`). -# The Wavelet upstream stack is in docker-compose.wavelet.yml and is not used here. -services: - openflare: - build: - context: . - dockerfile: docker/Dockerfile - args: - VERSION: v0.9.9 -# image: ghcr.io/rain-kl/openflare:latest - restart: unless-stopped - env_file: .env - environment: - TZ: ${TZ:-Asia/Shanghai} - OTEL_EXPORTER_OTLP_ENDPOINT: ${OTEL_EXPORTER_OTLP_ENDPOINT:-http://jaeger:4317} - OTEL_EXPORTER_OTLP_INSECURE: ${OTEL_EXPORTER_OTLP_INSECURE:-true} - OTEL_SAMPLING_RATE: ${OTEL_SAMPLING_RATE:-1.0} - ports: - - "3000:3000" - volumes: - - ./uploads:/app/uploads - - ./data/sqlite:/app/data - depends_on: - postgres: - condition: service_healthy - redis: - condition: service_healthy - clickhouse: - condition: service_healthy - jaeger: - condition: service_started - - postgres: - image: postgres:17-alpine - restart: unless-stopped - ports: - - "5432:5432" - environment: - POSTGRES_DB: ${DB_NAME:-openflare} - POSTGRES_USER: ${DB_USERNAME:-openflare} - POSTGRES_PASSWORD: ${DB_PASSWORD:-replace-with-strong-password} - volumes: - - ./data/postgres_data:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${DB_USERNAME:-openflare} -d ${DB_NAME:-openflare}"] - interval: 10s - timeout: 5s - retries: 5 - - redis: - image: valkey/valkey:8.0-alpine - restart: unless-stopped - command: ["valkey-server", "--appendonly", "yes"] - ports: - - "${REDIS_PORT:-6379}:6379" - volumes: - - ./data/valkey:/data - healthcheck: - test: ["CMD", "valkey-cli", "ping"] - interval: 10s - timeout: 5s - retries: 5 - start_period: 5s - - jaeger: - image: jaegertracing/jaeger:${JAEGER_VERSION:-2.19.0} - restart: unless-stopped - environment: - TZ: ${TZ:-Asia/Shanghai} - ports: - - "${JAEGER_UI_PORT:-16686}:16686" - - "${JAEGER_OTLP_GRPC_PORT:-4317}:4317" - - "${JAEGER_OTLP_HTTP_PORT:-4318}:4318" - - clickhouse: - image: clickhouse/clickhouse-server:25.3-alpine - restart: unless-stopped - environment: - CLICKHOUSE_DB: ${CLICKHOUSE_NAME:-openflare} - CLICKHOUSE_USER: ${CLICKHOUSE_USERNAME:-default} - CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD:-replace-with-clickhouse-password} - CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1 - TZ: ${TZ:-Asia/Shanghai} - ulimits: - nofile: - soft: 262144 - hard: 262144 - ports: - - "8123:8123" - - "9000:9000" - volumes: - - ./data/clickhouse_data:/var/lib/clickhouse - - ./config/clickhouse/performance.xml:/etc/clickhouse-server/config.d/performance.xml:ro - healthcheck: - test: ["CMD", "clickhouse-client", "--user", "${CLICKHOUSE_USERNAME:-default}", "--password", "${CLICKHOUSE_PASSWORD:-replace-with-clickhouse-password}", "--query", "SELECT 1"] - interval: 10s - timeout: 5s - retries: 5 - start_period: 15s - - agent: - build: - context: . - dockerfile: docker/Dockerfile.agent - container_name: openflare-agent - restart: unless-stopped - ports: - - "80:80" - - "443:443" - - "127.0.0.1:18081:18081" - volumes: - - ./data/agent/:/data - environment: - OPENFLARE_SERVER_URL: "http://host.docker.internal:3000" - OPENFLARE_AGENT_TOKEN: "7c7c4c13df0f3a77866bcd8cde492610" - LOG_LEVEL: "debug" - extra_hosts: - - "host.docker.internal:host-gateway" - - relay: - build: - context: . - dockerfile: docker/Dockerfile.relay - container_name: openflare-relay - network_mode: host - restart: unless-stopped - volumes: - - ./data/relay/:/app/data - environment: - OPENFLARE_SERVER_URL: http://host.docker.internal:3000 - OPENFLARE_DISCOVERY_TOKEN: 85464eeb72c49abc430569d6b9c77f78 - LOG_LEVEL: "debug" - extra_hosts: - - "host.docker.internal:host-gateway" - - flared: - build: - context: . - dockerfile: docker/Dockerfile.flared - container_name: openflare-flared - network_mode: "host" - restart: unless-stopped - volumes: - - ./data/flared/:/app/data - environment: - OPENFLARE_SERVER_URL: "http://host.docker.internal:3000" - OPENFLARE_TUNNEL_TOKEN: deb0783ac1e264a9d86440169aca0f09 diff --git a/docker-compose.yml b/docker-compose.yml index c1c322e4..5a10d241 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,147 @@ -# Isolated Wavelet compose filename. -# OpenFlare's default stack is docker-compose.yaml (`docker compose` prefers -# that name over this one). This stub is kept so `git merge wavelet/main` -# cannot restore a wavelet product stack under the default compose name. -include: - - path: docker-compose.yaml +# OpenFlare default compose file (`docker compose` / `docker-compose.yaml`). +# The Wavelet upstream stack is in docker-compose.wavelet.yml and is not used here. +services: + openflare: + build: + context: . + dockerfile: manifest/docker/Dockerfile + args: + VERSION: v0.9.9 + # image: ghcr.io/rain-kl/openflare:latest + restart: unless-stopped + env_file: .env + environment: + TZ: ${TZ:-Asia/Shanghai} + OTEL_EXPORTER_OTLP_ENDPOINT: ${OTEL_EXPORTER_OTLP_ENDPOINT:-http://jaeger:4317} + OTEL_EXPORTER_OTLP_INSECURE: ${OTEL_EXPORTER_OTLP_INSECURE:-true} + OTEL_SAMPLING_RATE: ${OTEL_SAMPLING_RATE:-1.0} + ports: + - "3000:3000" + volumes: + - ./uploads:/app/uploads + - ./data/sqlite:/app/data + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + clickhouse: + condition: service_healthy + jaeger: + condition: service_started + + postgres: + image: postgres:17-alpine + restart: unless-stopped + ports: + - "5432:5432" + environment: + POSTGRES_DB: ${DB_NAME:-openflare} + POSTGRES_USER: ${DB_USERNAME:-openflare} + POSTGRES_PASSWORD: ${DB_PASSWORD:-replace-with-strong-password} + volumes: + - ./data/postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${DB_USERNAME:-openflare} -d ${DB_NAME:-openflare}"] + interval: 10s + timeout: 5s + retries: 5 + + redis: + image: valkey/valkey:8.0-alpine + restart: unless-stopped + command: ["valkey-server", "--appendonly", "yes"] + ports: + - "${REDIS_PORT:-6379}:6379" + volumes: + - ./data/valkey:/data + healthcheck: + test: ["CMD", "valkey-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 5s + + jaeger: + image: jaegertracing/jaeger:${JAEGER_VERSION:-2.19.0} + restart: unless-stopped + environment: + TZ: ${TZ:-Asia/Shanghai} + ports: + - "${JAEGER_UI_PORT:-16686}:16686" + - "${JAEGER_OTLP_GRPC_PORT:-4317}:4317" + - "${JAEGER_OTLP_HTTP_PORT:-4318}:4318" + + clickhouse: + image: clickhouse/clickhouse-server:25.3-alpine + restart: unless-stopped + environment: + CLICKHOUSE_DB: ${CLICKHOUSE_NAME:-openflare} + CLICKHOUSE_USER: ${CLICKHOUSE_USERNAME:-default} + CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD:-replace-with-clickhouse-password} + CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1 + TZ: ${TZ:-Asia/Shanghai} + ulimits: + nofile: + soft: 262144 + hard: 262144 + ports: + - "8123:8123" + - "9000:9000" + volumes: + - ./data/clickhouse_data:/var/lib/clickhouse + - ./config/clickhouse/performance.xml:/etc/clickhouse-server/config.d/performance.xml:ro + healthcheck: + test: ["CMD", "clickhouse-client", "--user", "${CLICKHOUSE_USERNAME:-default}", "--password", "${CLICKHOUSE_PASSWORD:-replace-with-clickhouse-password}", "--query", "SELECT 1"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 15s + + agent: + build: + context: . + dockerfile: manifest/docker/Dockerfile.agent + container_name: openflare-agent + restart: unless-stopped + ports: + - "80:80" + - "443:443" + - "127.0.0.1:18081:18081" + volumes: + - ./data/agent/:/data + environment: + OPENFLARE_SERVER_URL: "http://host.docker.internal:3000" + OPENFLARE_AGENT_TOKEN: "7c7c4c13df0f3a77866bcd8cde492610" + LOG_LEVEL: "debug" + extra_hosts: + - "host.docker.internal:host-gateway" + + relay: + build: + context: . + dockerfile: manifest/docker/Dockerfile.relay + container_name: openflare-relay + network_mode: host + restart: unless-stopped + volumes: + - ./data/relay/:/app/data + environment: + OPENFLARE_SERVER_URL: http://host.docker.internal:3000 + OPENFLARE_DISCOVERY_TOKEN: 85464eeb72c49abc430569d6b9c77f78 + LOG_LEVEL: "debug" + extra_hosts: + - "host.docker.internal:host-gateway" + + flared: + build: + context: . + dockerfile: manifest/docker/Dockerfile.flared + container_name: openflare-flared + network_mode: "host" + restart: unless-stopped + volumes: + - ./data/flared/:/app/data + environment: + OPENFLARE_SERVER_URL: "http://host.docker.internal:3000" + OPENFLARE_TUNNEL_TOKEN: deb0783ac1e264a9d86440169aca0f09 diff --git a/docker/Dockerfile b/docker/Dockerfile deleted file mode 100644 index b1efa829..00000000 --- a/docker/Dockerfile +++ /dev/null @@ -1,77 +0,0 @@ -# syntax=docker/dockerfile:1.7 - -ARG GO_VERSION=1.25 -ARG NODE_VERSION=22 -ARG ALPINE_VERSION=3.23 - -FROM node:${NODE_VERSION}-alpine AS frontend-builder - -ARG VERSION=dev -ARG BUILD_DATE="" - -ENV PNPM_HOME="/pnpm" -ENV PATH="$PNPM_HOME:$PATH" -ENV NODE_ENV=production -ENV NEXT_STANDALONE_EXPORT=true -ENV NEXT_PUBLIC_APP_VERSION=${VERSION} -ENV NEXT_PUBLIC_APP_BUILD_DATE=${BUILD_DATE} - -RUN corepack enable && corepack prepare pnpm@10.10.0 --activate - -WORKDIR /workspace/frontend - -COPY frontend/package.json frontend/pnpm-lock.yaml frontend/pnpm-workspace.yaml ./ -RUN pnpm install --frozen-lockfile - -COPY frontend/ ./ - -# Assert index.html so a silent export failure cannot ship an API-only binary. -RUN pnpm build:embed && test -f out/index.html - -FROM golang:${GO_VERSION}-alpine AS backend-builder - -ARG VERSION=dev -ARG BUILD_DATE="" - -RUN apk add --no-cache ca-certificates git - -WORKDIR /workspace - -# Cache dependency layer -COPY backend/go.mod backend/go.sum ./backend/ -RUN cd backend && go mod download - -COPY . . - -# Drop any stale bundle carried in the context, then overlay the fresh export so -# `//go:embed all:dist` in driver_http picks up exactly this frontend build. -RUN rm -rf backend/plugins/drivers/driver_http/dist -COPY --from=frontend-builder /workspace/frontend/out backend/plugins/drivers/driver_http/dist - -WORKDIR /workspace/backend - -RUN test -f plugins/drivers/driver_http/dist/index.html && \ - CGO_ENABLED=0 GOOS=linux go build \ - -tags embed_frontend \ - -trimpath \ - -ldflags="-s -w -X Wavelet/pkg/buildinfo.Version=${VERSION} -X Wavelet/pkg/buildinfo.BuildTime=${BUILD_DATE}" \ - -o /out/openflare-server \ - ./main.go - -FROM alpine:${ALPINE_VERSION} - -ARG TZ=Asia/Shanghai - -RUN apk add --no-cache ca-certificates tzdata postgresql-client && \ - cp /usr/share/zoneinfo/${TZ} /etc/localtime && \ - echo "${TZ}" > /etc/timezone - -WORKDIR /app - -COPY --from=backend-builder /out/openflare-server ./openflare-server -COPY docs ./docs - -EXPOSE 3000 - -ENTRYPOINT ["./openflare-server"] -CMD ["all"] diff --git a/docs/changelog/index.md b/docs/changelog/index.md index 924f1ca3..cac78333 100644 --- a/docs/changelog/index.md +++ b/docs/changelog/index.md @@ -20,6 +20,7 @@ sidebar: false ### 💄 其他/体验 +- 对齐 Wavelet 架构配置与构建布局(提交 807343c8):配置收敛至 `manifest/config/`(以 `config.default.yaml` 作为基础配置并支持 `config.yaml` 覆盖),Docker 镜像构建文件统一收敛至 `manifest/docker/` 并清理根目录冗余 `docker/` 目录,根目录 docker-compose 配置保持不变并切至新构建路径。 - 内嵌前端拷贝目标改为 `backend/plugins/drivers/driver_http/dist`,与上游 `//go:embed all:dist` 对齐;发布工作流改为读取 `backend/go.mod`。仓库内 `.gitconfig` 提供 `merge.ours` 驱动,合并上游时保留 OpenFlare 自有路径;Wavelet 的 `build-image.yml` 与 `docker-compose.yml` 已隔离,避免 canary 发布成 wavelet 镜像。 - 后端代码整体迁入 `backend/`,与上游 Wavelet 的仓库布局对齐(Cordis 插件化改造第一阶段),模块名保持 `Wavelet` 以保证上游包路径逐字一致。构建、测试、镜像与发布链路已同步调整,`make build-all` / `make dev` / `make swagger` 等本地命令用法不变;HTTP 接口与控制台行为均无变化。 - 引入上游 Cordis 微内核与平台插件到 `backend/{core,pkg,plugins}`(与上游逐字一致,可用 `scripts/sync-upstream.sh` 重复同步),并新增 `backend/openflare/share/` 承载多插件共享资源(控制消息协议、GeoIP、边缘日志)。此阶段仅落位结构与共享层,尚未改变运行时行为。 diff --git a/docs/design/index.md b/docs/design/index.md index 654ffe3d..0197383a 100644 --- a/docs/design/index.md +++ b/docs/design/index.md @@ -83,7 +83,7 @@ OpenFlare 已收敛为**单 monorepo**(Go 模块 `OpenFlare`)。控制面 Se | `pkg/` | 跨组件共享库(协议、渲染、GeoIP 等) | | `scripts/` | Swagger 生成、安装脚本等 | | `docs/` | VitePress 文档站与设计基线 | -| `docker/` | 各组件 Dockerfile | +| `manifest/docker/` | 各组件 Dockerfile | | `uploads/`、`data/` | 运行时上传目录与静态数据(`.gitignore` 忽略) | ### 1. Server 分层(`main.go` + `internal/`) diff --git a/docs/en/design/index.md b/docs/en/design/index.md index 37551a59..36809998 100644 --- a/docs/en/design/index.md +++ b/docs/en/design/index.md @@ -83,7 +83,7 @@ When contributing code, strictly follow this physical layering and directory div | `pkg/` | cross-component shared libs (protocol, rendering, GeoIP, etc.) | | `scripts/` | Swagger generation, install scripts, etc. | | `docs/` | VitePress docs site and design baseline | -| `docker/` | per-component Dockerfiles | +| `manifest/docker/` | per-component Dockerfiles | | `uploads/`, `data/` | runtime upload dir and static data (`.gitignore`d) | ### 1. Server Layering (`main.go` + `internal/`) diff --git a/manifest/docker/Dockerfile b/manifest/docker/Dockerfile index f6148c66..b1efa829 100755 --- a/manifest/docker/Dockerfile +++ b/manifest/docker/Dockerfile @@ -55,7 +55,7 @@ RUN test -f plugins/drivers/driver_http/dist/index.html && \ -tags embed_frontend \ -trimpath \ -ldflags="-s -w -X Wavelet/pkg/buildinfo.Version=${VERSION} -X Wavelet/pkg/buildinfo.BuildTime=${BUILD_DATE}" \ - -o /out/wavelet \ + -o /out/openflare-server \ ./main.go FROM alpine:${ALPINE_VERSION} @@ -68,10 +68,10 @@ RUN apk add --no-cache ca-certificates tzdata postgresql-client && \ WORKDIR /app -COPY --from=backend-builder /out/wavelet ./wavelet +COPY --from=backend-builder /out/openflare-server ./openflare-server COPY docs ./docs -EXPOSE 8000 +EXPOSE 3000 -ENTRYPOINT ["./wavelet"] +ENTRYPOINT ["./openflare-server"] CMD ["all"]