feat: init cpdaily-xiaozhushou with blue-green deploy
- backed/: Go Fiber backend with cpdaily integration - frondend/: Vue 3 + Vite frontend - Dockerfile: multi-stage build (Node → Go → Alpine) - deploy/docker-compose.yml: production compose file - .woodpecker/build.yml: CI/CD with blue-green zero-downtime deploy - /health endpoint for deployment health checks - Port 8884/8885 blue-green swap via 1Panel OpenResty
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
when:
|
||||
- event: push
|
||||
branch: [main, master]
|
||||
- event: tag
|
||||
branch: [v*]
|
||||
|
||||
clone:
|
||||
git:
|
||||
image: woodpeckerci/plugin-git
|
||||
settings:
|
||||
remote: http://10.10.10.128:3000/becomer/cpdaily_xiaozhushou.git
|
||||
|
||||
steps:
|
||||
build-image:
|
||||
name: 构建 Docker 镜像
|
||||
image: docker
|
||||
commands: |
|
||||
docker build -t cpdaily-xiaozhushou:latest .
|
||||
docker tag cpdaily-xiaozhushou:latest cpdaily-xiaozhushou:${CI_COMMIT_TAG:-${CI_COMMIT_SHA:0:8}}
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
|
||||
deploy:
|
||||
name: 蓝绿部署
|
||||
image: docker
|
||||
commands: |
|
||||
set -e
|
||||
|
||||
IMAGE_TAG="${CI_COMMIT_TAG:-latest}"
|
||||
|
||||
# 确保网络存在
|
||||
docker network create likedream-net 2>/dev/null || true
|
||||
|
||||
# ============================================================
|
||||
# 第一步:初始化 1Panel 站点配置(首次部署时才需要)
|
||||
# ============================================================
|
||||
if ! docker exec 1Panel-openresty-ESmn ls /www/sites/xiaozhushou/proxy/api.conf 2>/dev/null; then
|
||||
echo "=== 首次部署:创建 1Panel 站点配置 ==="
|
||||
docker exec 1Panel-openresty-ESmn mkdir -p /www/sites/xiaozhushou/proxy /www/sites/xiaozhushou/log
|
||||
cat <<'NGINX_EOF' | docker exec -i 1Panel-openresty-ESmn tee /usr/local/openresty/nginx/conf/conf.d/xiaozhushou.conf
|
||||
server {
|
||||
listen 80 ;
|
||||
server_name xiaozhushou.eu.cc;
|
||||
index index.php index.html index.htm default.php default.htm default.html;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $server_name;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $http_connection;
|
||||
access_log /www/sites/xiaozhushou/log/access.log main;
|
||||
error_log /www/sites/xiaozhushou/log/error.log;
|
||||
location ^~ /.well-known/acme-challenge {
|
||||
allow all;
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
include /www/sites/xiaozhushou/proxy/*.conf;
|
||||
}
|
||||
NGINX_EOF
|
||||
cat <<'PROXY_EOF' | docker exec -i 1Panel-openresty-ESmn tee /www/sites/xiaozhushou/proxy/api.conf
|
||||
location ^~ / {
|
||||
proxy_pass http://10.10.10.128:8884/;
|
||||
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 REMOTE-HOST $remote_addr;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $http_connection;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
proxy_http_version 1.1;
|
||||
add_header X-Cache $upstream_cache_status;
|
||||
add_header Cache-Control no-cache;
|
||||
proxy_ssl_server_name off;
|
||||
proxy_ssl_name $proxy_host;
|
||||
}
|
||||
PROXY_EOF
|
||||
docker exec 1Panel-openresty-ESmn nginx -s reload
|
||||
echo " 1Panel 站点配置完成 ✓"
|
||||
fi
|
||||
|
||||
# ============================================================
|
||||
# 第二步:读取当前代理端口,确定蓝绿状态
|
||||
# ============================================================
|
||||
CURRENT_PORT=$(docker exec 1Panel-openresty-ESmn \
|
||||
grep -o 'proxy_pass http://10.10.10.128:[0-9]\+' \
|
||||
/www/sites/xiaozhushou/proxy/api.conf | grep -o '[0-9]\+$')
|
||||
echo "=== 当前 1Panel 反代端口: $CURRENT_PORT ==="
|
||||
|
||||
if [ "$CURRENT_PORT" = "8884" ]; then
|
||||
PORT_ACTIVE=8884
|
||||
PORT_STANDBY=8885
|
||||
elif [ "$CURRENT_PORT" = "8885" ]; then
|
||||
PORT_ACTIVE=8885
|
||||
PORT_STANDBY=8884
|
||||
else
|
||||
echo "未知当前端口 $CURRENT_PORT,默认使用 8884/8885"
|
||||
PORT_ACTIVE=8884
|
||||
PORT_STANDBY=8885
|
||||
fi
|
||||
echo " 活跃: $PORT_ACTIVE | 备用: $PORT_STANDBY"
|
||||
|
||||
# 清理之前可能残留的临时容器
|
||||
docker rm -f cpdaily-xiaozhushou-new 2>/dev/null || true
|
||||
|
||||
# ============================================================
|
||||
# 第三步:在备用端口启动新容器
|
||||
# ============================================================
|
||||
echo "=== 蓝绿部署: 启动新容器 on :$PORT_STANDBY (image: $IMAGE_TAG) ==="
|
||||
|
||||
docker run -d --name cpdaily-xiaozhushou-new \
|
||||
--restart unless-stopped \
|
||||
--network likedream-net \
|
||||
-p $PORT_STANDBY:8093 \
|
||||
-v /opt/cpdaily-xiaozhushou/config.toml:/app/config.toml:ro \
|
||||
cpdaily-xiaozhushou:$IMAGE_TAG
|
||||
|
||||
# ============================================================
|
||||
# 第四步:健康检查
|
||||
# ============================================================
|
||||
HEALTHY=false
|
||||
for i in $(seq 1 15); do
|
||||
if wget -q --timeout=3 -O /dev/null http://10.10.10.128:$PORT_STANDBY/health 2>/dev/null; then
|
||||
HEALTHY=true
|
||||
break
|
||||
fi
|
||||
echo " 等待新容器就绪... ($i/15)"
|
||||
sleep 2
|
||||
done
|
||||
|
||||
if [ "$HEALTHY" = false ]; then
|
||||
echo "ERROR: 新容器未通过健康检查,回滚"
|
||||
docker stop cpdaily-xiaozhushou-new
|
||||
docker rm cpdaily-xiaozhushou-new
|
||||
exit 1
|
||||
fi
|
||||
echo " 新容器已就绪 ✓"
|
||||
|
||||
# ============================================================
|
||||
# 第五步:切换 1Panel 代理到备用端口
|
||||
# ============================================================
|
||||
echo "=== 切换 1Panel 反代 :$PORT_ACTIVE → :$PORT_STANDBY ==="
|
||||
docker exec 1Panel-openresty-ESmn \
|
||||
sed -i "s|:$PORT_ACTIVE|:$PORT_STANDBY|g" \
|
||||
/www/sites/xiaozhushou/proxy/api.conf
|
||||
docker exec 1Panel-openresty-ESmn nginx -s reload
|
||||
echo " Nginx 热加载完成(零中断)✓"
|
||||
|
||||
# ============================================================
|
||||
# 第六步:停止旧容器
|
||||
# ============================================================
|
||||
echo "=== 清理旧容器 ==="
|
||||
docker stop cpdaily-xiaozhushou 2>/dev/null || true
|
||||
docker rm cpdaily-xiaozhushou 2>/dev/null || true
|
||||
|
||||
# ============================================================
|
||||
# 第七步:在活跃端口启动正式容器
|
||||
# ============================================================
|
||||
echo "=== 启动正式容器 on :$PORT_ACTIVE ==="
|
||||
docker run -d --name cpdaily-xiaozhushou \
|
||||
--restart unless-stopped \
|
||||
--network likedream-net \
|
||||
-p $PORT_ACTIVE:8093 \
|
||||
-v /opt/cpdaily-xiaozhushou/config.toml:/app/config.toml:ro \
|
||||
cpdaily-xiaozhushou:$IMAGE_TAG
|
||||
|
||||
# ============================================================
|
||||
# 第八步:切回 1Panel 代理到活跃端口
|
||||
# ============================================================
|
||||
echo "=== 切回 1Panel 反代 :$PORT_STANDBY → :$PORT_ACTIVE ==="
|
||||
docker exec 1Panel-openresty-ESmn \
|
||||
sed -i "s|:$PORT_STANDBY|:$PORT_ACTIVE|g" \
|
||||
/www/sites/xiaozhushou/proxy/api.conf
|
||||
docker exec 1Panel-openresty-ESmn nginx -s reload
|
||||
echo " Nginx 热加载完成(零中断)✓"
|
||||
|
||||
# ============================================================
|
||||
# 第九步:清理
|
||||
# ============================================================
|
||||
echo "=== 清理 ==="
|
||||
docker rm -f cpdaily-xiaozhushou-new 2>/dev/null || true
|
||||
docker images cpdaily-xiaozhushou --format '{{.Tag}}' | grep -v latest | head -n -3 | while read tag; do
|
||||
docker rmi cpdaily-xiaozhushou:$tag 2>/dev/null || true
|
||||
done
|
||||
echo "=== 部署完成 ✓ ==="
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
Reference in New Issue
Block a user