deploy: 挂目录+替换文件部署,构建产物到 deploy/,不重建 web/admin 镜像
Made-with: Cursor
This commit is contained in:
@@ -102,7 +102,7 @@ docker compose up -d --build
|
|||||||
```
|
```
|
||||||
若你已手动执行过 `git pull` 且报错 `Your local changes would be overwritten`,先以远程为准:`git fetch origin && git reset --hard origin/master`,再执行 `./pull-and-restart.sh`。脚本内已含默认 `REGISTRY_MIRROR`,一般直接 `./pull-and-restart.sh` 即可。
|
若你已手动执行过 `git pull` 且报错 `Your local changes would be overwritten`,先以远程为准:`git fetch origin && git reset --hard origin/master`,再执行 `./pull-and-restart.sh`。脚本内已含默认 `REGISTRY_MIRROR`,一般直接 `./pull-and-restart.sh` 即可。
|
||||||
|
|
||||||
构建会从 DaoCloud 等镜像拉取 node、nginx、golang、alpine、mongo,启动后**对外仅 443**,由 compose 内 Nginx 反代到 api/web/admin,证书按脚本自动处理。
|
采用**挂目录 + 替换文件**部署:脚本将 web/admin 构建到 `deploy/web/dist`、`deploy/admin/dist`,api 二进制到 `deploy/api/server`,容器挂载这些目录;更新时只重新构建产物并重启,无需重建前端镜像,仅 api 使用轻量运行时镜像。详见 `deploy/README.md`。构建会从 DaoCloud 等镜像拉取 node、nginx、golang、alpine、mongo,启动后**对外仅 443**,由 compose 内 Nginx 反代到 api/web/admin,证书按脚本自动处理。
|
||||||
|
|
||||||
**脚本说明**:仅保留两个脚本,均会检测 Docker 并在未安装时一键安装(apt 或 yum/dnf)。
|
**脚本说明**:仅保留两个脚本,均会检测 Docker 并在未安装时一键安装(apt 或 yum/dnf)。
|
||||||
- **拉取代码并重启**:`./pull-and-restart.sh` — 若无 Git 仓库会提示设置 `GIT_REPO_URL` 后自动克隆;然后拉取并构建、启动。
|
- **拉取代码并重启**:`./pull-and-restart.sh` — 若无 Git 仓库会提示设置 `GIT_REPO_URL` 后自动克隆;然后拉取并构建、启动。
|
||||||
|
|||||||
8
deploy/README.md
Normal file
8
deploy/README.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# deploy 目录(挂目录 + 替换文件部署)
|
||||||
|
|
||||||
|
- **deploy/web/dist**:前台构建产物,由 `pull-and-restart.sh` 生成;替换此目录内容即可更新前台。
|
||||||
|
- **deploy/admin/dist**:后台构建产物,同上。
|
||||||
|
- **deploy/api/server**:API 二进制,同上;替换后重启 api 容器生效。
|
||||||
|
- **deploy/web/default.conf**、**deploy/admin/default.conf**:Nginx 配置,已纳入版本库。
|
||||||
|
|
||||||
|
日常更新:在服务器执行 `./pull-and-restart.sh` 会拉代码、重新构建到上述目录并重启容器。若只改静态资源,也可在服务器上手动构建后只重启对应容器。
|
||||||
9
deploy/admin/default.conf
Normal file
9
deploy/admin/default.conf
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# 外层 Nginx 已把 /admin/ 转成 / 转发到本容器,此处 location / 提供 SPA
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
deploy/web/default.conf
Normal file
17
deploy/web/default.conf
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# 根路径下的验证文件走热加载目录,替换文件即可生效
|
||||||
|
location ~ ^/([A-Za-z0-9._-]+\.(txt|html|xml))$ {
|
||||||
|
alias /verify-root/$1;
|
||||||
|
}
|
||||||
|
|
||||||
|
location = / {
|
||||||
|
try_files /index.html =404;
|
||||||
|
}
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,17 +2,19 @@
|
|||||||
# version 已废弃,已移除
|
# version 已废弃,已移除
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
# 二进制由脚本构建到 deploy/api/server,挂载 deploy/api 即可更新,无需重建镜像
|
||||||
api:
|
api:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: server/Dockerfile
|
dockerfile: server/Dockerfile.run
|
||||||
args:
|
args:
|
||||||
GOPROXY: ${GOPROXY:-https://goproxy.cn,direct}
|
|
||||||
REGISTRY_MIRROR: ${REGISTRY_MIRROR:-}
|
REGISTRY_MIRROR: ${REGISTRY_MIRROR:-}
|
||||||
image: yh_web-api:latest
|
image: yh_web-api-run:latest
|
||||||
container_name: yh_api
|
container_name: yh_api
|
||||||
|
volumes:
|
||||||
|
- ./deploy/api:/app:ro
|
||||||
|
- ./server/.env:/app/.env:ro
|
||||||
environment:
|
environment:
|
||||||
# PORT=8088 仅容器内监听,不映射到宿主机(无 ports 配置)
|
|
||||||
- PORT=8088
|
- PORT=8088
|
||||||
- MONGODB_URI=${MONGODB_URI:-mongodb://mongo:27017}
|
- MONGODB_URI=${MONGODB_URI:-mongodb://mongo:27017}
|
||||||
- MONGODB_DB=${MONGODB_DB:-yxd-agent-testing}
|
- MONGODB_DB=${MONGODB_DB:-yxd-agent-testing}
|
||||||
@@ -22,34 +24,27 @@ services:
|
|||||||
- mongo
|
- mongo
|
||||||
networks:
|
networks:
|
||||||
- yh_net
|
- yh_net
|
||||||
# 不暴露宿主机端口,仅由 nginx 容器反代
|
|
||||||
|
|
||||||
|
# 静态文件由脚本构建到 deploy/web/dist,挂载后替换文件即可生效
|
||||||
web:
|
web:
|
||||||
build:
|
image: ${REGISTRY_MIRROR:-docker.m.daocloud.io/library/}nginx:alpine
|
||||||
context: ./web
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
args:
|
|
||||||
REGISTRY_MIRROR: ${REGISTRY_MIRROR:-}
|
|
||||||
image: yh_web-web:latest
|
|
||||||
container_name: yh_web
|
container_name: yh_web
|
||||||
volumes:
|
volumes:
|
||||||
# 仅挂载验证文件目录,便于热更新;前台静态站点仍由镜像内 dist 提供
|
- ./deploy/web/dist:/usr/share/nginx/html:ro
|
||||||
|
- ./deploy/web/default.conf:/etc/nginx/conf.d/default.conf:ro
|
||||||
- ./verify-root:/verify-root:ro
|
- ./verify-root:/verify-root:ro
|
||||||
networks:
|
networks:
|
||||||
- yh_net
|
- yh_net
|
||||||
# 不暴露宿主机端口,仅由 nginx 容器反代
|
|
||||||
|
|
||||||
|
# 静态文件由脚本构建到 deploy/admin/dist,挂载后替换文件即可生效
|
||||||
admin:
|
admin:
|
||||||
build:
|
image: ${REGISTRY_MIRROR:-docker.m.daocloud.io/library/}nginx:alpine
|
||||||
context: ./admin
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
args:
|
|
||||||
REGISTRY_MIRROR: ${REGISTRY_MIRROR:-}
|
|
||||||
image: yh_web-admin:latest
|
|
||||||
container_name: yh_admin
|
container_name: yh_admin
|
||||||
|
volumes:
|
||||||
|
- ./deploy/admin/dist:/usr/share/nginx/html:ro
|
||||||
|
- ./deploy/admin/default.conf:/etc/nginx/conf.d/default.conf:ro
|
||||||
networks:
|
networks:
|
||||||
- yh_net
|
- yh_net
|
||||||
# 不暴露宿主机端口,仅由 nginx 容器反代
|
|
||||||
|
|
||||||
nginx:
|
nginx:
|
||||||
image: ${REGISTRY_MIRROR:-docker.m.daocloud.io/library/}nginx:alpine
|
image: ${REGISTRY_MIRROR:-docker.m.daocloud.io/library/}nginx:alpine
|
||||||
|
|||||||
10
nginx/admin.conf
Normal file
10
nginx/admin.conf
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# 供 compose 中 admin 容器使用:宿主机挂载 admin/dist,SPA 回退
|
||||||
|
# 外层 Nginx 把 /admin/ 转成 / 转发到本容器
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
nginx/web.conf
Normal file
17
nginx/web.conf
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# 供 compose 中 web 容器使用:宿主机挂载 web/dist 与 verify-root,仅提供静态与 SPA 回退
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
location ~ ^/([A-Za-z0-9._-]+\.(txt|html|xml))$ {
|
||||||
|
alias /verify-root/$1;
|
||||||
|
}
|
||||||
|
|
||||||
|
location = / {
|
||||||
|
try_files /index.html =404;
|
||||||
|
}
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -281,12 +281,34 @@ if grep -q '9527' "$ROOT/docker-compose.yml" 2>/dev/null; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
export GOPROXY="${GOPROXY:-https://goproxy.cn,direct}"
|
export GOPROXY="${GOPROXY:-https://goproxy.cn,direct}"
|
||||||
# 国内直连 Docker Hub 超时时,用镜像拉取基础镜像(Dockerfile FROM 与 mongo 镜像)
|
|
||||||
export REGISTRY_MIRROR="${REGISTRY_MIRROR:-docker.m.daocloud.io/library/}"
|
export REGISTRY_MIRROR="${REGISTRY_MIRROR:-docker.m.daocloud.io/library/}"
|
||||||
compose_cmd build --no-cache
|
|
||||||
# 先显式从镜像站拉 mongo,避免 compose up 时直连 Docker Hub 超时
|
# 挂目录方案:构建产物到 deploy/,容器挂载这些目录,无需重建 web/admin 镜像
|
||||||
echo "拉取 mongo 镜像..."
|
mkdir -p "$ROOT/deploy/web/dist" "$ROOT/deploy/admin/dist" "$ROOT/deploy/api"
|
||||||
run_sudo docker pull "${REGISTRY_MIRROR}mongo:7" || true
|
|
||||||
|
echo "构建 web 前端 -> deploy/web/dist ..."
|
||||||
|
run_sudo docker run --rm -v "$ROOT/web:/app" -v "$ROOT/deploy/web/dist:/out" -w /app \
|
||||||
|
"${REGISTRY_MIRROR}node:20-alpine" sh -c "rm -rf /out/* 2>/dev/null; (npm ci --legacy-peer-deps 2>/dev/null || npm install --legacy-peer-deps) && npm run build && cp -r dist/. /out/"
|
||||||
|
|
||||||
|
echo "构建 admin 前端 -> deploy/admin/dist ..."
|
||||||
|
run_sudo docker run --rm -v "$ROOT/admin:/app" -v "$ROOT/deploy/admin/dist:/out" -w /app \
|
||||||
|
"${REGISTRY_MIRROR}node:20-alpine" sh -c "rm -rf /out/* 2>/dev/null; (npm ci --legacy-peer-deps 2>/dev/null || npm install --legacy-peer-deps) && npm run build && cp -r dist/. /out/"
|
||||||
|
|
||||||
|
echo "构建 api 二进制 -> deploy/api/server ..."
|
||||||
|
run_sudo docker run --rm -v "$ROOT/server:/src" -v "$ROOT/deploy/api:/out" -w /src -e GOPROXY="${GOPROXY}" \
|
||||||
|
"${REGISTRY_MIRROR}golang:1.21-alpine" sh -c "go build -mod=vendor -o /out/server ."
|
||||||
|
|
||||||
|
# 仅构建 api 运行时镜像(轻量,无业务代码);web/admin 使用官方 nginx 镜像无需构建
|
||||||
|
compose_cmd build api
|
||||||
|
|
||||||
|
# 仅当本地没有 mongo:7 时才从镜像站拉取,避免每次重复下载约 250MB
|
||||||
|
MONGO_IMAGE="${REGISTRY_MIRROR}mongo:7"
|
||||||
|
if ! run_sudo docker image inspect "$MONGO_IMAGE" >/dev/null 2>&1; then
|
||||||
|
echo "拉取 mongo 镜像(仅首次或镜像缺失时)..."
|
||||||
|
run_sudo docker pull "$MONGO_IMAGE" || true
|
||||||
|
else
|
||||||
|
echo "mongo 镜像已存在,跳过拉取."
|
||||||
|
fi
|
||||||
# 证书目录在 compose up 前就要就绪(compose 内 nginx 容器会挂载)
|
# 证书目录在 compose up 前就要就绪(compose 内 nginx 容器会挂载)
|
||||||
NGINX_DOMAIN="${NGINX_DOMAIN:-yuheng.yuxindazhineng.com}"
|
NGINX_DOMAIN="${NGINX_DOMAIN:-yuheng.yuxindazhineng.com}"
|
||||||
NGINX_SSL_DIR="/etc/ssl/yh_web/$NGINX_DOMAIN"
|
NGINX_SSL_DIR="/etc/ssl/yh_web/$NGINX_DOMAIN"
|
||||||
|
|||||||
8
server/Dockerfile.run
Normal file
8
server/Dockerfile.run
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# 仅运行时:不包含二进制,启动时挂载 deploy/api 到 /app,/app/server 由宿主机构建
|
||||||
|
ARG REGISTRY_MIRROR=docker.m.daocloud.io/library/
|
||||||
|
FROM ${REGISTRY_MIRROR}alpine:3.19
|
||||||
|
RUN apk add --no-cache ca-certificates tzdata
|
||||||
|
ENV TZ=Asia/Shanghai
|
||||||
|
WORKDIR /app
|
||||||
|
EXPOSE 8088
|
||||||
|
ENTRYPOINT ["/app/server"]
|
||||||
Reference in New Issue
Block a user