From 36e46c400837efb77021c2298fb08a37f4c4a732 Mon Sep 17 00:00:00 2001 From: yml2213 Date: Wed, 22 Jul 2026 13:15:29 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=83=A8=E7=BD=B2=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .dockerignore | 11 +++++++++++ .env.example | 12 ++++++------ Dockerfile.backend | 7 +++++-- Dockerfile.caddy | 22 ++++++++++++++++++++++ Makefile | 41 ++++++++++++----------------------------- docker-compose.yml | 18 ++++++++++++------ 6 files changed, 68 insertions(+), 43 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile.caddy diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..dd51c45 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,11 @@ +.git +.env +backend/tmp +backend/data +backend/logs +frontend/node_modules +frontend/dist +node_modules +dist +coverage +*.log diff --git a/.env.example b/.env.example index ee90fa1..8e05688 100644 --- a/.env.example +++ b/.env.example @@ -1,15 +1,15 @@ PORT=8080 JWT_SECRET=your_very_secure_jwt_secret_here_change_me_in_production DB_PATH=data/app.db -MODE=release +GIN_MODE=release OPEN_API_KEY=sk_source_dev_key_change_me OPEN_API_SECRET=sk_source_dev_secret_change_me OPEN_SIGN_SKEW=300 OPEN_API_DEBUG=false LOG_FILE=logs/app.log -# Caddy 镜像配置:make docker-up 会先拉取来源镜像并标记成本地运行镜像 -CADDY_RUNTIME_IMAGE=affiliate-caddy:2 -CADDY_SOURCE_IMAGE=caddy:2 -CADDY_FALLBACK_IMAGES=docker.m.daocloud.io/library/caddy:2 registry.cn-hangzhou.aliyuncs.com/caddy/caddy:2 -# Caddy 生产环境无需前端运行时环境变量,前端会构建为静态文件 +# Docker 构建基础镜像;如镜像源不可用,可改为官方镜像或你的私有镜像源 +GO_BUILDER_IMAGE=docker.m.daocloud.io/library/golang:1.26-alpine +BACKEND_RUNTIME_IMAGE=docker.m.daocloud.io/library/alpine:3.22 +NODE_BUILDER_IMAGE=docker.m.daocloud.io/library/node:22-alpine +CADDY_BASE_IMAGE=docker.m.daocloud.io/library/caddy:2-alpine diff --git a/Dockerfile.backend b/Dockerfile.backend index 44d4600..db4bcb3 100644 --- a/Dockerfile.backend +++ b/Dockerfile.backend @@ -1,4 +1,7 @@ -FROM golang:1.26-alpine AS builder +ARG GO_BUILDER_IMAGE=docker.m.daocloud.io/library/golang:1.26-alpine +ARG BACKEND_RUNTIME_IMAGE=docker.m.daocloud.io/library/alpine:3.22 + +FROM ${GO_BUILDER_IMAGE} AS builder WORKDIR /app @@ -13,7 +16,7 @@ WORKDIR /app/backend RUN CGO_ENABLED=0 GOOS=linux go build -o /server ./cmd/server # 最终运行镜像 / Runtime image -FROM alpine:latest +FROM ${BACKEND_RUNTIME_IMAGE} RUN apk --no-cache add ca-certificates tzdata curl diff --git a/Dockerfile.caddy b/Dockerfile.caddy new file mode 100644 index 0000000..d6b47d3 --- /dev/null +++ b/Dockerfile.caddy @@ -0,0 +1,22 @@ +ARG NODE_BUILDER_IMAGE=docker.m.daocloud.io/library/node:22-alpine +ARG CADDY_BASE_IMAGE=docker.m.daocloud.io/library/caddy:2-alpine + +FROM ${NODE_BUILDER_IMAGE} AS frontend-builder + +WORKDIR /app/frontend + +# 先安装依赖,利用 Docker 层缓存 / Install dependencies first for Docker cache +COPY frontend/package.json frontend/package-lock.json ./ +RUN npm ci + +COPY frontend ./ +RUN npm run build + +FROM ${CADDY_BASE_IMAGE} + +COPY Caddyfile /etc/caddy/Caddyfile +COPY --from=frontend-builder /app/frontend/dist /usr/share/caddy + +EXPOSE 80 443 + +CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"] diff --git a/Makefile b/Makefile index 46e9e2e..c25cc47 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,10 @@ -.PHONY: start dev backend frontend install stop frontend-build docker-pull-caddy docker-build docker-up docker-down docker-logs +.PHONY: start dev backend frontend install stop docker-build docker-up docker-down docker-logs docker-ps docker-config ifneq (,$(wildcard .env)) include .env export endif -CADDY_RUNTIME_IMAGE ?= affiliate-caddy:2 -CADDY_SOURCE_IMAGE ?= caddy:2 -CADDY_FALLBACK_IMAGES ?= docker.m.daocloud.io/library/caddy:2 registry.cn-hangzhou.aliyuncs.com/caddy/caddy:2 - # 一键启动前后端(推荐) start dev: @bash ./start.sh @@ -29,31 +25,12 @@ stop: @-lsof -tiTCP:5173 -sTCP:LISTEN | xargs kill 2>/dev/null || true @echo "已尝试停止 8080 / 5173 端口服务" -# Docker 部署相关命令 -frontend-build: - @echo "构建前端静态文件..." - cd frontend && npm ci && npm run build +# Docker 部署:宿主机只需要 Docker/Compose,前端与后端都在镜像内构建 +docker-build: + @echo "构建 Docker 镜像..." + docker compose build -docker-pull-caddy: - @set -e; \ - echo "准备 Caddy 运行镜像: $(CADDY_RUNTIME_IMAGE)"; \ - for image in $(CADDY_SOURCE_IMAGE) $(CADDY_FALLBACK_IMAGES); do \ - echo "尝试拉取 Caddy 镜像: $$image"; \ - if docker pull "$$image"; then \ - docker tag "$$image" "$(CADDY_RUNTIME_IMAGE)"; \ - echo "已将 $$image 标记为 $(CADDY_RUNTIME_IMAGE)"; \ - exit 0; \ - fi; \ - done; \ - echo "错误: Caddy 镜像拉取失败,可在 .env 中设置 CADDY_SOURCE_IMAGE 或 CADDY_FALLBACK_IMAGES"; \ - exit 1 - -docker-build: frontend-build docker-pull-caddy - @echo "构建后端 Docker 镜像..." - docker build -f Dockerfile.backend -t affiliate-backend:latest . - @echo "构建完成,可执行: docker compose up -d --build" - -docker-up: frontend-build docker-pull-caddy +docker-up: @echo "启动 Docker Compose 服务..." docker compose up -d --build @@ -64,3 +41,9 @@ docker-down: docker-logs: @echo "查看 backend 和 caddy 日志..." docker compose logs -f backend caddy + +docker-ps: + docker compose ps + +docker-config: + docker compose config diff --git a/docker-compose.yml b/docker-compose.yml index 85bcd91..64cccac 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,13 +3,17 @@ services: build: context: . dockerfile: Dockerfile.backend + args: + GO_BUILDER_IMAGE: ${GO_BUILDER_IMAGE:-docker.m.daocloud.io/library/golang:1.26-alpine} + BACKEND_RUNTIME_IMAGE: ${BACKEND_RUNTIME_IMAGE:-docker.m.daocloud.io/library/alpine:3.22} + image: affiliate-backend:latest ports: - "8080:8080" environment: - PORT=8080 - JWT_SECRET=${JWT_SECRET} - DB_PATH=/data/app.db - - MODE=release + - GIN_MODE=${GIN_MODE:-release} - OPEN_API_KEY=${OPEN_API_KEY} - OPEN_API_SECRET=${OPEN_API_SECRET} - OPEN_SIGN_SKEW=${OPEN_SIGN_SKEW:-300} @@ -25,17 +29,19 @@ services: retries: 3 caddy: - image: ${CADDY_RUNTIME_IMAGE:-affiliate-caddy:2} - pull_policy: never + build: + context: . + dockerfile: Dockerfile.caddy + args: + NODE_BUILDER_IMAGE: ${NODE_BUILDER_IMAGE:-docker.m.daocloud.io/library/node:22-alpine} + CADDY_BASE_IMAGE: ${CADDY_BASE_IMAGE:-docker.m.daocloud.io/library/caddy:2-alpine} + image: affiliate-caddy:latest ports: - "80:80" - "443:443" volumes: - - ./Caddyfile:/etc/caddy/Caddyfile - - ./frontend/dist:/usr/share/caddy - caddy-data:/data - caddy-config:/config - command: caddy run --config /etc/caddy/Caddyfile --adapter caddyfile depends_on: backend: condition: service_healthy