init: ALiYunManager 基础设施项目 — nginx配置/docker-compose/部署文档

This commit is contained in:
Superuser
2026-05-16 23:27:24 +08:00
commit 0413d2715c
28 changed files with 2590 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
# 环境变量配置示例
# 复制此文件为 .env 后修改
# 域名配置
DOMAIN_RESUME_WEB=me.dxz99wyr.cn
DOMAIN_MINIAPP_WEB=www.dxz99wyr.cn
DOMAIN_RESUME_API=api-resume.dxz99wyr.cn
DOMAIN_MINIAPP_API=api-miniapp.dxz99wyr.cn
DOMAIN_GIT=git.dxz99wyr.cn
DOMAIN_DASH=dash.dxz99wyr.cn
# -- 待开发服务(上线时取消注释) --
# DOMAIN_IMG=img.dxz99wyr.cn
# DOMAIN_LOGS=logs.dxz99wyr.cn
# 主 Nginx 端口
NGINX_HTTP_PORT=80
NGINX_HTTPS_PORT=443
# 时区
TZ=Asia/Shanghai
+29
View File
@@ -0,0 +1,29 @@
# 环境变量文件(包含敏感信息)
.env
# SSL 证书
nginx/ssl/*.pem
nginx/ssl/*.crt
nginx/ssl/*.key
# 日志文件
nginx/logs/*.log
nginx/logs/*/
# 独立仓库的服务代码(各有自己的 Git 仓库)
services/me_jianliweb/
services/resume-api/
services/miniapp-web/
services/miniapp-api/
# 运行时数据
*.zip
*.tar.gz
# IDE
.idea/
.vscode/
.claude/
# Git 子目录
**/.git/
+160
View File
@@ -0,0 +1,160 @@
================================================================================
阿里云多服务 Docker 部署方案 - 2026年5月14日
================================================================================
一、服务器信息
--------------------------------------------------------------------------------
公网 IP: 8.136.137.59
域名: dxz99wyr.cn
系统: Ubuntu 5.15.0-174-generic
SSH密钥: D:\003_Project\小程序连接.pem
项目路径: /opt/ALiYunManager
二、架构设计
--------------------------------------------------------------------------------
阿里云服务器 (8.136.137.59)
beian-nginx (:80) ← 现有,已在运行
├── api-miniapp.dxz99wyr.cn → main-nginx (:8080)
│ │
│ 主 Nginx (Docker)
│ ┌──────────┬──────────┬──────────┐
│ │ │ │ │
│ resume. miniapp. api-resume. api-miniapp.
│ dxz99wyr. dxz99wyr. dxz99wyr.cn dxz99wyr.cn
│ cn cn │ │
│ (占位) host.docker.
│ internal:3000
│ │
│ quanyixiaozhushou-app
│ (小程序后端, 3000端口)
└── /quanyi → 静态页面 (原有服务)
三、子域名规划
--------------------------------------------------------------------------------
域名 用途 当前状态
─────────────────────────────────────────────────────────
resume.dxz99wyr.cn 个人简历网站 占位页面已部署
miniapp.dxz99wyr.cn 小程序网站 占位页面已部署
api-resume.dxz99wyr.cn 个人简历后台 占位页面已部署
api-miniapp.dxz99wyr.cn 小程序后台 已接入真实后端 (3000)
DNS 解析: 以上4个子域名 A 记录均指向 8.136.137.59
四、Docker 容器
--------------------------------------------------------------------------------
容器名 端口映射 说明
─────────────────────────────────────────────────────────
beian-nginx 80:80, 443:443 现有,80入口
quanyixiaozhushou-app 3000:3000 小程序后端
quanyixiaozhushou-mongo 27018:27017 MongoDB
main-nginx 8080:80, 8443:443 主 Nginx (新)
resume-web 80 (内部) 简历网站占位
miniapp-web 80 (内部) 小程序网站占位
resume-api 80 (内部) 简历后台占位
miniapp-api 80 (内部) 小程序后台占位
Docker 网络: aliyun-app-network (bridge)
beian-nginx 在 beian-docker_default 网络
五、访问链路
--------------------------------------------------------------------------------
小程序后端:
用户 → api-miniapp.dxz99wyr.cn (DNS)
→ beian-nginx (:80)
→ main-nginx (:8080)
→ host.docker.internal:3000 (本地回环)
→ quanyixiaozhushou-app (:3000)
简历网站:
用户 → resume.dxz99wyr.cn → beian-nginx (:80) → main-nginx (:8080) → resume-web (:80)
简历后台:
用户 → api-resume.dxz99wyr.cn → beian-nginx (:80) → main-nginx (:8080) → resume-api (:80)
⚠ 注:beian-nginx 目前只配了 api-miniapp 的中转,
其他三个子域名还未配置中转,后续需要补充。
六、配置文件位置
--------------------------------------------------------------------------------
项目目录: /opt/ALiYunManager/
├── docker-compose.yml 完整部署配置
├── docker-compose.main-nginx-only.yml 仅主 Nginx
├── docker-compose.override.yml 开发覆盖
├── .env / .env.example 环境变量 (端口8080)
├── nginx/
│ ├── nginx.conf 主 Nginx 核心配置
│ └── conf.d/
│ ├── resume-web.conf 简历网站反向代理
│ ├── miniapp-web.conf 小程序网站反向代理
│ ├── resume-api.conf 简历后台反向代理
│ ├── miniapp-api.conf 小程序后台反向代理 (→3000)
│ ├── ssl-template.conf HTTPS 模板
│ └── port-based-example.conf 端口模式示例
└── services/
├── resume-web/ (前端占位)
├── miniapp-web/ (前端占位)
├── resume-api/ (后端占位)
└── miniapp-api/ (后端占位)
beian-nginx 配置: /opt/beian-docker/nginx.conf
beian-nginx 备份: /opt/beian-docker/nginx.conf.bak
七、beian-nginx 中转配置要点
--------------------------------------------------------------------------------
- 添加了 server 块监听 api-miniapp.dxz99wyr.cn
- 反向代理到 172.19.0.1:8080 (Docker 网关 = 宿主机)
- 保留原有的 default_server 和 /quanyi 路径
- master nginx 模板路径: /opt/beian-docker/nginx.conf → /etc/nginx/conf.d/default.conf
八、端口说明
--------------------------------------------------------------------------------
端口 开放给外网 用途
─────────────────────────────────────
22 是 SSH
80 是 HTTP 入口 (beian-nginx)
443 是 HTTPS 入口 (beian-nginx)
3000 否 (已关闭) 小程序后端 (仅本地回环访问)
8080 否 主 Nginx (内部)
8443 否 主 Nginx HTTPS (内部)
九、常用命令
--------------------------------------------------------------------------------
# 部署/管理
docker compose up -d 启动所有服务
docker compose down 停止所有服务
docker compose restart nginx 重启主 Nginx
docker compose exec nginx nginx -s reload 重载配置 (不重启)
docker compose ps 查看服务状态
docker compose logs -f nginx 查看日志
# beian-nginx
docker exec beian-nginx nginx -t 测试配置
docker exec beian-nginx nginx -s reload 重载配置
# 单个服务更新
./scripts/update-service.sh resume-web
十、后续需要完成的工作
--------------------------------------------------------------------------------
1. [ ] beian-nginx 补充剩下 3 个子域名的中转配置
(resume, miniapp, api-resume)
2. [ ] 各服务替换占位页面为真实代码
3. [ ] 配置 HTTPS (Certbot + SSL证书)
4. [ ] 申请 SSL 证书覆盖 4 个子域名
5. [ ] 配置日志轮转 (logrotate)
6. [ ] 阿里云 DNS: 确认 4 个子域名 A 记录都已添加
十一、重要提醒
--------------------------------------------------------------------------------
- 主 Nginx (main-nginx) 当前在 8080 端口,不对外网开放
- 3000 端口已关闭外网访问,只走本地回环,更安全
- 各服务容器内部始终用 80 端口,添加新服务不需要改端口
- beian-nginx 配置修改前记得备份 (已有 .bak)
- 所有脚本已添加执行权限
================================================================================
记录时间: 2026-05-14 21:35
================================================================================
+766
View File
@@ -0,0 +1,766 @@
# Git 私有仓库 + 自动部署流水线 (AI可读)
> 基于阿里云服务器 `8.136.137.59`,部署 Gitea 私有 Git 仓库 + Webhook 自动部署流水线。
> 遵循现有架构:beian-nginx → main-nginx → 服务容器。
> **所有 Git 相关文件统一放在 `/home/Git/`,能容器化的全部容器化。**
---
## 一、架构总览
```
外网 git.dxz99wyr.cn
beian-nginx (:80/:443)
│ 新增: git.dxz99wyr.cn → 172.19.0.1:8080
main-nginx (:8080)
│ 新增: git.dxz99wyr.cn → gitea:3000
┌─────────────────────────────────────────────┐
│ gitea (Docker) │
│ 镜像: gitea/gitea:latest │
│ 内部端口: 3000 (Web UI) │
│ 内部端口: 22 (SSH Git) → 宿主机映射 2222 │
│ 数据卷: /home/Git/gitea/data → /data │
│ 网络: aliyun-app-network │
└──────────┬──────────────────────────────────┘
│ Webhook POST (push 事件)
│ URL: http://webhook:9000/hooks/xxx
┌─────────────────────────────────────────────┐
│ webhook (Docker / 自定义镜像) │
│ 内部端口: 9000 │
│ 内置: git + docker CLI + webhook 二进制 │
│ 收到 push → 执行对应脚本 │
│ 网络: aliyun-app-network │
│ 挂载: docker.sock(操控宿主机 Docker
│ /home/Git/webhook/ → 配置只读 │
│ /opt/ALiYunManager/ → 更新代码+重载 │
│ /opt/services/ → 更新各服务代码 │
│ /home/Git/logs/ → 部署日志 │
└──────────┬──────────────────────────────────┘
│ git clone/pullDocker 内网 HTTP
│ http://${GITEA_TOKEN}@gitea:3000/...
│ docker-compose up -d(通过 docker.sock
┌──────┴──────┬──────────┐
│ │ │
resume-web resume-api 其他服务...
(自动拉代码、构建、重启)
```
### 端口规划
| 端口 | 用途 | 对外网 | 说明 |
|------|------|--------|------|
| `2222` | Git SSH 克隆/推送(开发者用) | 开放 | gitea 容器 22 → 宿主机 2222 |
| `3000` | Gitea Web UI(容器内部) | 不开放 | 仅 Docker 网络内,通过 nginx 代理 |
| `9000` | Webhook 接收器(容器内部) | 不开放 | 仅 Docker 网络内,gitea 调用 |
> 2222 端口需要在阿里云安全组和服务器防火墙中放行。
### 宿主机文件总览(仅 `/home/Git/` 目录)
```
/home/Git/
├── gitea/
│ ├── docker-compose.yml # Gitea 容器定义
│ └── data/ # Gitea 全部数据(SQLite + 仓库 + 配置)
├── webhook/
│ ├── Dockerfile # 自定义镜像(git + docker CLI + webhook
│ ├── docker-compose.yml # Webhook 容器定义
│ ├── hooks.json # Webhook 路由规则
│ ├── .env # GITEA_TOKEN 等敏感变量
│ └── scripts/ # 各服务部署脚本
│ ├── deploy-common.sh
│ ├── deploy-resume-web.sh
│ ├── deploy-resume-api.sh
│ ├── deploy-aliyun-manager.sh
│ └── deploy-miniapp-web.sh
└── logs/
└── deploy.log # 部署历史日志
```
> 除此之外无需在宿主机创建其他文件。SSH 密钥、Git 配置等均在 Docker 容器内部处理。
---
## 二、部署步骤
### 步骤 1:服务器环境准备
```bash
ssh -i "D:\003_Project\小程序连接.pem" root@8.136.137.59
# 创建目录结构(一次性)
mkdir -p /home/Git/gitea/data
mkdir -p /home/Git/webhook/scripts
mkdir -p /home/Git/logs
# 放行 Git SSH 端口
ufw allow 2222/tcp
# 阿里云安全组也需要添加 2222 入方向规则
```
### 步骤 2:部署 Gitea 容器
创建 `/home/Git/gitea/docker-compose.yml`
```yaml
version: "3.8"
services:
gitea:
image: gitea/gitea:latest
container_name: gitea
restart: always
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__server__DOMAIN=git.dxz99wyr.cn
- GITEA__server__SSH_DOMAIN=8.136.137.59
- GITEA__server__SSH_PORT=2222
- GITEA__server__ROOT_URL=https://git.dxz99wyr.cn
- GITEA__server__HTTP_PORT=3000
- GITEA__server__DISABLE_SSH=false
- GITEA__database__DB_TYPE=sqlite3
- GITEA__repository__ENABLE_PUSH_CREATE_USER=true
- GITEA__repository__ENABLE_PUSH_CREATE_ORG=true
- GITEA__service__DISABLE_REGISTRATION=true
ports:
- "2222:22"
volumes:
- /home/Git/gitea/data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
networks:
- gitea-network
networks:
gitea-network:
driver: bridge
name: aliyun-app-network
```
```bash
cd /home/Git/gitea
docker-compose up -d
# 验证
docker-compose ps
docker-compose logs -f
```
### 步骤 3:配置 Nginx 反向代理
#### 3a. main-nginx 配置 — 已存在,确认即可
文件 `nginx/conf.d/git.conf`(已在项目中创建):
```nginx
server {
listen 80;
server_name git.dxz99wyr.cn;
access_log /var/log/nginx/git.access.log main;
error_log /var/log/nginx/git.error.log warn;
location / {
proxy_pass http://gitea:3000;
proxy_http_version 1.1;
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_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 300s;
proxy_send_timeout 300s;
client_max_body_size 512m;
}
}
```
#### 3b. 重载 main-nginx
```bash
cd /opt/ALiYunManager
docker-compose exec nginx nginx -t && docker-compose exec nginx nginx -s reload
```
#### 3c. beian-nginx 追加中转
```bash
# 备份
cp /opt/beian-docker/nginx.conf /opt/beian-docker/nginx.conf.bak.$(date +%Y%m%d_%H%M)
# 编辑配置,追加以下 server 块
vim /opt/beian-docker/nginx.conf
```
`http {}` 内追加:
```nginx
# Gitea 私有 Git 仓库
server {
listen 80;
server_name git.dxz99wyr.cn;
location / {
proxy_pass http://172.19.0.1:8080;
proxy_http_version 1.1;
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 300s;
proxy_send_timeout 300s;
client_max_body_size 512m;
}
}
```
```bash
docker exec beian-nginx nginx -t && docker exec beian-nginx nginx -s reload
```
### 步骤 4DNS 解析
阿里云域名控制台添加:
| 记录类型 | 主机记录 | 记录值 |
|---------|---------|--------|
| A | git | 8.136.137.59 |
### 步骤 5:初始化 Gitea
1. 浏览器访问 `http://git.dxz99wyr.cn`
2. 首次访问进入安装页(大部分配置已由 docker-compose.yml 环境变量预设)
3. 设置管理员账号:
- 用户名:`admin`
- 密码:**设置强密码并牢记**
- 邮箱:`admin@dxz99wyr.cn`
4. 点击「安装 Gitea」
### 步骤 6:创建 Gitea 访问令牌(供 Webhook 脚本拉取代码用)
1. Gitea Web UI → 右上角头像 → **Settings****Applications**
2. **Generate New Token**
- Token Name`deploy-token`
- 权限:勾选 `read:repository`
3. 复制生成的 Token(只显示一次),保存备用
### 步骤 7:创建仓库
在 Gitea Web UI 中创建:
| 仓库名 | 用途 |
|--------|------|
| `aliyun-manager` | ALiYunManager 部署项目 |
| `resume-web` | 个人简历前端 |
| `resume-api` | 个人简历后台 |
| `miniapp-web` | 小程序前端 |
| `miniapp-api` | 小程序后台 |
---
## 三、Webhook 自动部署流水线
```
git push → Gitea → Webhook POST → webhook:9000/hooks/xxx → 对应脚本 → clone/pull → docker-compose 重建
```
### 步骤 8:构建 Webhook 自定义镜像
创建 `/home/Git/webhook/Dockerfile`
```dockerfile
# ============================================
# Webhook 接收器自定义镜像
# 内置: docker CLI + git + bash + webhook 二进制
# ============================================
FROM docker:cli
RUN apk add --no-cache git bash curl
ARG WEBHOOK_VERSION=2.8.1
ADD https://github.com/adnanh/webhook/releases/download/${WEBHOOK_VERSION}/webhook-linux-amd64.tar.gz /tmp/
RUN tar -xzf /tmp/webhook-linux-amd64.tar.gz -C /usr/local/bin/ webhook && \
chmod +x /usr/local/bin/webhook && \
rm /tmp/webhook-linux-amd64.tar.gz
WORKDIR /opt/webhook
ENTRYPOINT ["/usr/local/bin/webhook"]
```
### 步骤 9:创建 Webhook 配置文件
#### 9a. 环境变量 `/home/Git/webhook/.env`
```bash
# Gitea 访问令牌(步骤 6 中生成的)
GITEA_TOKEN=粘贴你的token到这里
# 各个 Webhook Secret(随机生成,与 Gitea Webhook 设置保持一致)
SECRET_RESUME_WEB=resume-web-deploy-secret
SECRET_RESUME_API=resume-api-deploy-secret
SECRET_ALIYUN_MANAGER=aliyun-manager-deploy-secret
SECRET_MINIAPP_WEB=miniapp-web-deploy-secret
```
#### 9b. Webhook 路由 `/home/Git/webhook/hooks.json`
```json
[
{
"id": "resume-web",
"execute-command": "/opt/webhook/scripts/deploy-resume-web.sh",
"command-working-directory": "/opt/webhook/scripts",
"trigger-rule": {
"match": {
"type": "value",
"value": "resume-web-deploy-secret",
"parameter": {
"source": "payload",
"name": "secret"
}
}
}
},
{
"id": "resume-api",
"execute-command": "/opt/webhook/scripts/deploy-resume-api.sh",
"command-working-directory": "/opt/webhook/scripts",
"trigger-rule": {
"match": {
"type": "value",
"value": "resume-api-deploy-secret",
"parameter": {
"source": "payload",
"name": "secret"
}
}
}
},
{
"id": "aliyun-manager",
"execute-command": "/opt/webhook/scripts/deploy-aliyun-manager.sh",
"command-working-directory": "/opt/webhook/scripts",
"trigger-rule": {
"match": {
"type": "value",
"value": "aliyun-manager-deploy-secret",
"parameter": {
"source": "payload",
"name": "secret"
}
}
}
},
{
"id": "miniapp-web",
"execute-command": "/opt/webhook/scripts/deploy-miniapp-web.sh",
"command-working-directory": "/opt/webhook/scripts",
"trigger-rule": {
"match": {
"type": "value",
"value": "miniapp-web-deploy-secret",
"parameter": {
"source": "payload",
"name": "secret"
}
}
}
}
]
```
#### 9c. docker-compose `/home/Git/webhook/docker-compose.yml`
```yaml
version: "3.8"
services:
webhook:
build: .
image: webhook-receiver:latest
container_name: webhook
restart: always
ports:
- "9000:9000"
env_file:
- .env
volumes:
# Webhook 配置(只读)
- /home/Git/webhook/hooks.json:/opt/webhook/hooks.json:ro
- /home/Git/webhook/scripts:/opt/webhook/scripts:ro
# 部署日志(读写)
- /home/Git/logs:/opt/webhook/logs
# 宿主机 Docker 控制权
- /var/run/docker.sock:/var/run/docker.sock
# 各项目代码目录(用于 git pull 更新)
- /opt/ALiYunManager:/opt/ALiYunManager
- /opt/services/resume-web:/opt/services/resume-web
- /opt/services/resume-api:/opt/services/resume-api
- /opt/services/miniapp-web:/opt/services/miniapp-web
networks:
- webhook-network
command:
- "-hooks=/opt/webhook/hooks.json"
- "-verbose"
- "-hot-reload"
networks:
webhook-network:
driver: bridge
name: aliyun-app-network
```
> **说明**
> - `-hot-reload`:修改 hooks.json 后无需重启容器
> - 代码目录挂载:webhook 容器直接 git pull 到这些目录,然后通过 docker.sock 执行 docker-compose
> - 容器内部通过 HTTP 访问 gitea`http://gitea:3000`,无需 SSH
#### 9d. 通用部署函数 `/home/Git/webhook/scripts/deploy-common.sh`
```bash
#!/bin/bash
# ============================================
# 通用部署函数库
# 被各服务脚本 source 引用
# 运行在 webhook 容器内
# ============================================
set -e
LOG_DIR="/opt/webhook/logs"
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
log() {
local SERVICE=$1
local MESSAGE=$2
echo "[$TIMESTAMP] [$SERVICE] $MESSAGE" | tee -a "$LOG_DIR/deploy.log"
}
# 从 Gitea 拉取最新代码(Docker 内网 HTTP
# 参数: REPO_NAME GIT_DIR BRANCH
# 使用 GITEA_TOKEN 环境变量认证
clone_or_pull() {
local REPO_NAME=$1
local GIT_DIR=$2
local BRANCH=${3:-main}
local REPO_URL="http://${GITEA_TOKEN}@gitea:3000/admin/${REPO_NAME}.git"
if [ -d "$GIT_DIR/.git" ]; then
log "git" "拉取最新代码: ${REPO_NAME}${GIT_DIR} (分支: ${BRANCH})"
cd "$GIT_DIR"
git fetch origin
git reset --hard "origin/${BRANCH}"
else
log "git" "克隆仓库: ${REPO_NAME}${GIT_DIR} (分支: ${BRANCH})"
git clone -b "$BRANCH" "$REPO_URL" "$GIT_DIR"
fi
}
# 重建并重启 Docker 服务
# 参数: COMPOSE_DIR SERVICE_NAME
docker_rebuild() {
local COMPOSE_DIR=$1
local SERVICE_NAME=$2
cd "$COMPOSE_DIR"
if [ -f "Dockerfile" ]; then
log "$SERVICE_NAME" "构建镜像..."
docker-compose build "$SERVICE_NAME"
fi
log "$SERVICE_NAME" "重启容器..."
docker-compose up -d --no-deps --force-recreate "$SERVICE_NAME"
log "$SERVICE_NAME" "部署完成"
}
```
> **关键点**`clone_or_pull` 使用 `http://${GITEA_TOKEN}@gitea:3000/...` 格式,
> Gitea 和 webhook 同属 `aliyun-app-network`,直接用容器名 `gitea:3000` 通信,
> 不经过外网,也不需要 SSH。
#### 9e. 各服务部署脚本
**个人简历前端** `/home/Git/webhook/scripts/deploy-resume-web.sh`
```bash
#!/bin/bash
source /opt/webhook/scripts/deploy-common.sh
SERVICE="resume-web"
REPO_NAME="resume-web"
GIT_DIR="/opt/services/resume-web"
BRANCH="main"
log "$SERVICE" "========== 开始部署 =========="
clone_or_pull "$REPO_NAME" "$GIT_DIR" "$BRANCH"
docker_rebuild "$GIT_DIR" "$SERVICE"
log "$SERVICE" "========== 部署完成 =========="
```
**个人简历后台** `/home/Git/webhook/scripts/deploy-resume-api.sh`
```bash
#!/bin/bash
source /opt/webhook/scripts/deploy-common.sh
SERVICE="resume-api"
REPO_NAME="resume-api"
GIT_DIR="/opt/services/resume-api"
BRANCH="main"
log "$SERVICE" "========== 开始部署 =========="
clone_or_pull "$REPO_NAME" "$GIT_DIR" "$BRANCH"
docker_rebuild "$GIT_DIR" "$SERVICE"
log "$SERVICE" "========== 部署完成 =========="
```
**ALiYunManagernginx 配置部署)** `/home/Git/webhook/scripts/deploy-aliyun-manager.sh`
```bash
#!/bin/bash
source /opt/webhook/scripts/deploy-common.sh
SERVICE="aliyun-manager"
REPO_NAME="aliyun-manager"
GIT_DIR="/opt/ALiYunManager"
BRANCH="main"
log "$SERVICE" "========== 开始部署 =========="
clone_or_pull "$REPO_NAME" "$GIT_DIR" "$BRANCH"
cd "$GIT_DIR"
# 重载 main-nginx 配置(不重启容器,零停机)
docker-compose exec -T nginx nginx -t && docker-compose exec -T nginx nginx -s reload
log "$SERVICE" "main-nginx 配置已重载"
log "$SERVICE" "========== 部署完成 =========="
```
**小程序前端** `/home/Git/webhook/scripts/deploy-miniapp-web.sh`
```bash
#!/bin/bash
source /opt/webhook/scripts/deploy-common.sh
SERVICE="miniapp-web"
REPO_NAME="miniapp-web"
GIT_DIR="/opt/services/miniapp-web"
BRANCH="main"
log "$SERVICE" "========== 开始部署 =========="
clone_or_pull "$REPO_NAME" "$GIT_DIR" "$BRANCH"
docker_rebuild "$GIT_DIR" "$SERVICE"
log "$SERVICE" "========== 部署完成 =========="
```
### 步骤 10:构建并启动 Webhook 容器
```bash
# 赋予脚本执行权限
chmod +x /home/Git/webhook/scripts/*.sh
# 构建自定义镜像并启动
cd /home/Git/webhook
docker-compose build
docker-compose up -d
# 验证
docker-compose ps
docker-compose logs -f
```
---
## 四、Gitea Webhook 配置
对每个仓库,在 Gitea Web UI 中操作:
### 配置步骤
1. 进入仓库 → **Settings****Webhooks**
2. 点击 **Add Webhook** → 选择 **Gitea**
3. 填写:
| 字段 | 值 |
|------|-----|
| Target URL | `http://webhook:9000/hooks/resume-web`(对应 hooks.json 中的 id |
| HTTP Method | `POST` |
| POST Content Type | `application/json` |
| Secret | `resume-web-deploy-secret`(与 hooks.json 和 .env 一致) |
| Trigger On | 勾选 **Push** |
4. 点击 **Add Webhook**
5. 点击 **Test Delivery** 验证
### 各仓库 Webhook 配置汇总
| 仓库 | Target URL | Secret |
|------|-----------|--------|
| `resume-web` | `http://webhook:9000/hooks/resume-web` | `resume-web-deploy-secret` |
| `resume-api` | `http://webhook:9000/hooks/resume-api` | `resume-api-deploy-secret` |
| `aliyun-manager` | `http://webhook:9000/hooks/aliyun-manager` | `aliyun-manager-deploy-secret` |
| `miniapp-web` | `http://webhook:9000/hooks/miniapp-web` | `miniapp-web-deploy-secret` |
> Gitea 和 webhook 同属 `aliyun-app-network`,用容器名 `webhook` 直接通信。
---
## 五、本地开发环境配置
### 个人 Git 配置
```bash
git config --global user.name "Your Name"
git config --global user.email "your-email@example.com"
```
### SSH 密钥(用于 git push
```bash
# 生成密钥(如果还没有)
ssh-keygen -t ed25519 -C "your-email@example.com"
# 将公钥添加到 Gitea
cat ~/.ssh/id_ed25519.pub
# Gitea Web UI → Settings → SSH/GPG Keys → Add Key 粘贴
```
### 关联远程仓库并推送
```bash
# 以 resume-web 为例
cd D:\003_Project\ALiYunManager\services\resume-web
git init
git add .
git commit -m "init"
# 添加远程仓库(走 SSH,端口 2222)
git remote add origin ssh://git@8.136.137.59:2222/admin/resume-web.git
# 推送(此后每次推送自动触发服务器部署)
git push -u origin main
```
### SSH 别名(可选,简化地址)
编辑 `~/.ssh/config`
```
Host gitea
HostName 8.136.137.59
Port 2222
User git
IdentityFile ~/.ssh/id_ed25519
```
之后:
```bash
git clone gitea:admin/resume-web.git
```
### 日常开发流程
```bash
git add .
git commit -m "feat: 更新xxx"
git push
# ↑ 推送后自动触发 Webhook → 服务器自动拉代码并部署,无需手动 ssh
```
---
## 六、安全设计
| 措施 | 说明 |
|------|------|
| 禁用公开注册 | `DISABLE_REGISTRATION=true` |
| Webhook 仅内网可达 | 9000 端口无宿主机映射,仅 Docker 网络内 gitea 可调用 |
| 独立 Secret | 每个仓库使用不同的 Webhook Secret |
| 令牌最小权限 | Gitea Token 仅勾选 `read:repository`,只能拉代码 |
| Token 存于 .env | 不硬编码在脚本中,`.env` 文件权限 600 |
| docker.sock 隔离 | webhook 是唯一挂载 docker.sock 的辅助容器,不对外暴露端口 |
---
## 七、完整部署清单(执行顺序)
| # | 操作 | 位置 |
|---|------|------|
| 1 | `mkdir -p /home/Git/{gitea/data,webhook/scripts,logs}` | 服务器 |
| 2 | 部署 Gitea 容器 | `/home/Git/gitea/docker-compose.yml` |
| 3 | 重载 main-nginxgit.conf 已就绪) | `/opt/ALiYunManager/` |
| 4 | beian-nginx 追加 git 中转 + 重载 | `/opt/beian-docker/nginx.conf` |
| 5 | DNS 添加 `git` A 记录 → `8.136.137.59` | 阿里云控制台 |
| 6 | Gitea Web 安装 + 管理员注册 | `http://git.dxz99wyr.cn` |
| 7 | 生成 Gitea Access Token (read:repository) | Gitea Settings → Applications |
| 8 | 创建各项目仓库 | Gitea Web UI |
| 9 | 填写 `/home/Git/webhook/.env`GITEA_TOKEN + Secrets| 服务器 |
| 10 | 写入 hooks.json + 各部署脚本 | `/home/Git/webhook/` |
| 11 | 构建自定义镜像 + 启动 webhook 容器 | `/home/Git/webhook/` |
| 12 | 每个仓库配置 Webhook | Gitea Web UI |
| 13 | 本地推送测试自动部署 | 开发机 |
---
## 八、故障排查
### Webhook 不触发
```bash
docker logs webhook -f
# Gitea Web UI → Settings → Webhooks → Recent Deliveries 查看投递状态
```
### 部署脚本报错
```bash
# 查看部署日志
tail -f /home/Git/logs/deploy.log
# 进入容器手动测试
docker exec -it webhook sh
cd /opt/webhook/scripts
bash deploy-resume-web.sh
```
### Git clone 认证失败
```bash
# 检查 Token 是否正确
docker exec webhook env | grep GITEA_TOKEN
# 测试容器内能否访问 Gitea
docker exec webhook curl -s http://gitea:3000/api/v1/version
```
### Gitea 无法访问
```bash
docker ps | grep gitea
docker network inspect aliyun-app-network | grep gitea
docker logs gitea -f
```
---
## 九、ICP 备案提醒
`git.dxz99wyr.cn` 页面底部中间必须显示:
`浙ICP备2026030774号-1` 并链接到 `https://beian.miit.gov.cn`
配置方式:Gitea 管理后台 → 自定义 → Footer HTML。
+57
View File
@@ -0,0 +1,57 @@
# ============================================
# Makefile - 简化常用操作
# ============================================
.PHONY: help deploy up down restart status logs reload ssl init backup update
help:
@echo "可用命令:"
@echo " make deploy - 首次部署所有服务"
@echo " make up - 启动服务"
@echo " make down - 停止服务"
@echo " make restart - 重启所有服务"
@echo " make status - 查看服务状态"
@echo " make logs - 查看主 Nginx 日志"
@echo " make reload - 重载 Nginx 配置(不重启)"
@echo " make ssl - 配置 SSL 证书"
@echo " make init - 初始化服务器(安装 Docker"
@echo " make backup - 备份配置"
@echo " make update S=xxx - 更新指定服务"
deploy:
./deploy.sh
up:
docker-compose up -d
down:
docker-compose down
restart:
docker-compose restart
status:
docker-compose ps
logs:
docker-compose logs -f nginx
reload:
docker-compose exec nginx nginx -s reload
ssl:
./scripts/setup-ssl.sh
init:
./scripts/init-server.sh
backup:
./scripts/backup.sh
update:
@if [ -z "$(S)" ]; then \
echo "用法: make update S=resume-web"; \
echo "可用服务: resume-web, miniapp-web, resume-api, miniapp-api"; \
exit 1; \
fi
./scripts/update-service.sh $(S)
+334
View File
@@ -0,0 +1,334 @@
# ALiYunManager 项目上下文 (AI可读)
> 本文档供 AI 助手快速理解项目部署环境、架构和服务状态,避免做出与现有环境冲突的操作。
---
## 一、服务器信息
| 项目 | 值 |
|------|-----|
| 公网 IP | `8.136.137.59` |
| 根域名 | `dxz99wyr.cn` |
| 操作系统 | Ubuntu (5.15.0-174-generic) |
| SSH 连接命令 | `ssh -i "D:\003_Project\小程序连接.pem" root@8.136.137.59` |
| SSH 密钥路径 | `D:\003_Project\小程序连接.pem` |
| 服务器项目路径 | `/opt/ALiYunManager` |
---
## 二、全量子域名规划
### 已部署 / 进行中
| 子域名 | 用途 | 类型 | 状态 |
|--------|------|------|------|
| `me.dxz99wyr.cn` | 个人简历网站 | 前端 | 🔧 进行中 |
| `www.dxz99wyr.cn` | 小程序网站 | 前端 | ✅ 使用中 [后续替换到二级域名] |
| `api-resume.dxz99wyr.cn` | 个人简历后台 API | 后端 | ⏳ 占位,待实现 |
| `api-miniapp.dxz99wyr.cn` | 小程序后台 API | 后端 | ✅ 已接入真实后端 (:3000) |
### 待开发
| 子域名 | 用途 | 类型 | 状态 |
|--------|------|------|------|
| `img.dxz99wyr.cn` | 图床网站 | 服务 | 📋 待开发 |
| `dash.dxz99wyr.cn` | 服务监控网站 | 服务 | 🔧 部署中(详见 `Dash.md` |
| `logs.dxz99wyr.cn` | 日志监控网站 | 服务 | 📋 待开发 |
| `git.dxz99wyr.cn` | 私有 Git 仓库 + CI/CD | 服务 | 🔧 部署中(详见 `Git.md` |
> DNS A 记录:所有子域名均指向 `8.136.137.59`,已经在阿里云域名控制台配置。
>
> **ICP 备案合规要求**:所有涉及二级域名对外展示的页面,**一律在页面底部中间位置**添加 ICP 备案号 `浙ICP备2026030774号-1`,并链接到 `https://beian.miit.gov.cn`。这是法律合规要求,新增任何服务时不可遗漏。
### 待开发服务说明
**1. 图床网站 `img.dxz99wyr.cn`**
- 用途:存储个人网站(me.dxz99wyr.cn)上传的图片内容,提供图片外链
- 需要:图片上传接口、存储管理、访问权限控制
**2. 服务监控网站 `dash.dxz99wyr.cn`**
- 用途:在线监控服务器 CPU、内存、磁盘使用率
- 监控各 Docker 容器的运行状态(up/down/restart
- 监控系统各端口的占用状态、对应服务
- 可选方案:Grafana + Prometheus、或轻量自建面板
**3. 日志网站 `logs.dxz99wyr.cn`**
- 用途:汇总展示所有 Docker 容器的运行日志
- 提供历史和实时日志查看
- 支持按服务、时间过滤
- 可选方案:ELK (Elasticsearch + Logstash + Kibana)、Grafana Loki、或自建简易面板
**4. 私有 Git 仓库 `git.dxz99wyr.cn`**
- 用途:存档所有项目的源代码(包括本 ALiYunManager 项目)
- 配套 CI/CD:配置 Git Webhook + 脚本,实现 `git push` 后自动拉取代码并部署到对应服务,不再需要手动 ssh 部署
- 可选方案:Gitea(轻量)、GitLab CE、Gogs
---
## 三、端口分配(关键:防止冲突)
### 对外网开放的端口
| 端口 | 用途 | 备注 |
|------|------|------|
| `22` | SSH | 必须保持 |
| `80` | HTTP 入口 | 由 **beian-nginx**(现有)占用 |
| `443` | HTTPS 入口 | 由 **beian-nginx**(现有)占用 |
### 内部端口(不对外网)
| 端口 | 用途 | 备注 |
|------|------|------|
| `8080` | main-nginx HTTP | Docker 容器内 80 → 宿主机 8080 |
| `8443` | main-nginx HTTPS | Docker 容器内 443 → 宿主机 8443 |
| `3000` | 小程序后端 | `quanyixiaozhushou-app`,仅本地回环访问 |
### 端口冲突规则
- **绝对不要占用 80/443** — 已被 beian-nginx 使用,新增服务必须挂到 main-nginx 后面(通过 Docker 网络内部 80 通信)
- **绝对不要占用 8080** — 已被 main-nginx 映射使用
- **绝对不要暴露 3000 到外网** — 小程序后端已关闭外网访问,仅走本地回环
- 新增服务容器内部一律使用 `80` 端口,通过 Docker 网络互通,**不要额外映射宿主机端口**
- **新增待开发服务(img/dash/logs/git)同理**,全部挂到 main-nginx 后面,内部 80 通信,不暴露新端口到外网
---
## 四、现有 Nginx 链路(两层代理)
```
外网请求
┌─────────────────────────────────────────────────────────┐
│ beian-nginx (宿主机 :80/:443) │ ← 第1层:入口
│ 容器名: beian-nginx │
│ 所属网络: beian-docker_default │
│ │
│ 目前已配置中转: │
│ ✅ me.dxz99wyr.cn → :8080 │
│ ✅ www.dxz99wyr.cn → :8080 │
│ ✅ api-resume.dxz99wyr.cn → :8080 │
│ ✅ api-miniapp.dxz99wyr.cn → :8080 │
│ ✅ git.dxz99wyr.cn → :8080 │
│ ✅ dash.dxz99wyr.cn → :8080 │
│ ✅ /quanyi → 静态页面 (原有服务) │
└──────────────┬──────────────────────────────────────────┘
│ 中转请求到 172.19.0.1:8080 (Docker网关=宿主机)
┌─────────────────────────────────────────────────────────┐
│ main-nginx (Docker :8080/:8443) │ ← 第2层:分发
│ 容器名: main-nginx │
│ 所属网络: aliyun-app-network │
│ │
│ 路由表 (已配置): │
│ me.dxz99wyr.cn → resume-web:80 │
│ www.dxz99wyr.cn → miniapp-web:80 │
│ api-resume.dxz99wyr.cn → resume-api:80 │
│ api-miniapp.dxz99wyr.cn → host.docker.internal:3000 │
│ │
│ 路由表 (待添加,新服务上线时): │
│ img.dxz99wyr.cn → img-service:80 │
│ dash.dxz99wyr.cn → dash-service:80 │
│ logs.dxz99wyr.cn → logs-service:80 │
│ git.dxz99wyr.cn → git-service:80 │
└──────────────┬──────────────────────────────────────────┘
│ Docker 内部网络
┌──────────┼──────────┬──────────┐
│ │ │ │
resume-web miniapp-web resume-api miniapp-api
(进行中) (使用中) (占位) (→宿主机:3000)
```
### 关键理解
- **beian-nginx 是真正的入口**main-nginx 只在内部做二级分发
- **beian-nginx 配置文件位置**: `/opt/beian-docker/nginx.conf`(映射到容器内 `/etc/nginx/conf.d/default.conf`
- **修改 beian-nginx 前必须先备份**: 备份文件在 `/opt/beian-docker/nginx.conf.bak`
- 重载 beian-nginx: `docker exec beian-nginx nginx -t && docker exec beian-nginx nginx -s reload`
---
## 五、Docker 容器清单
| 容器名 | 镜像 | 网络 | 端口映射 | 说明 |
|--------|------|------|----------|------|
| `beian-nginx` | nginx | beian-docker_default | 80:80, 443:443 | **现有,勿动基础配置** |
| `main-nginx` | nginx:alpine | aliyun-app-network | 8080:80, 8443:443 | 主 Nginx,本项目管理 |
| `resume-web` | nginx:alpine | aliyun-app-network | 无(内部80) | 个人简历网站(进行中) |
| `miniapp-web` | nginx:alpine | aliyun-app-network | 无(内部80) | 小程序网站(使用中) |
| `resume-api` | nginx:alpine | aliyun-app-network | 无(内部80) | 个人简历后台(占位) |
| `miniapp-api` | nginx:alpine | aliyun-app-network | 无(内部80) | 小程序后台占位容器 |
| `quanyixiaozhushou-app` | 自有镜像 | beian-docker_default | 3000:3000 | **现有小程序后端,勿动** |
| `quanyixiaozhushou-mongo` | mongo | beian-docker_default | 27018:27017 | **现有 MongoDB,勿动** |
### Docker 网络
| 网络名 | 类型 | 用途 |
|--------|------|------|
| `aliyun-app-network` | bridge | 本项目所有服务容器互通 |
| `beian-docker_default` | bridge | 现有 beian-nginx 及小程序后端 |
> **注意**: main-nginx 通过 `extra_hosts: host.docker.internal:host-gateway` 访问宿主机端口(如 3000),不需要两个网络互通。
---
## 六、项目文件结构
```
ALiYunManager/
├── .env # 环境变量(域名+端口),修改后需重启
├── .env.example # 环境变量模板
├── docker-compose.yml # 完整部署(main-nginx + 4个服务)
├── docker-compose.main-nginx-only.yml # 仅主 Nginx(各服务独立部署时用)
├── docker-compose.override.yml # 开发环境覆盖(自动加载)
├── deploy.sh # 一键部署脚本
├── Makefile # 常用命令快捷方式
├── nginx/
│ ├── nginx.conf # 主 Nginx 核心配置(一般不改)
│ ├── conf.d/
│ │ ├── resume-web.conf # me.dxz99wyr.cn → resume-web:80
│ │ ├── miniapp-web.conf # www.dxz99wyr.cn → miniapp-web:80
│ │ ├── resume-api.conf # api-resume.dxz99wyr.cn → resume-api:80
│ │ ├── miniapp-api.conf # api-miniapp.dxz99wyr.cn → host.docker.internal:3000
│ │ ├── ssl-template.conf # HTTPS 配置模板(按需取消注释)
│ │ └── port-based-example.conf # 基于端口的备选方案模板
│ ├── ssl/ # SSL 证书目录(.gitignore 排除)
│ └── logs/ # Nginx 日志目录
├── services/
│ ├── resume-web/ # 个人简历前端(进行中)
│ │ ├── html/index.html # 占位页面 → 替换为真实简历
│ │ ├── nginx.conf # 内部 Nginx 配置
│ │ ├── Dockerfile # 前端 Dockerfile
│ │ └── docker-compose.yml # 独立部署配置
│ ├── miniapp-web/ # 小程序前端(使用中)
│ ├── resume-api/ # 个人简历后台(占位)
│ │ ├── nginx.conf # 内部 Nginx(占位)
│ │ ├── Dockerfile # 模板,含 Node/Python/Go 示例
│ │ └── docker-compose.yml # 独立部署配置
│ └── miniapp-api/ # 小程序后台(占位 → 实际走宿主机3000)
└── scripts/
├── init-server.sh # 新服务器初始化(安装 Docker 等)
├── setup-ssl.sh # SSL 证书申请(Certbot
├── update-service.sh # 更新单个服务
├── backup.sh # 备份配置和证书
└── logrotate-nginx # 日志轮转配置
```
---
## 七、环境变量(.env 当前值)
```
DOMAIN_RESUME_WEB=me.dxz99wyr.cn
DOMAIN_MINIAPP_WEB=www.dxz99wyr.cn
DOMAIN_RESUME_API=api-resume.dxz99wyr.cn
DOMAIN_MINIAPP_API=api-miniapp.dxz99wyr.cn
NGINX_HTTP_PORT=8080
NGINX_HTTPS_PORT=8443
TZ=Asia/Shanghai
# -- 待开发服务(上线时取消注释) --
# DOMAIN_IMG=img.dxz99wyr.cn
# DOMAIN_DASHBOARD=dash.dxz99wyr.cn
# DOMAIN_LOGS=logs.dxz99wyr.cn
# DOMAIN_GIT=git.dxz99wyr.cn
```
---
## 八、操作注意事项(AI 助手必读)
### 全局铁律(所有新增内容必须遵守)
**规则 1 — 文件存储路径**
- 所有新增项目的文件**一律存储在 `/home/` 目录下**,子目录以项目名命名(如 `/home/Git/``/home/Dash/`)。
- **能放在 Docker 容器里的,就不要放在宿主机上**。配置文件、脚本等通过 volume 挂载进容器,不要在宿主机直接运行。
**规则 2 — 脚本后台运行 & 开机自启**
- 所有需要持续运行的脚本/服务,启动时必须使用后台方式(nohup、screen、tmux 或 Docker 容器),**保证关闭 SSH 会话后不受影响**。
- 必须配置**开机自启动**,云服务器重启后自动恢复运行。
- Docker 容器:`restart: always`(已在所有 docker-compose.yml 中统一配置)
- 宿主机脚本/进程:必须配置 systemd service 或 crontab `@reboot` 条目
- Docker 守护进程自启:`systemctl enable docker`(已由 `scripts/init-server.sh` 配置)
**规则 3 — SSL 证书自动化**
- 所有涉及在线 Web 访问的服务,**必须通过 Certbot 自动配置 SSL 证书**(参考 `scripts/setup-ssl.sh`)。
- 证书到期前 3 天**自动续期**,通过 crontab 定时任务实现:
```
0 3 * * * certbot renew --quiet --deploy-hook 'docker exec main-nginx nginx -s reload'
```
- 新增服务上线时,同步更新 certbot 证书覆盖的域名列表。
**规则 4 — 优先使用国内镜像源**
- 所有涉及下载的操作(pip install、npm install、apt-get、apk add、docker pull、git clone 等),**优先查找并使用国内镜像源**,提升下载速度。
- 常用国内源:
- Docker Hub:阿里云容器镜像服务、腾讯云 `mirror.ccs.tencentyun.com`
- Python pip:清华 `pypi.tuna.tsinghua.edu.cn`、阿里 `mirrors.aliyun.com/pypi/simple`
- Node.js npm:淘宝 `registry.npmmirror.com`
- Alpine apk:清华 `mirrors.tuna.tsinghua.edu.cn/alpine`、中科大 `mirrors.ustc.edu.cn/alpine`
- Debian/Ubuntu apt:阿里 `mirrors.aliyun.com/ubuntu`、清华 `mirrors.tuna.tsinghua.edu.cn/ubuntu`
- Git clone:优先使用 Docker 内网 HTTP(如 `http://gitea:3000/...`),不走外网
- Dockerfile 中 `RUN` 命令在安装包前先替换为国内源。
**规则 5 — 服务修改隔离**
- 修改某一服务时,**不准修改非该服务的内容**,包括但不限于:其他服务的网页页面、nginx 配置、反向代理规则、重定向、Docker 容器配置。
- 如果发现其他服务存在问题,**一律先告知用户**,不得自行改动。
- **用户未正面答复确认的**(如"知道了"、"先不管"、"改"等),AI 助手在之后的每次会话中,**都需要主动提醒用户**,直到用户给出正面答复为止。
### 绝对不能违反的合规要求
0. **所有二级域名的页面底部中间必须显示 ICP 备案号**:`浙ICP备2026030774号-1`,并链接到 `https://beian.miit.gov.cn`。新增任何服务时不可遗漏。
### 绝对不能做的事
1. **不要修改 beian-nginx 的基础配置**default_server、/quanyi 路径等),只能追加新的 server 块做域名中转
2. **不要改动 `nginx/nginx.conf`**(主 Nginx 核心配置),除非明确需要调整全局参数
3. **不要将 3000、8080、8443 端口暴露到外网**
4. **不要删除或停用 beian-nginx、quanyixiaozhushou-app、quanyixiaozhushou-mongo 容器**
5. **不要在 main-nginx 容器内直接改配置**,应修改本地 `nginx/conf.d/*.conf` 文件后重载
### 新增服务时的标准流程
1. 在 `/home/<项目名>/` 下创建项目目录(遵守规则 1
2. 所有服务逻辑放入 Docker 容器,宿主机仅保留 docker-compose.yml 和配置文件(遵守规则 1)
3. 在 `nginx/conf.d/` 下创建对应的反向代理 `.conf` 文件(参考已有配置)
4. 在 `.env` 中添加新子域名变量
5. 在本项目 `docker-compose.yml` 中添加新服务定义,确保 `restart: always`(遵守规则 2
6. 在 beian-nginx 中追加对应的中转 server 块
7. 在阿里云 DNS 添加子域名 A 记录
### 修改 beian-nginx 配置的标准流程
```bash
# 1. 备份当前配置
cp /opt/beian-docker/nginx.conf /opt/beian-docker/nginx.conf.bak.$(date +%Y%m%d)
# 2. 编辑配置(在 server 块区域追加新的域名中转)
vim /opt/beian-docker/nginx.conf
# 3. 测试配置
docker exec beian-nginx nginx -t
# 4. 重载
docker exec beian-nginx nginx -s reload
```
---
## 九、待办清单
| # | 事项 | 优先级 | 所属服务 |
|---|------|--------|----------|
| 1 | beian-nginx 补充中转配置(me、www、api-resume | ✅ 已完成 | 基础设施 |
| 2 | 替换 `services/resume-web/html/` 为真实简历代码 | 🔴 高 | me.dxz99wyr.cn |
| 3 | 实现个人简历后台真实后端代码(`services/resume-api/` | 🟡 中 | api-resume.dxz99wyr.cn |
| 4 | 配置 HTTPS / SSL 证书(运行 `./scripts/setup-ssl.sh` | 🟡 中 | 全部 |
| 5 | 新建图床服务 `img.dxz99wyr.cn` | 🟢 低 | img |
| 6 | 部署监控面板 `dash.dxz99wyr.cn`Dashy + Netdata + 状态API | 🔧 进行中 | dash |
| 7 | 新建日志面板 `logs.dxz99wyr.cn`(汇总所有 Docker 日志) | 🟢 低 | logs |
| 8 | 部署私有 Git 仓库 `git.dxz99wyr.cn`Gitea + Webhook 自动部署) | 🔧 进行中 | git |
| 9 | 配置 Git Webhook + 自动部署流水线(git push → 自动拉代码部署) | 🔧 进行中 | git/CICD |
| 10 | 配置日志轮转 (logrotate) | 🟢 低 | 基础设施 |
| 11 | 小程序网站后续替换为二级域名 | 🟢 低 | www.dxz99wyr.cn |
+122
View File
@@ -0,0 +1,122 @@
# 快速开始指南
## 方案一:完整部署(所有服务一起管理)
适用于所有服务代码都在同一个项目中管理。
### 1. 初始化服务器(如果是新服务器)
```bash
ssh -i "小程序连接.pem" root@8.136.137.59
cd /opt
git clone <你的仓库地址> ALiYunManager
cd ALiYunManager
./scripts/init-server.sh
```
### 2. 部署所有服务
```bash
./deploy.sh
```
### 3. 配置 DNS
在阿里云域名控制台添加解析:
| 记录类型 | 主机记录 | 记录值 |
|---------|---------|--------|
| A | me | 8.136.137.59 |
| A | www | 8.136.137.59 |
| A | api-resume | 8.136.137.59 |
| A | api-miniapp | 8.136.137.59 |
### 4. 配置 HTTPS
```bash
./scripts/setup-ssl.sh
```
按提示修改 `nginx/conf.d/` 下的配置文件启用 443 端口。
---
## 方案二:仅部署主 Nginx(各服务独立管理)
适用于各服务由不同项目/仓库管理,独立部署。
### 1. 部署主 Nginx
```bash
docker-compose -f docker-compose.main-nginx-only.yml up -d
```
### 2. 各服务独立部署
每个服务在自己的目录下有独立的 `docker-compose.yml`,例如:
```yaml
# services/resume-web/docker-compose.yml
version: "3.8"
services:
resume-web:
image: nginx:alpine
container_name: resume-web
restart: always
ports:
- "8081:80"
volumes:
- ./html:/usr/share/nginx/html:ro
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
networks:
- aliyun-app-network
networks:
aliyun-app-network:
external: true
```
主 Nginx 通过端口 `8081` 反向代理到该服务。
---
## 常用操作
```bash
# 查看所有容器状态
docker-compose ps
# 查看主 Nginx 日志
docker-compose logs -f nginx
# 查看某个服务日志
docker-compose logs -f resume-web
# 重启某个服务
docker-compose restart resume-web
# 重载 Nginx 配置(不重启容器)
docker-compose exec nginx nginx -s reload
# 更新单个服务
./scripts/update-service.sh resume-web
# 进入容器调试
docker-compose exec nginx sh
docker-compose exec resume-web sh
```
---
## 文件说明
| 文件/目录 | 说明 |
|-----------|------|
| `docker-compose.yml` | 完整部署配置(含示例服务) |
| `docker-compose.main-nginx-only.yml` | 仅主 Nginx |
| `nginx/nginx.conf` | 主 Nginx 核心配置 |
| `nginx/conf.d/*.conf` | 各服务的反向代理配置 |
| `nginx/ssl/` | SSL 证书目录 |
| `services/服务名/` | 各服务独立配置 |
| `scripts/` | 辅助脚本 |
| `.env` | 环境变量配置 |
+175
View File
@@ -0,0 +1,175 @@
# ALiYunManager - 阿里云多服务 Docker 部署方案
## 架构概览
```
┌─────────────────────────────────────────────────────────────┐
│ 阿里云服务器 (8.136.137.59) │
│ 主 Nginx (Docker 容器) │
│ ┌──────────┬──────────┬──────────────┬──────────────┐ │
│ │ me. │ www. │ api-resume. │api-miniapp. │ │
│ │dxz99wyr. │dxz99wyr. │ dxz99wyr.cn │dxz99wyr.cn │ │
│ │cn │cn │ │ │ │
│ └────┬─────┴────┬─────┴──────┬───────┴──────┬───────┘ │
│ │ │ │ │ │
│ ┌────▼─────┐ ┌──▼─────┐ ┌───▼──────┐ ┌────▼──────┐ │
│ │ Docker 1 │ │Docker 2│ │ Docker 3 │ │ Docker 4 │ │
│ │个人简历网站│ │小程序网站│ │个人简历后台│ │小程序后台 │ │
│ │内部Nginx │ │内部Nginx│ │内部Nginx │ │内部Nginx │ │
│ └──────────┘ └────────┘ └──────────┘ └───────────┘ │
└─────────────────────────────────────────────────────────────┘
```
## 域名规划
| 服务 | 域名 | 类型 |
|------|------|------|
| 个人简历网站 | `me.dxz99wyr.cn` | 前端 |
| 小程序网站 | `www.dxz99wyr.cn` | 前端 |
| 个人简历后台 | `api-resume.dxz99wyr.cn` | API |
| 小程序后台 | `api-miniapp.dxz99wyr.cn` | API |
## 目录结构
```
ALiYunManager/
├── docker-compose.yml # 主 Docker Compose 文件
├── deploy.sh # 部署脚本
├── README.md # 本文件
├── nginx/
│ ├── nginx.conf # 主 Nginx 核心配置(**不要修改**)
│ ├── conf.d/ # 各个服务的反向代理配置(由服务自行管理)
│ │ ├── resume-web.conf
│ │ ├── miniapp-web.conf
│ │ ├── resume-api.conf
│ │ └── miniapp-api.conf
│ ├── ssl/ # SSL 证书目录
│ └── logs/ # 日志目录
└── services/ # 各个服务的配置(每个服务自行管理)
├── resume-web/
│ ├── nginx.conf # 服务内部 Nginx 配置
│ └── html/ # 静态文件
├── miniapp-web/
│ ├── nginx.conf
│ └── html/
├── resume-api/
│ ├── nginx.conf # 内部 Nginx 配置或反向代理
│ └── Dockerfile # 后端 Dockerfile 模板
└── miniapp-api/
├── nginx.conf
└── Dockerfile
```
## 核心设计原则
1. **主 Nginx 只负责反向代理**:将外部请求按域名分发到各个 Docker 容器
2. **每个服务独立管理自己的配置**
- 每个服务在 `nginx/conf.d/` 下放一个 `.conf` 文件(主 Nginx 加载)
- 每个服务在 `services/服务名/` 下放自己的内部 Nginx 配置
3. **所有服务都在 Docker 容器中运行**:便于管理和隔离
4. **使用 Docker 内部网络通信**:主 Nginx 通过容器名直接访问服务
## 快速开始
### 1. 上传到服务器
```bash
# 在项目目录打包
zip -r aliyun-manager.zip ALiYunManager/
# 上传到服务器(使用你的密钥)
scp -i "D:\003_Project\小程序连接.pem" aliyun-manager.zip root@8.136.137.59:/opt/
```
### 2. 在服务器上部署
```bash
ssh -i "D:\003_Project\小程序连接.pem" root@8.136.137.59
cd /opt
unzip aliyun-manager.zip
cd ALiYunManager
chmod +x deploy.sh
./deploy.sh
```
### 3. 配置 DNS
在域名管理后台添加以下解析记录:
| 记录类型 | 主机记录 | 记录值 |
|---------|---------|--------|
| A | me | 8.136.137.59 |
| A | miniapp | 8.136.137.59 |
| A | api-resume | 8.136.137.59 |
| A | api-miniapp | 8.136.137.59 |
## 常用命令
```bash
# 启动所有服务
docker-compose up -d
# 停止所有服务
docker-compose down
# 查看主 Nginx 日志
docker-compose logs -f nginx
# 重启主 Nginx
docker-compose restart nginx
# 查看所有容器状态
docker-compose ps
# 重载 Nginx 配置(不重启容器)
docker-compose exec nginx nginx -s reload
```
## 配置 HTTPS (SSL)
### 方法一:使用 Certbot (推荐)
```bash
# 进入容器安装 certbot
docker-compose exec nginx sh
apk add certbot
# 申请证书(需要先确保 DNS 已解析)
certbot certonly --standalone -d me.dxz99wyr.cn -d www.dxz99wyr.cn -d api-resume.dxz99wyr.cn -d api-miniapp.dxz99wyr.cn
```
### 方法二:手动配置
将证书文件放入 `nginx/ssl/` 目录:
```
nginx/ssl/
├── me.dxz99wyr.cn.crt
├── me.dxz99wyr.cn.key
└── ...
```
然后修改对应服务的 `.conf` 文件,添加 443 监听和 SSL 配置。
## 各服务如何接入
### 前端网站接入
1. 将你的构建产物放入 `services/resume-web/html/` 目录
2. 如需修改内部 Nginx 配置,编辑 `services/resume-web/nginx.conf`
3. 如需修改反向代理规则,编辑 `nginx/conf.d/resume-web.conf`
4. 重启对应容器
### 后端 API 接入
1. 替换 `services/resume-api/Dockerfile` 为你的后端 Dockerfile
2. 修改 `services/resume-api/nginx.conf` 中的 `upstream` 指向你的应用端口
3. 如需修改反向代理规则,编辑 `nginx/conf.d/resume-api.conf`
4. 重新构建并启动容器
## 注意事项
1. **不要修改** `nginx/nginx.conf` 主配置文件,除非你需要调整全局参数
2. 各个服务的 `.conf` 文件命名不要冲突
3. 后端服务如果不需要内部 Nginx,可以直接暴露应用端口,主 Nginx 直接代理到应用端口
4. 生产环境建议开启防火墙,只开放 80 和 443 端口
+81
View File
@@ -0,0 +1,81 @@
#!/bin/bash
# ============================================
# 阿里云服务器 Docker 服务部署脚本
# ============================================
set -e
# 加载环境变量
if [ -f .env ]; then
set -a
source .env
set +a
fi
# 设置默认值
DOMAIN_RESUME_WEB=${DOMAIN_RESUME_WEB:-me.dxz99wyr.cn}
DOMAIN_MINIAPP_WEB=${DOMAIN_MINIAPP_WEB:-www.dxz99wyr.cn}
DOMAIN_RESUME_API=${DOMAIN_RESUME_API:-api-resume.dxz99wyr.cn}
DOMAIN_MINIAPP_API=${DOMAIN_MINIAPP_API:-api-miniapp.dxz99wyr.cn}
echo "=========================================="
echo " 阿里云服务器 Docker 服务部署脚本"
echo "=========================================="
# 检查 Docker 是否安装
if ! command -v docker &> /dev/null; then
echo "错误:Docker 未安装"
echo "运行 ./scripts/init-server.sh 进行初始化安装"
exit 1
fi
# 检查 Docker Compose 是否安装
if ! command -v docker-compose &> /dev/null; then
echo "错误:Docker Compose 未安装"
echo "运行 ./scripts/init-server.sh 进行初始化安装"
exit 1
fi
# 创建必要的目录
mkdir -p nginx/logs
mkdir -p nginx/ssl
mkdir -p services/resume-web/html
mkdir -p services/miniapp-web/html
echo ""
echo "检查 Docker 网络..."
if ! docker network ls | grep -q "aliyun-app-network"; then
echo "创建 Docker 网络: aliyun-app-network"
docker network create aliyun-app-network
fi
echo ""
echo "正在启动主 Nginx 及示例服务..."
docker-compose up -d --build
echo ""
echo "=========================================="
echo " 部署状态"
echo "=========================================="
docker-compose ps
echo ""
echo "=========================================="
echo " 服务访问地址"
echo "=========================================="
echo " 个人简历网站: http://${DOMAIN_RESUME_WEB}"
echo " 小程序网站: http://${DOMAIN_MINIAPP_WEB}"
echo " 个人简历后台: http://${DOMAIN_RESUME_API}"
echo " 小程序后台: http://${DOMAIN_MINIAPP_API}"
echo "=========================================="
echo ""
echo "下一步建议:"
echo " 1. 配置 DNS 解析(将域名指向 8.136.137.59"
echo " 2. 配置 HTTPS: ./scripts/setup-ssl.sh"
echo ""
echo "常用命令:"
echo " 查看日志: docker-compose logs -f nginx"
echo " 重载配置: docker-compose exec nginx nginx -s reload"
echo ""
+29
View File
@@ -0,0 +1,29 @@
# ============================================
# 仅主 Nginx 的 Docker Compose 配置
# 适用场景:各个服务独立部署,不与此文件一起管理
# ============================================
version: "3.8"
services:
nginx:
image: nginx:alpine
container_name: main-nginx
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
- ./nginx/logs:/var/log/nginx
networks:
- app-network
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
app-network:
driver: bridge
name: aliyun-app-network
+26
View File
@@ -0,0 +1,26 @@
# ============================================
# Docker Compose 开发环境覆盖配置
# 此文件会自动被 docker-compose 加载,无需显式指定
# ============================================
version: "3.8"
services:
nginx:
# 开发环境映射更多日志便于调试
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
- ./nginx/logs:/var/log/nginx
resume-web:
# 开发环境自动重载静态文件
volumes:
- ./services/resume-web/html:/usr/share/nginx/html:ro
- ./services/resume-web/nginx.conf:/etc/nginx/conf.d/default.conf:ro
miniapp-web:
volumes:
- ./services/miniapp-web/html:/usr/share/nginx/html:ro
- ./services/miniapp-web/nginx.conf:/etc/nginx/conf.d/default.conf:ro
+89
View File
@@ -0,0 +1,89 @@
version: "3.8"
services:
nginx:
image: nginx:alpine
container_name: main-nginx
restart: always
ports:
- "${NGINX_HTTP_PORT:-8080}:80"
- "${NGINX_HTTPS_PORT:-8443}:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
- ./nginx/logs:/var/log/nginx
networks:
- app-network
extra_hosts:
- "host.docker.internal:host-gateway"
depends_on:
- resume-web
- miniapp-web
- resume-api
- miniapp-api
env_file:
- .env
# 示例服务 - 个人简历网站
resume-web:
image: nginx:alpine
container_name: resume-web
restart: always
volumes:
- ./services/resume-web/html:/usr/share/nginx/html:ro
- ./services/resume-web/nginx.conf:/etc/nginx/conf.d/default.conf
networks:
- app-network
expose:
- "80"
env_file:
- .env
# 示例服务 - 小程序网站
miniapp-web:
image: nginx:alpine
container_name: miniapp-web
restart: always
volumes:
- ./services/miniapp-web/html:/usr/share/nginx/html:ro
- ./services/miniapp-web/nginx.conf:/etc/nginx/conf.d/default.conf
networks:
- app-network
expose:
- "80"
env_file:
- .env
# 示例服务 - 个人简历后台
resume-api:
image: nginx:alpine
container_name: resume-api
restart: always
volumes:
- ./services/resume-api/nginx.conf:/etc/nginx/conf.d/default.conf
networks:
- app-network
expose:
- "80"
env_file:
- .env
# 示例服务 - 小程序后台
miniapp-api:
image: nginx:alpine
container_name: miniapp-api
restart: always
volumes:
- ./services/miniapp-api/nginx.conf:/etc/nginx/conf.d/default.conf
networks:
- app-network
expose:
- "80"
env_file:
- .env
networks:
app-network:
driver: bridge
name: aliyun-app-network
+62
View File
@@ -0,0 +1,62 @@
# ============================================
# 运维监控面板 - dash.dxz99wyr.cn
# ============================================
# 上游定义
upstream dashy_upstream {
server dashy:8080;
}
upstream netdata_upstream {
server netdata:19999;
}
upstream dash_status_upstream {
# dash-status 使用 host 网络模式,通过宿主机访问
server host.docker.internal:5000;
}
# Dashy 主面板
server {
listen 80;
server_name dash.dxz99wyr.cn;
access_log /var/log/nginx/dash.access.log main;
error_log /var/log/nginx/dash.error.log warn;
# Dashy Web UI
location / {
proxy_pass http://dashy_upstream;
proxy_http_version 1.1;
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_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# Netdata 监控面板
location /netdata/ {
proxy_pass http://netdata_upstream/;
proxy_http_version 1.1;
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_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400s;
proxy_buffering off;
}
# Status API
location /api/ {
proxy_pass http://dash_status_upstream/api/;
proxy_http_version 1.1;
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;
}
}
+35
View File
@@ -0,0 +1,35 @@
# ============================================
# 私有 Git 仓库 - Gitea
# 服务名: gitea
# 由主 Nginx 反向代理,此文件可独立维护
# ============================================
server {
listen 80;
server_name git.dxz99wyr.cn;
# 日志
access_log /var/log/nginx/git.access.log main;
error_log /var/log/nginx/git.error.log warn;
# Gitea Web UI
location / {
proxy_pass http://gitea:3000;
proxy_http_version 1.1;
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_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Gitea 需要的较大超时
proxy_read_timeout 300s;
proxy_send_timeout 300s;
# 上传限制(Git push 通过 Web 可能较大)
client_max_body_size 512m;
}
}
+42
View File
@@ -0,0 +1,42 @@
# ============================================
# 小程序后台 - API 服务
# 接入现有后端 quanyixiaozhushou-app (宿主机3000端口)
# 由主 Nginx 反向代理,此文件可独立维护
# ============================================
server {
listen 80;
server_name api-miniapp.dxz99wyr.cn;
# 日志
access_log /var/log/nginx/miniapp-api.access.log main;
error_log /var/log/nginx/miniapp-api.error.log warn;
location / {
# 反向代理到宿主机的3000端口(quanyixiaozhushou-app后端)
proxy_pass http://host.docker.internal:3000;
proxy_http_version 1.1;
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 支持
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# CORS 头部
add_header Access-Control-Allow-Origin * always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" always;
if ($request_method = OPTIONS) {
return 204;
}
}
}
+36
View File
@@ -0,0 +1,36 @@
# ============================================
# 小程序网站 - 前端
# 服务名: miniapp-web
# 由主 Nginx 反向代理,此文件可独立维护
# ============================================
server {
listen 80;
server_name www.dxz99wyr.cn;
# 日志
access_log /var/log/nginx/miniapp-web.access.log main;
error_log /var/log/nginx/miniapp-web.error.log warn;
location / {
proxy_pass http://miniapp-web:80;
proxy_http_version 1.1;
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_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# 静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
proxy_pass http://miniapp-web:80;
proxy_set_header Host $host;
expires 30d;
add_header Cache-Control "public, immutable";
}
}
+64
View File
@@ -0,0 +1,64 @@
# ============================================
# 基于端口的反向代理配置示例(备选方案)
# ============================================
# 如果各个服务通过宿主机端口暴露(如 -p 8081:80),
# 主 Nginx 可以通过 host.docker.internal 或宿主机 IP 访问
# ============================================
# 示例:假设各服务映射端口如下:
# 简历网站: 8081
# 小程序网站: 8082
# 简历后台: 8083
# 小程序后台: 8084
# server {
# listen 80;
# server_name me.dxz99wyr.cn;
#
# location / {
# proxy_pass http://host.docker.internal:8081;
# 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;
# }
# }
#
# server {
# listen 80;
# server_name www.dxz99wyr.cn;
#
# location / {
# proxy_pass http://host.docker.internal:8082;
# 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;
# }
# }
#
# server {
# listen 80;
# server_name api-resume.dxz99wyr.cn;
#
# location / {
# proxy_pass http://host.docker.internal:8083;
# 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;
# }
# }
#
# server {
# listen 80;
# server_name api-miniapp.dxz99wyr.cn;
#
# location / {
# proxy_pass http://host.docker.internal:8084;
# 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;
# }
# }
+43
View File
@@ -0,0 +1,43 @@
# ============================================
# 个人简历后台 - API 服务
# 服务名: resume-api
# 由主 Nginx 反向代理,此文件可独立维护
# ============================================
server {
listen 80;
server_name api-resume.dxz99wyr.cn;
# 日志
access_log /var/log/nginx/resume-api.access.log main;
error_log /var/log/nginx/resume-api.error.log warn;
# 允许跨域(API 服务通常需要)
location / {
proxy_pass http://resume-api:80;
proxy_http_version 1.1;
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 支持(如需要)
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# CORS 头部
add_header Access-Control-Allow-Origin * always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" always;
# 预检请求处理
if ($request_method = OPTIONS) {
return 204;
}
}
}
+36
View File
@@ -0,0 +1,36 @@
# ============================================
# 个人简历网站 - 前端
# 服务名: resume-web
# 由主 Nginx 反向代理,此文件可独立维护
# ============================================
server {
listen 80;
server_name me.dxz99wyr.cn;
# 日志
access_log /var/log/nginx/resume-web.access.log main;
error_log /var/log/nginx/resume-web.error.log warn;
location / {
proxy_pass http://resume-web:80;
proxy_http_version 1.1;
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_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# 静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
proxy_pass http://resume-web:80;
proxy_set_header Host $host;
expires 30d;
add_header Cache-Control "public, immutable";
}
}
+40
View File
@@ -0,0 +1,40 @@
# ============================================
# SSL/HTTPS 配置模板
# ============================================
# 申请证书后,将证书文件放入 nginx/ssl/ 目录
# 然后为每个域名添加对应的 server 块
# ============================================
# 示例:me.dxz99wyr.cn 的 HTTPS 配置
# server {
# listen 443 ssl http2;
# server_name me.dxz99wyr.cn;
#
# ssl_certificate /etc/nginx/ssl/me.dxz99wyr.cn.crt;
# ssl_certificate_key /etc/nginx/ssl/me.dxz99wyr.cn.key;
#
# ssl_protocols TLSv1.2 TLSv1.3;
# ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
# ssl_prefer_server_ciphers off;
# ssl_session_cache shared:SSL:10m;
# ssl_session_timeout 1d;
#
# access_log /var/log/nginx/resume-web.access.log main;
# error_log /var/log/nginx/resume-web.error.log warn;
#
# location / {
# proxy_pass http://resume-web:80;
# proxy_http_version 1.1;
# 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;
# }
# }
#
# # HTTP 自动跳转到 HTTPS
# server {
# listen 80;
# server_name me.dxz99wyr.cn;
# return 301 https://$server_name$request_uri;
# }
View File
+43
View File
@@ -0,0 +1,43 @@
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
use epoll;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'upstream=$upstream_addr response_time=$upstream_response_time';
access_log /var/log/nginx/access.log main;
# 性能优化
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# Gzip 压缩
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;
# 防止暴露版本号
server_tokens off;
# 引入各个服务的配置文件(每个服务独立管理)
include /etc/nginx/conf.d/*.conf;
}
View File
+36
View File
@@ -0,0 +1,36 @@
#!/bin/bash
# ============================================
# 备份脚本
# 备份 Nginx 配置和 SSL 证书
# ============================================
BACKUP_DIR="/opt/backups"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="aliyun-manager_backup_$DATE"
echo "=========================================="
echo " 开始备份"
echo "=========================================="
mkdir -p "$BACKUP_DIR"
# 备份配置
cd "$(dirname "$0")/.."
tar czf "$BACKUP_DIR/${BACKUP_NAME}.tar.gz" \
nginx/nginx.conf \
nginx/conf.d/ \
nginx/ssl/ \
services/ \
docker-compose.yml \
.env \
2>/dev/null || true
# 保留最近 30 天的备份
cd "$BACKUP_DIR"
ls -t *.tar.gz | tail -n +31 | xargs rm -f 2>/dev/null || true
echo "备份完成: $BACKUP_DIR/${BACKUP_NAME}.tar.gz"
echo ""
echo "最近备份列表:"
ls -lh "$BACKUP_DIR"/*.tar.gz 2>/dev/null | tail -5
+108
View File
@@ -0,0 +1,108 @@
#!/bin/bash
# ============================================
# 服务器初始化脚本
# 在全新的阿里云服务器上运行此脚本
# ============================================
set -e
echo "=========================================="
echo " 阿里云服务器初始化"
echo "=========================================="
echo ""
# 更新系统
if command -v apt-get &> /dev/null; then
echo "检测到 Debian/Ubuntu 系统"
apt-get update
apt-get upgrade -y
apt-get install -y curl wget git vim unzip ufw
elif command -v yum &> /dev/null; then
echo "检测到 CentOS/RHEL 系统"
yum update -y
yum install -y curl wget git vim unzip firewalld
fi
# 安装 Docker
echo ""
echo "正在安装 Docker..."
if ! command -v docker &> /dev/null; then
curl -fsSL https://get.docker.com | sh
systemctl start docker
systemctl enable docker
echo "Docker 安装完成"
else
echo "Docker 已安装,跳过"
fi
# 安装 Docker Compose
echo ""
echo "正在安装 Docker Compose..."
if ! command -v docker-compose &> /dev/null; then
DOCKER_COMPOSE_VERSION=$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep -oP '"tag_name": "\K(.*)(?=")')
curl -L "https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
ln -sf /usr/local/bin/docker-compose /usr/bin/docker-compose
echo "Docker Compose 安装完成"
else
echo "Docker Compose 已安装,跳过"
fi
# 配置防火墙
echo ""
echo "正在配置防火墙..."
if command -v ufw &> /dev/null; then
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable
echo "UFW 防火墙配置完成"
elif command -v firewall-cmd &> /dev/null; then
systemctl start firewalld
systemctl enable firewalld
firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
echo "Firewalld 防火墙配置完成"
fi
# 配置时区
echo ""
echo "设置时区为 Asia/Shanghai..."
timedatectl set-timezone Asia/Shanghai || true
# Docker 镜像加速(阿里云)
echo ""
echo "配置 Docker 镜像加速..."
mkdir -p /etc/docker
cat > /etc/docker/daemon.json << 'EOF'
{
"registry-mirrors": [
"https://mirror.ccs.tencentyun.com",
"https://hub-mirror.c.163.com"
],
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
EOF
systemctl restart docker
echo ""
echo "=========================================="
echo " 服务器初始化完成"
echo "=========================================="
echo ""
echo "Docker 版本:"
docker --version
echo "Docker Compose 版本:"
docker-compose --version
echo ""
echo "下一步:上传项目文件并运行 ./deploy.sh"
echo ""
+13
View File
@@ -0,0 +1,13 @@
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0644 nginx nginx
sharedscripts
postrotate
docker exec main-nginx nginx -s reload > /dev/null 2>&1 || true
endscript
}
+96
View File
@@ -0,0 +1,96 @@
#!/bin/bash
# ============================================
# SSL 证书自动配置脚本 (使用 Certbot)
# ============================================
# 前置条件:
# 1. 域名已解析到服务器
# 2. 80 端口可从外网访问
# 3. Docker 和 Docker Compose 已安装
# ============================================
set -e
DOMAIN_RESUME_WEB=${DOMAIN_RESUME_WEB:-me.dxz99wyr.cn}
DOMAIN_MINIAPP_WEB=${DOMAIN_MINIAPP_WEB:-www.dxz99wyr.cn}
DOMAIN_RESUME_API=${DOMAIN_RESUME_API:-api-resume.dxz99wyr.cn}
DOMAIN_MINIAPP_API=${DOMAIN_MINIAPP_API:-api-miniapp.dxz99wyr.cn}
# 证书存储目录
SSL_DIR="$(cd "$(dirname "$0")/.." && pwd)/nginx/ssl"
mkdir -p "$SSL_DIR"
echo "=========================================="
echo " SSL 证书自动配置"
echo "=========================================="
echo ""
echo "将为以下域名申请证书:"
echo " - $DOMAIN_RESUME_WEB"
echo " - $DOMAIN_MINIAPP_WEB"
echo " - $DOMAIN_RESUME_API"
echo " - $DOMAIN_MINIAPP_API"
echo ""
# 检查 Certbot 是否安装
if ! command -v certbot &> /dev/null; then
echo "正在安装 Certbot..."
if command -v apt-get &> /dev/null; then
apt-get update
apt-get install -y certbot
elif command -v yum &> /dev/null; then
yum install -y certbot
elif command -v apk &> /dev/null; then
apk add certbot
else
echo "错误:无法自动安装 Certbot,请手动安装"
exit 1
fi
fi
# 使用 Certbot 申请证书(standalone 模式)
echo "正在申请证书..."
certbot certonly \
--standalone \
--agree-tos \
--non-interactive \
--email admin@dxz99wyr.cn \
-d "$DOMAIN_RESUME_WEB" \
-d "$DOMAIN_MINIAPP_WEB" \
-d "$DOMAIN_RESUME_API" \
-d "$DOMAIN_MINIAPP_API" \
|| {
echo ""
echo "证书申请失败,可能原因:"
echo " 1. 域名未正确解析到本服务器"
echo " 2. 80 端口被占用或防火墙阻止"
echo " 3. 请确保上述域名都已添加 A 记录指向本服务器 IP"
exit 1
}
# 复制证书到项目目录
CERT_DIR="/etc/letsencrypt/live"
for domain in "$DOMAIN_RESUME_WEB" "$DOMAIN_MINIAPP_WEB" "$DOMAIN_RESUME_API" "$DOMAIN_MINIAPP_API"; do
if [ -d "$CERT_DIR/$domain" ]; then
cp "$CERT_DIR/$domain/fullchain.pem" "$SSL_DIR/$domain.crt"
cp "$CERT_DIR/$domain/privkey.pem" "$SSL_DIR/$domain.key"
echo "已复制证书: $domain"
fi
done
# 设置自动续期
echo ""
echo "设置证书自动续期..."
(crontab -l 2>/dev/null | grep -v "certbot renew"; echo "0 3 * * * certbot renew --quiet --deploy-hook 'docker exec main-nginx nginx -s reload'") | crontab -
echo ""
echo "=========================================="
echo " SSL 证书配置完成"
echo "=========================================="
echo ""
echo "请执行以下步骤启用 HTTPS"
echo " 1. 将 nginx/conf.d/ssl-template.conf 的内容取消注释"
echo " 2. 根据实际域名修改 server_name 和证书路径"
echo " 3. 重启 Nginx: docker-compose restart nginx"
echo ""
echo "证书将自动续期,每天凌晨 3 点检查"
echo ""
+47
View File
@@ -0,0 +1,47 @@
#!/bin/bash
# ============================================
# 更新单个服务脚本
# 用法: ./update-service.sh <服务名>
# 示例: ./update-service.sh resume-web
# ============================================
SERVICE_NAME=$1
if [ -z "$SERVICE_NAME" ]; then
echo "错误:请指定服务名"
echo "用法: $0 <服务名>"
echo "可用服务: resume-web, miniapp-web, resume-api, miniapp-api"
exit 1
fi
if [ ! -d "services/$SERVICE_NAME" ]; then
echo "错误:服务 '$SERVICE_NAME' 不存在"
exit 1
fi
echo "=========================================="
echo " 更新服务: $SERVICE_NAME"
echo "=========================================="
# 如果有 Dockerfile,重新构建
if [ -f "services/$SERVICE_NAME/Dockerfile" ]; then
echo "检测到 Dockerfile,正在构建镜像..."
docker-compose build "$SERVICE_NAME"
fi
# 重启指定服务
echo "正在重启服务..."
docker-compose up -d --no-deps --force-recreate "$SERVICE_NAME"
# 检查健康状态
echo ""
echo "等待服务启动..."
sleep 3
if docker-compose ps | grep "$SERVICE_NAME" | grep -q "Up"; then
echo "服务 $SERVICE_NAME 更新成功"
else
echo "警告:服务 $SERVICE_NAME 状态异常,请检查日志"
docker-compose logs --tail=50 "$SERVICE_NAME"
fi