ci(workflow): 修复 deploy 步骤 bash 语法,改为数组参数并适配 docker run 直接部署
Build and Deploy / build-and-deploy (push) Canceled after 0s
Build and Deploy / build-and-deploy (push) Canceled after 0s
This commit is contained in:
@@ -10,7 +10,7 @@ env:
|
|||||||
IMAGE_NAME: henry_du/bywcloudreve
|
IMAGE_NAME: henry_du/bywcloudreve
|
||||||
SERVER_HOST: 192.140.163.199
|
SERVER_HOST: 192.140.163.199
|
||||||
SERVER_USER: ubuntu
|
SERVER_USER: ubuntu
|
||||||
COMPOSE_PATH: /home/ubuntu/cloudreve
|
CONTAINER_NAME: cloudreve
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-and-deploy:
|
build-and-deploy:
|
||||||
@@ -66,19 +66,119 @@ jobs:
|
|||||||
username: ${{ env.SERVER_USER }}
|
username: ${{ env.SERVER_USER }}
|
||||||
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||||
port: 22
|
port: 22
|
||||||
|
script_stop: true
|
||||||
script: |
|
script: |
|
||||||
set -e
|
set -euo pipefail
|
||||||
cd ${{ env.COMPOSE_PATH }}
|
sudo -n true 2>/dev/null || SUDO=""
|
||||||
|
[ -z "${SUDO+x}" ] && SUDO="sudo"
|
||||||
|
|
||||||
echo "${{ secrets.GITEA_TOKEN }}" | docker login ${{ env.REGISTRY }} -u "${{ gitea.actor }}" --password-stdin
|
CONTAINER="${{ env.CONTAINER_NAME }}"
|
||||||
|
NEW_IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest"
|
||||||
|
|
||||||
echo "Pulling latest image..."
|
echo "[1/6] 登录 Gitea Container Registry"
|
||||||
docker compose pull cloudreve
|
echo "${{ secrets.GITEA_TOKEN }}" | $SUDO docker login "${{ env.REGISTRY }}" -u "${{ gitea.actor }}" --password-stdin
|
||||||
|
|
||||||
echo "Recreating cloudreve container (preserving volumes)..."
|
echo "[2/6] 拉取最新镜像 ${NEW_IMAGE}"
|
||||||
docker compose up -d --remove-orphans cloudreve
|
$SUDO docker pull "${NEW_IMAGE}"
|
||||||
|
|
||||||
echo "Cleaning up old images..."
|
if ! $SUDO docker inspect "$CONTAINER" > /tmp/old.json 2>/dev/null; then
|
||||||
docker image prune -f
|
echo "[WARN] 现有容器 $CONTAINER 不存在,按默认参数首次启动(请确认 postgres/redis 已在 172.17.0.1)。"
|
||||||
|
$SUDO docker run -d \
|
||||||
|
--name "$CONTAINER" \
|
||||||
|
--restart unless-stopped \
|
||||||
|
-p 5212:5212 -p 6888:6888 -p 6888:6888/udp \
|
||||||
|
-v cloudreve_backend_data:/cloudreve/data \
|
||||||
|
--add-host=postgresql:172.17.0.1 \
|
||||||
|
--add-host=redis:172.17.0.1 \
|
||||||
|
-e CR_CONF_Database.Type=postgres \
|
||||||
|
-e CR_CONF_Database.Host=postgresql \
|
||||||
|
-e CR_CONF_Database.User=cloudreve \
|
||||||
|
-e CR_CONF_Database.Name=cloudreve \
|
||||||
|
-e CR_CONF_Database.Port=5432 \
|
||||||
|
-e CR_CONF_Redis.Server=redis:6379 \
|
||||||
|
"$NEW_IMAGE" || true
|
||||||
|
echo "首次启动命令已执行。"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Deployment completed at $(date)"
|
echo "[3/6] 从现有容器提取运行参数 (安装 jq)"
|
||||||
|
which jq >/dev/null 2>&1 || ($SUDO apt-get update -qq && $SUDO apt-get install -y -qq jq >/dev/null)
|
||||||
|
|
||||||
|
OLD_IMAGE="$(jq -r '.Config.Image' /tmp/old.json)"
|
||||||
|
RESTART_POLICY="$(jq -r '.HostConfig.RestartPolicy.Name' /tmp/old.json)"
|
||||||
|
NETWORK_MODE="$(jq -r '.HostConfig.NetworkMode' /tmp/old.json)"
|
||||||
|
echo "旧镜像: ${OLD_IMAGE} -> 新镜像: ${NEW_IMAGE}"
|
||||||
|
echo "重启策略: ${RESTART_POLICY}, 网络: ${NETWORK_MODE}"
|
||||||
|
|
||||||
|
# 以数组方式构建参数,避免 eval 转义问题
|
||||||
|
RUN_ARGS=( -d )
|
||||||
|
RUN_ARGS+=( --name "${CONTAINER}_new" )
|
||||||
|
[ "${RESTART_POLICY}" != "null" ] && [ -n "${RESTART_POLICY}" ] && RUN_ARGS+=( --restart "${RESTART_POLICY}" )
|
||||||
|
[ "${NETWORK_MODE}" != "null" ] && [ -n "${NETWORK_MODE}" ] && RUN_ARGS+=( --network "${NETWORK_MODE}" )
|
||||||
|
|
||||||
|
# 环境变量
|
||||||
|
while IFS= read -r env_line; do
|
||||||
|
[ -z "${env_line}" ] && continue
|
||||||
|
RUN_ARGS+=( -e "${env_line}" )
|
||||||
|
done < <(jq -r '.Config.Env[]?' /tmp/old.json)
|
||||||
|
|
||||||
|
# 端口映射
|
||||||
|
while IFS=$'\t' read -r cport hostip hostport; do
|
||||||
|
[ -z "${cport}" ] && continue
|
||||||
|
proto=""
|
||||||
|
if [[ "${cport}" == */udp ]]; then
|
||||||
|
proto="/udp"
|
||||||
|
cport="${cport%/udp}"
|
||||||
|
elif [[ "${cport}" == */tcp ]]; then
|
||||||
|
cport="${cport%/tcp}"
|
||||||
|
fi
|
||||||
|
if [ -n "${hostport}" ]; then
|
||||||
|
ip_part=""
|
||||||
|
[ -n "${hostip}" ] && ip_part="${hostip}:"
|
||||||
|
RUN_ARGS+=( -p "${ip_part}${hostport}:${cport}${proto}" )
|
||||||
|
else
|
||||||
|
RUN_ARGS+=( -p "${cport}${proto}" )
|
||||||
|
fi
|
||||||
|
done < <(jq -r '.HostConfig.PortBindings | to_entries[]? | .key as $k | .value[]? | [$k, .HostIp, .HostPort] | @tsv' /tmp/old.json)
|
||||||
|
|
||||||
|
# 卷挂载
|
||||||
|
while IFS= read -r mline; do
|
||||||
|
[ -z "${mline}" ] && continue
|
||||||
|
RUN_ARGS+=( ${mline} )
|
||||||
|
done < <(jq -r '.Mounts[]? | select(.Type=="bind" or .Type=="volume") as $m
|
||||||
|
| if $m.Type == "bind" then
|
||||||
|
"-v " + $m.Source + ":" + $m.Destination + (if $m.ReadOnly then ":ro" else "" end)
|
||||||
|
else
|
||||||
|
"-v " + $m.Name + ":" + $m.Destination + (if $m.ReadOnly then ":ro" else "" end)
|
||||||
|
end' /tmp/old.json 2>/dev/null || true)
|
||||||
|
|
||||||
|
# Extra hosts
|
||||||
|
while IFS= read -r h; do
|
||||||
|
[ -z "${h}" ] && continue
|
||||||
|
RUN_ARGS+=( --add-host "${h}" )
|
||||||
|
done < <(jq -r '.HostConfig.ExtraHosts[]?' /tmp/old.json 2>/dev/null || true)
|
||||||
|
|
||||||
|
echo "[4/6] 以相同参数启动新容器 (${#RUN_ARGS[@]} args)"
|
||||||
|
NEW_CID=$($SUDO docker run "${RUN_ARGS[@]}" "${NEW_IMAGE}")
|
||||||
|
echo "新容器ID: ${NEW_CID}"
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
NEW_STATUS=$($SUDO docker inspect -f '{{.State.Status}}' "${NEW_CID}" 2>/dev/null || echo "unknown")
|
||||||
|
echo "新容器状态: ${NEW_STATUS}"
|
||||||
|
if [ "${NEW_STATUS}" != "running" ] && [ "${NEW_STATUS}" != "created" ]; then
|
||||||
|
echo "[ERROR] 新容器未正常运行,输出最近日志后回滚。"
|
||||||
|
$SUDO docker logs --tail 60 "${NEW_CID}" || true
|
||||||
|
$SUDO docker rm -f "${NEW_CID}" 2>/dev/null || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[5/6] 停用旧容器并切换新容器为目标名称"
|
||||||
|
$SUDO docker stop -t 30 "$CONTAINER" 2>/dev/null || true
|
||||||
|
$SUDO docker rm -f "$CONTAINER" 2>/dev/null || true
|
||||||
|
$SUDO docker rename "${CONTAINER}_new" "$CONTAINER"
|
||||||
|
|
||||||
|
echo "[6/6] 清理旧镜像 / 悬空镜像"
|
||||||
|
$SUDO docker image prune -f >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
FINAL_IMG=$($SUDO docker inspect -f '{{.Config.Image}}' "$CONTAINER")
|
||||||
|
echo "✅ 部署完成 @ $(date) 。容器 $CONTAINER 当前镜像: ${FINAL_IMG}"
|
||||||
|
|||||||
Reference in New Issue
Block a user