2核2G 40G空间的服务器,不推荐使用Jenkins
尽量别在服务器 npm build、mvn package,还是走镜像
安装git#
1
| sudo apt-get update && sudo apt-get install -y git
|
方案一:GitHub Actions + deploy. sh#
- push 到 GitHub
- GitHub Actions 自动:
- build 后端镜像
- build 前端镜像
- push 到 GHCR / Docker Hub
- 并SSH到服务器,并执行部署脚本deploy. sh :
docker compose pulldocker 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#
- 本地
push 到 GitHub 的 main - GitHub Actions(CI)自动:
- GitHub Webhook 发送一个 HTTP POST 到你的 Portainer Webhook URL
- Portainer 收到 Webhook 后:
- 重新拉取镜像(pull)
- 重新部署Stack(等价于 docker compose up -d)
- 服务器上的容器更新完成,对外服务切到新版本
注意:Portainer webhook 只负责“触发 Portainer 做 redeploy”,真正的 pull/up 由 Portainer 完成,所以你可以不用 deploy.sh。