2核2G 40G空间的服务器,不推荐使用Jenkins

尽量别在服务器 npm build、mvn package,还是走镜像

安装git

1
sudo apt-get update && sudo apt-get install -y git

方案一:GitHub Actions + deploy. sh

  1. push 到 GitHub
  2. GitHub Actions 自动:
    • build 后端镜像
    • build 前端镜像
    • push 到 GHCR / Docker Hub
  3. 并SSH到服务器,并执行部署脚本deploy. sh :
    • docker compose pull
    • docker compose up -d

✅ 优点:服务器不吃资源(2核2G非常适合)
✅ 部署快、稳定、可回滚(tag)

详细操作

前端Dockerfile(已废弃,前端build后手动上传到nginx目录下)

示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# frontend/Dockerfile
FROM node:20-alpine AS build

WORKDIR /app

# 1. 先拷贝依赖描述利用缓存
COPY package*.json ./
RUN npm ci

# 2. 再拷贝全部源码包含 public/drawio
COPY . .

# 3. Vue CLI 构建public 目录会原样拷贝进 dist
RUN npm run build

# 4. 运行阶段Nginx
FROM nginx:alpine

# 用我们自己的 nginx 配置
COPY nginx.conf /etc/nginx/conf.d/default.conf

# 拷贝构建产物
COPY --from=build /app/dist /usr/share/nginx/html

EXPOSE 80

nginx.conf

放到和Dockerfile同一目录下,示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
server {
  listen 80;
  server_name _;

  root /usr/share/nginx/html;
  index index.html;

  # draw.io 静态资源必须放在 / 前面
  location /drawio/ {
    try_files $uri $uri/ =404;
  }

  # Vue CLI history 模式
  location / {
    try_files $uri $uri/ /index.html;
  }

  # 后端 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;
  }
}

顺序非常重要:
/drawio/一定要在/ 前面,否则会被 history fallback 吃掉。

后端Dockerfile

示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
FROM maven:3.9-eclipse-temurin-17 AS build
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn -q -DskipTests package

FROM eclipse-temurin:17-jre
WORKDIR /app
COPY --from=build /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app/app.jar"]

GitHub Actions

.github/workflows/deploy.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
name: build-push-deploy

on:
  push:
    branches: ["main"]

permissions:
  contents: read
  packages: write

jobs:
  build_and_push:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: docker/setup-buildx-action@v3

      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build & push backend
        uses: docker/build-push-action@v6
        with:
          context: ./backend
          push: true
          tags: |
            ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}-backend:latest
            ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}-backend:${{ github.sha }}

      - name: Build & push frontend
        uses: docker/build-push-action@v6
        with:
          context: ./frontend
          push: true
          tags: |
            ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}-frontend:latest
            ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}-frontend:${{ github.sha }}

  deploy:
    needs: build_and_push
    runs-on: ubuntu-latest
    steps:
      - name: SSH deploy
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SERVER_SSH_KEY }}
          port: ${{ secrets.SERVER_PORT || 22 }}
          script: |
            cd /project/easy-draw
            ./deploy.sh

服务器项目文件 - docker-compose.yml

/project/easy-draw/docker-compose.yml,示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
services:
  easy-draw-backend:
    image: ghcr.io/grid-oaa/easy-draw-backend:latest
    container_name: easy-draw-backend
    restart: always
    expose:
      - "8080"
    networks:
      - gateway-net

networks:
  gateway-net:
    external: true

服务器项目文件 - deploy.sh

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#!/usr/bin/env bash
set -euo pipefail

cd /project/easy-draw

echo "==> Pull latest images"
docker compose pull

echo "==> Up"
docker compose up -d --remove-orphans

echo "==> Status"
docker compose ps

echo "==> Cleanup"
docker image prune -f

流程图

方案二:GitHub Actions + Webhook

  1. 本地 push 到 GitHub 的 main
  2. GitHub Actions(CI)自动:
    • 构建后端/前端镜像
    • push 到 GHCR
  3. GitHub Webhook 发送一个 HTTP POST 到你的 Portainer Webhook URL
  4. Portainer 收到 Webhook 后:
    • 重新拉取镜像(pull)
    • 重新部署Stack(等价于 docker compose up -d)
  5. 服务器上的容器更新完成,对外服务切到新版本

注意:Portainer webhook 只负责“触发 Portainer 做 redeploy”,真正的 pull/up 由 Portainer 完成,所以你可以不用 deploy.sh。