f169afc1bc
新增「其他部署方式」分组,共 5 页: - 方式对比与选型:5 种方式对照、服务依赖表、服务间通信易错点 - 二进制部署:各服务 Go 版本/CGO/构建目录/产物名对照表, admin-svr 需 CGO 的说明,交叉编译限制,systemd unit 模板, 静态前端交给 nginx,升级回滚流程 - 自建镜像:各仓 Dockerfile 位置与构建上下文、构建参数、 镜像命名规则、批量构建脚本、常见问题 - 分离部署:中间件独立,业务机精简 compose,配置改为外部地址 - 离线部署:镜像导出导入、校验、内网镜像仓库方案 同时记录一个实际阻塞:openapi/app/admin-ui 共 5 个 Dockerfile 的 FROM 仍指向私有镜像仓库,外部环境无法构建,页内给出替换方法。
322 lines
8.9 KiB
Markdown
322 lines
8.9 KiB
Markdown
---
|
||
title: 二进制部署
|
||
description: 直接编译 Go 程序运行,不依赖 Docker
|
||
outline: deep
|
||
---
|
||
|
||
# 二进制部署
|
||
|
||
不使用容器,把各服务编译为可执行文件,用 systemd 托管。
|
||
|
||
## 适用场景
|
||
|
||
- 服务器不允许安装 Docker
|
||
- 需要把服务纳入既有的 systemd / 进程管理体系统一运维
|
||
- 需要针对特定 CPU 架构或内核参数做优化
|
||
|
||
## 构建环境
|
||
|
||
| 项 | 要求 |
|
||
| --- | --- |
|
||
| Go | 按各服务 `go.mod` 要求,最低 1.23(见下表) |
|
||
| GCC | admin-svr 需要(`CGO_ENABLED=1`,内存库用 SQLite) |
|
||
| 系统 | 建议与目标服务器同发行版,避免 libc 差异 |
|
||
|
||
```bash
|
||
# Debian / Ubuntu
|
||
apt-get install -y build-essential
|
||
|
||
# CentOS / Rocky
|
||
yum groupinstall -y "Development Tools"
|
||
```
|
||
|
||
::: tip 其余服务可静态编译
|
||
除 admin-svr 外,其余服务 `CGO_ENABLED=0`,产物为静态二进制,可直接拷到任意同架构 Linux 运行。
|
||
:::
|
||
|
||
## 各服务构建参数
|
||
|
||
| 服务 | 仓库 | Go 版本 | CGO | 构建目录 | 产物名 | 监听端口 |
|
||
| --- | --- | --- | --- | --- | --- | --- |
|
||
| admin-svr | `iotlcm-admin-svr` | 1.23 | **需开启** | `server/` | `iotlcmadmin_svc` | 8008 |
|
||
| openapi | `iotlcm-openapi` | 1.23 | 关闭 | 根目录 | `iotlcm-openapi` | 8000 |
|
||
| worker-svr | `iotlcm-worker-svr` | 1.25 | 关闭 | 根目录 | `iotlcm-worker-svr` | 无(队列消费) |
|
||
| upstream-chan | `iotlcm-upstream-chan` | 1.25 | 关闭 | 根目录 | `iotlcmupstreamchan_svc` | 8110 / 8310 |
|
||
| upstream-proxy | `iotlcm-upstream-proxy` | 1.25 | 关闭 | 根目录 | `iotlcmupstreamproxy_svc` | 8510 |
|
||
| app-server | `iotlcm-app` | 1.23 | 关闭 | `server/` | `iotlcm-app-server` | 8010 |
|
||
| sms | `iotlcm-sms` | 1.25 | 关闭 | 根目录 | `iotlcm-sms` | 11190 / 11200 |
|
||
| bot | `iotlcm-bot` | 1.23 | 关闭 | `cmd/iotlcm-bot` | `iotlcm-bot` | 无 |
|
||
|
||
::: warning 仓库里的 Dockerfile 不能直接照搬
|
||
部分仓库的 Dockerfile 基础镜像指向私有仓库(见[自建镜像](build-image)),二进制构建不受影响,但 `FROM` 行需要替换。
|
||
:::
|
||
|
||
## 构建
|
||
|
||
### admin-svr(需要 CGO)
|
||
|
||
```bash
|
||
git clone https://git.5iot.com/iotlcm-public/iotlcm-admin-svr.git
|
||
cd iotlcm-admin-svr/server
|
||
|
||
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 \
|
||
go build -trimpath \
|
||
-ldflags "-s -w \
|
||
-X main.BuildVersion=$(git describe --tags --always) \
|
||
-X main.CommitID=$(git rev-parse --short HEAD) \
|
||
-X main.BuildTime=$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \
|
||
-o iotlcmadmin_svc .
|
||
```
|
||
|
||
### 其余服务(静态编译)
|
||
|
||
```bash
|
||
git clone https://git.5iot.com/iotlcm-public/iotlcm-openapi.git
|
||
cd iotlcm-openapi
|
||
|
||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
|
||
go build -trimpath \
|
||
-ldflags "-s -w \
|
||
-X main.BuildVersion=$(git describe --tags --always) \
|
||
-X main.CommitID=$(git rev-parse --short HEAD) \
|
||
-X main.BuildTime=$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \
|
||
-o iotlcm-openapi .
|
||
```
|
||
|
||
替换仓库名与产物名即可用于其他服务,`bot` 需要指定子目录:
|
||
|
||
```bash
|
||
cd iotlcm-bot
|
||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -o iotlcm-bot ./cmd/iotlcm-bot
|
||
```
|
||
|
||
### 交叉编译说明
|
||
|
||
| 服务 | 能否交叉编译 |
|
||
| --- | --- |
|
||
| admin-svr(CGO) | ❌ 需在目标架构上编译,或用对应架构的交叉工具链 |
|
||
| 其余(静态) | ✅ 可直接 `GOOS=linux GOARCH=arm64` |
|
||
|
||
查看服务器架构:
|
||
|
||
```bash
|
||
uname -m # x86_64 → amd64;aarch64 → arm64
|
||
```
|
||
|
||
## 部署布局
|
||
|
||
```text
|
||
/opt/iotlcm/
|
||
├── admin-svr/
|
||
│ ├── iotlcmadmin_svc
|
||
│ ├── config/config.yaml ← 从 config.example/admin-svr 复制
|
||
│ ├── logs/
|
||
│ ├── upload/
|
||
│ └── cache/
|
||
├── openapi/
|
||
│ ├── iotlcm-openapi
|
||
│ ├── config/config.yaml
|
||
│ └── logs/
|
||
├── worker-svr/
|
||
│ ├── iotlcm-worker-svr
|
||
│ ├── config/config.yaml
|
||
│ └── logs/
|
||
├── upstream-chan/
|
||
├── upstream-proxy/
|
||
├── app-server/
|
||
│ ├── iotlcm-app-server
|
||
│ ├── config/config.yaml
|
||
│ └── resource/
|
||
│ ├── log/server/
|
||
│ └── upload/
|
||
├── sms/
|
||
└── bot/
|
||
```
|
||
|
||
**配置文件放 `config/config.yaml`**(相对工作目录),这是 GoFrame 的默认搜索路径。启动时工作目录必须在服务目录内。
|
||
|
||
### 目录准备
|
||
|
||
```bash
|
||
sudo mkdir -p /opt/iotlcm/{admin-svr,openapi,worker-svr,upstream-chan,upstream-proxy,app-server,sms,bot}
|
||
sudo useradd -r -s /sbin/nologin iotlcm
|
||
sudo chown -R iotlcm:iotlcm /opt/iotlcm
|
||
```
|
||
|
||
## 修改配置中的服务地址
|
||
|
||
容器部署时配置里写的是服务名(`mysql:3306`、`upstream-proxy:8510`),二进制部署必须改为实际地址:
|
||
|
||
```yaml
|
||
# admin-svr / openapi / worker-svr / app-server
|
||
database:
|
||
default:
|
||
link: "mysql:u_iotlcm:<口令>@tcp(127.0.0.1:3306)/db_iotlcm?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai"
|
||
redis:
|
||
default:
|
||
address: "127.0.0.1:6379"
|
||
rabbitmq:
|
||
dsn: "amqp://<用户>:<口令>@127.0.0.1:5672/"
|
||
|
||
# upstream-chan / upstream-proxy
|
||
registry:
|
||
address: "127.0.0.1:8500"
|
||
|
||
# 上游服务地址
|
||
upstream:
|
||
proxy:
|
||
address: "127.0.0.1:8510"
|
||
gateway:
|
||
address: "127.0.0.1:8110"
|
||
```
|
||
|
||
::: danger logger.path 也要改
|
||
配置里的 `logger.path` 在容器版本中是 `/app/logs`,二进制部署要改为实际路径,例如 `/opt/iotlcm/admin-svr/logs`,否则会因目录不存在启动失败。
|
||
:::
|
||
|
||
## systemd 托管
|
||
|
||
以为 `admin-svr` 为例,保存为 `/etc/systemd/system/iotlcm-admin-svr.service`:
|
||
|
||
```ini
|
||
[Unit]
|
||
Description=IotLCM Admin Service
|
||
After=network-online.target mysql.service redis.service
|
||
Wants=network-online.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=iotlcm
|
||
Group=iotlcm
|
||
WorkingDirectory=/opt/iotlcm/admin-svr
|
||
ExecStart=/opt/iotlcm/admin-svr/iotlcmadmin_svc
|
||
Restart=always
|
||
RestartSec=5s
|
||
LimitNOFILE=65535
|
||
|
||
# 环境变量(JWT 密钥等敏感值建议放独立文件)
|
||
EnvironmentFile=-/etc/iotlcm/admin-svr.env
|
||
|
||
# 日志交给 journald,也可用配置里的文件日志
|
||
StandardOutput=journal
|
||
StandardError=journal
|
||
|
||
# 安全加固
|
||
NoNewPrivileges=true
|
||
PrivateTmp=true
|
||
ProtectSystem=full
|
||
ProtectHome=true
|
||
ReadWritePaths=/opt/iotlcm/admin-svr
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
```
|
||
|
||
`/etc/iotlcm/admin-svr.env`:
|
||
|
||
```bash
|
||
JWT_SIGNING_KEY=<与其它服务一致的密钥>
|
||
```
|
||
|
||
启用:
|
||
|
||
```bash
|
||
sudo systemctl daemon-reload
|
||
sudo systemctl enable --now iotlcm-admin-svr
|
||
sudo systemctl status iotlcm-admin-svr
|
||
```
|
||
|
||
### 各服务的差异点
|
||
|
||
| 服务 | 特殊处理 |
|
||
| --- | --- |
|
||
| admin-svr | 需 `ReadWritePaths` 包含 upload 与 logs 目录 |
|
||
| worker-svr | 无监听端口,`After` 需包含 rabbitmq |
|
||
| upstream-chan / proxy | `After` 需包含 consul |
|
||
| app-server | 需 `resource/log/server` 与 `resource/upload` 可写 |
|
||
| bot | `ExecStart` 需带参数:`/opt/iotlcm/bot/iotlcm-bot watch --config /opt/iotlcm/bot/config/config.yaml` |
|
||
|
||
### 启动顺序
|
||
|
||
```text
|
||
MySQL / Redis / RabbitMQ / Consul
|
||
↓
|
||
admin-svr、openapi、worker-svr、upstream-chan、upstream-proxy、app-server、sms
|
||
↓
|
||
admin-ui、app-web、docs(静态文件,由 nginx 托管)
|
||
```
|
||
|
||
用 systemd 依赖表达:
|
||
|
||
```ini
|
||
[Unit]
|
||
After=iotlcm-admin-svr.service
|
||
Requires=iotlcm-admin-svr.service
|
||
```
|
||
|
||
## 静态前端
|
||
|
||
`admin-ui`、`app-web`、`docs` 是静态文件,二进制部署时不需要跑容器,把构建产物交给 nginx:
|
||
|
||
```bash
|
||
# admin-ui:需 Node 构建
|
||
cd iotlcm-admin-ui/vue
|
||
npm ci && npm run build
|
||
sudo cp -r apps/web-antd/dist /var/www/iotlcm/admin-ui
|
||
```
|
||
|
||
nginx 配置参考部署仓的 `config.example/admin-ui/default.conf` 与 `config.example/nginx/iotlcm.conf`,把 `proxy_pass http://admin-svr:8008` 改为 `http://127.0.0.1:8008`。
|
||
|
||
## 验证
|
||
|
||
```bash
|
||
# 进程状态
|
||
systemctl status iotlcm-admin-svr
|
||
journalctl -u iotlcm-admin-svr -n 50 --no-pager
|
||
|
||
# 端口监听
|
||
ss -lntp | grep -E '8008|8000|8510|8110'
|
||
|
||
# 接口
|
||
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8008/api.json
|
||
```
|
||
|
||
## 与容器部署的差异
|
||
|
||
| 项 | 容器部署 | 二进制部署 |
|
||
| --- | --- | --- |
|
||
| 配置路径 | `/app/config`(挂载) | `<服务目录>/config` |
|
||
| 日志路径 | `/app/logs` | 需在配置里改成实际路径 |
|
||
| 服务互访 | 服务名(Docker DNS) | `127.0.0.1` 或内网 IP |
|
||
| 进程管理 | Docker restart policy | systemd |
|
||
| 升级 | 换镜像 + `up -d` | 停服务 → 换二进制 → 起服务 |
|
||
| 时区 | 镜像已内置 | 依赖宿主机 tzdata |
|
||
|
||
## 升级流程
|
||
|
||
```bash
|
||
# 1. 备份配置与程序
|
||
sudo tar czf /backup/iotlcm-admin-svr-$(date +%F).tar.gz -C /opt/iotlcm admin-svr
|
||
|
||
# 2. 停服务
|
||
sudo systemctl stop iotlcm-admin-svr
|
||
|
||
# 3. 替换二进制
|
||
sudo cp iotlcmadmin_svc /opt/iotlcm/admin-svr/
|
||
sudo chown iotlcm:iotlcm /opt/iotlcm/admin-svr/iotlcmadmin_svc
|
||
|
||
# 4. 起服务并验证
|
||
sudo systemctl start iotlcm-admin-svr
|
||
sudo systemctl status iotlcm-admin-svr
|
||
```
|
||
|
||
## 回滚
|
||
|
||
保留上一版二进制,回滚只需换回:
|
||
|
||
```bash
|
||
sudo systemctl stop iotlcm-admin-svr
|
||
sudo cp /opt/iotlcm/admin-svr/iotlcmadmin_svc.bak /opt/iotlcm/admin-svr/iotlcmadmin_svc
|
||
sudo systemctl start iotlcm-admin-svr
|
||
```
|