From 7108d2a58b9c5eb22584b4802fac34857628f87d Mon Sep 17 00:00:00 2001 From: hhs <386998068@qq.com> Date: Sun, 14 Jun 2026 13:38:22 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=89=8D?= =?UTF-8?q?=E7=AB=AF=20Dockerfile=20=E5=92=8C=20Nginx=20=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 多阶段构建:node:22-alpine 构建,nginx:stable-alpine 运行 - Nginx 配置:静态文件服务 + /api /ws 反代到后端 --- frontend/Dockerfile | 25 ++++++++++++++++++++++++ frontend/nginx.conf | 46 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 frontend/Dockerfile create mode 100644 frontend/nginx.conf diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..2e72310 --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,25 @@ +# ---- 构建阶段 ---- +FROM node:22-alpine AS builder + +WORKDIR /app + +# 先复制依赖清单,利用 Docker 缓存层 +COPY package.json package-lock.json ./ +RUN npm ci + +# 复制源码并构建 +COPY . . +RUN npm run build + +# ---- 运行阶段 ---- +FROM nginx:stable-alpine + +# 复制 Nginx 配置 +COPY nginx.conf /etc/nginx/conf.d/default.conf + +# 复制构建产物 +COPY --from=builder /app/dist /usr/share/nginx/html + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] diff --git a/frontend/nginx.conf b/frontend/nginx.conf new file mode 100644 index 0000000..1490d6a --- /dev/null +++ b/frontend/nginx.conf @@ -0,0 +1,46 @@ +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + # 前端静态资源 + location / { + try_files $uri $uri/ /index.html; + } + + # REST API 反代 + location /api/ { + proxy_pass http://backend:8080; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + # WebSocket 反代 + location /ws { + proxy_pass http://backend:8080; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_read_timeout 86400s; + proxy_send_timeout 86400s; + } + + # 静态资源缓存 + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + expires 7d; + add_header Cache-Control "public, immutable"; + } + + # Gzip 压缩 + gzip on; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + gzip_min_length 256; +} From d75cdf95c844e05cca8da96d7a26143bd9975fae Mon Sep 17 00:00:00 2001 From: hhs <386998068@qq.com> Date: Sun, 14 Jun 2026 13:38:25 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=20Dockerfile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 多阶段构建:golang:1.24-alpine 编译,alpine:3.20 运行 - CGO_ENABLED=0 静态链接,包含 ca-certificates 和时区数据 --- backend/Dockerfile | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 backend/Dockerfile diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..67bd3f3 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,27 @@ +# ---- 构建阶段 ---- +FROM golang:1.26-alpine AS builder + +WORKDIR /app + +# 先复制依赖清单,利用 Docker 缓存层 +COPY go.mod go.sum ./ +RUN go mod download + +# 复制源码并构建 +COPY . . +RUN CGO_ENABLED=0 GOOS=linux go build -o /camtalk ./cmd/server + +# ---- 运行阶段 ---- +FROM alpine:3.20 + +RUN apk add --no-cache ca-certificates tzdata + +WORKDIR /app + +# 复制二进制和配置 +COPY --from=builder /camtalk . +COPY config.yaml . + +EXPOSE 8080 + +ENTRYPOINT ["./camtalk"] From 1c74fdb894486d7b96c6057e3909503fada884a5 Mon Sep 17 00:00:00 2001 From: hhs <386998068@qq.com> Date: Sun, 14 Jun 2026 13:38:29 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20Docker=20Compo?= =?UTF-8?q?se=20=E7=BC=96=E6=8E=92=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - frontend 和 backend 两个服务,共享 camtalk-net 网络 - backend 通过 .env 注入 API Key,不对外暴露端口 - frontend 通过 Nginx 反代对外暴露 80 端口 --- docker-compose.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..d331f9d --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,30 @@ +services: + frontend: + build: + context: ./frontend + dockerfile: Dockerfile + container_name: camtalk-frontend + ports: + - "80:80" + depends_on: + - backend + networks: + - camtalk-net + restart: unless-stopped + + backend: + build: + context: ./backend + dockerfile: Dockerfile + container_name: camtalk-backend + env_file: + - .env + environment: + - APP_ENV=production + networks: + - camtalk-net + restart: unless-stopped + +networks: + camtalk-net: + driver: bridge From 84f5303632527a0f780efff9252ba7928cda370c Mon Sep 17 00:00:00 2001 From: hhs <386998068@qq.com> Date: Sun, 14 Jun 2026 13:38:32 +0800 Subject: [PATCH 4/5] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E9=83=A8?= =?UTF-8?q?=E7=BD=B2=E8=84=9A=E6=9C=AC=20deploy.sh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 支持 build / up / down / restart / logs / status 命令 - 首次运行自动从 .env.example 生成 .env 模板 --- deploy.sh | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100755 deploy.sh diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..ebf1858 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash +set -euo pipefail + +PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)" +cd "$PROJECT_DIR" + +# 颜色输出 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +info() { echo -e "${GREEN}[INFO]${NC} $*"; } +warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } +error() { echo -e "${RED}[ERROR]${NC} $*" >&2; } + +# 确保 .env 存在 +ensure_env() { + if [ ! -f .env ]; then + if [ -f .env.example ]; then + warn ".env 文件不存在,从 .env.example 复制模板" + cp .env.example .env + warn "请编辑 .env 填入实际的 API Key,然后重新运行" + exit 1 + else + error ".env.example 也不存在,请手动创建 .env" + exit 1 + fi + fi +} + +cmd_build() { + info "构建 Docker 镜像..." + docker compose build + info "构建完成" +} + +cmd_up() { + ensure_env + info "启动服务..." + docker compose up -d + info "服务已启动" + info "前端: http://localhost" + info "健康检查: http://localhost/api/health" +} + +cmd_down() { + info "停止服务..." + docker compose down + info "服务已停止" +} + +cmd_restart() { + info "重启服务..." + cmd_down + cmd_up +} + +cmd_logs() { + docker compose logs -f "${@}" +} + +cmd_status() { + docker compose ps +} + +usage() { + cat < + +命令: + build 构建 Docker 镜像 + up 启动服务(后台运行) + down 停止服务 + restart 重启服务 + logs 查看日志(可加服务名,如: $0 logs backend) + status 查看服务状态 +EOF +} + +case "${1:-}" in + build) cmd_build ;; + up) cmd_up ;; + down) cmd_down ;; + restart) cmd_restart ;; + logs) shift; cmd_logs "$@" ;; + status) cmd_status ;; + *) usage; exit 1 ;; +esac From 65718a8460b07a29b003b8d4a94d9705e0d5a835 Mon Sep 17 00:00:00 2001 From: hhs <386998068@qq.com> Date: Sun, 14 Jun 2026 13:38:35 +0800 Subject: [PATCH 5/5] =?UTF-8?q?ci:=20=E6=B7=BB=E5=8A=A0=20Gitea=20Actions?= =?UTF-8?q?=20=E9=83=A8=E7=BD=B2=E5=B7=A5=E4=BD=9C=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PR 到 main 时验证 Docker 镜像构建 - push 到 main 时自动构建并部署,含健康检查 --- .gitea/workflows/deploy.yml | 53 +++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 .gitea/workflows/deploy.yml diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..540e850 --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,53 @@ +name: Deploy + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + # ---- PR 时:验证 Docker 镜像可构建 ---- + verify: + if: github.event_name == 'pull_request' + runs-on: aliyun + steps: + - name: Checkout + uses: "http://8.161.227.145:3000/huanghaosheng/checkout@releases/v4" + + - name: Verify Frontend Build + run: docker build -t camtalk-frontend-test ./frontend + + - name: Verify Backend Build + run: docker build -t camtalk-backend-test ./backend + + - name: Cleanup + run: | + docker rmi camtalk-frontend-test camtalk-backend-test || true + + # ---- push main 时:构建并部署 ---- + deploy: + if: github.event_name == 'push' + runs-on: aliyun + steps: + - name: Checkout + uses: "http://8.161.227.145:3000/huanghaosheng/checkout@releases/v4" + + - name: Build and Deploy + run: | + chmod +x deploy.sh + ./deploy.sh build + ./deploy.sh restart + + - name: Health Check + run: | + for i in $(seq 1 10); do + if curl -sf http://localhost/api/health > /dev/null 2>&1; then + echo "服务启动成功" + exit 0 + fi + echo "等待服务启动... ($i/10)" + sleep 3 + done + echo "服务启动超时" + exit 1