#!/usr/bin/env sh set -eu if [ "$#" -ne 4 ]; then echo "用法: $0 <镜像仓库> <镜像标签> <逗号分隔服务> <环境文件>" >&2 exit 2 fi IMAGE_REPOSITORY="$1" IMAGE_TAG="$2" SERVICE_CSV="$3" ENV_FILE="$4" SSH_TARGET="${DEVELOPMENT_SSH_TARGET:-deploy@172.31.198.8}" SSH_KEY="${DEVELOPMENT_SSH_KEY:-/var/jenkins_home/.ssh/dev_deploy}" SSH_KNOWN_HOSTS="${DEVELOPMENT_SSH_KNOWN_HOSTS:-/var/jenkins_home/.ssh/known_hosts}" REMOTE_DIR="${DEVELOPMENT_DEPLOY_DIR:-/opt/firstleg/application}" COMPOSE_FILE="deploy/docker-compose.yml" if [ ! -f "$SSH_KEY" ]; then echo "开发环境 SSH 私钥不存在: $SSH_KEY" >&2 exit 2 fi if [ ! -f "$SSH_KNOWN_HOSTS" ]; then echo "SSH 主机指纹文件不存在: $SSH_KNOWN_HOSTS" >&2 exit 2 fi if [ ! -f "$ENV_FILE" ]; then echo "开发环境变量文件不存在: $ENV_FILE" >&2 exit 2 fi if [ ! -f "$COMPOSE_FILE" ]; then echo "Compose 文件不存在: $COMPOSE_FILE" >&2 exit 2 fi SERVICES=$(printf '%s' "$SERVICE_CSV" | tr ',' ' ') for service in $SERVICES; do case "$service" in *[!A-Za-z0-9_-]*|'') echo "非法服务名: $service" >&2 exit 2 ;; esac done run_ssh() { ssh -i "$SSH_KEY" \ -o BatchMode=yes \ -o StrictHostKeyChecking=yes \ -o UserKnownHostsFile="$SSH_KNOWN_HOSTS" \ -o ConnectTimeout=10 \ "$SSH_TARGET" "$@" } run_scp() { scp -i "$SSH_KEY" \ -o BatchMode=yes \ -o StrictHostKeyChecking=yes \ -o UserKnownHostsFile="$SSH_KNOWN_HOSTS" \ -o ConnectTimeout=10 \ "$@" } run_ssh install -d -m 750 "$REMOTE_DIR" SUFFIX="${IMAGE_TAG}.$$.${SERVICE_CSV}" REMOTE_ENV_TMP="$REMOTE_DIR/.env.$SUFFIX.tmp" REMOTE_COMPOSE_TMP="$REMOTE_DIR/docker-compose.yml.$SUFFIX.tmp" run_scp "$ENV_FILE" "$SSH_TARGET:$REMOTE_ENV_TMP" run_scp "$COMPOSE_FILE" "$SSH_TARGET:$REMOTE_COMPOSE_TMP" run_ssh sh -s -- "$REMOTE_DIR" "$REMOTE_ENV_TMP" "$REMOTE_COMPOSE_TMP" <<'REMOTE_PREPARE' set -eu remote_dir="$1" env_tmp="$2" compose_tmp="$3" chmod 600 "$env_tmp" chmod 644 "$compose_tmp" mv -f "$env_tmp" "$remote_dir/.env" mv -f "$compose_tmp" "$remote_dir/docker-compose.yml" REMOTE_PREPARE for service in $SERVICES; do image="$IMAGE_REPOSITORY/$service:$IMAGE_TAG" docker image inspect "$image" >/dev/null echo "传输开发镜像: $image" docker save "$image" | gzip -1 | run_ssh 'gzip -dc | docker load' done run_ssh sh -s -- "$REMOTE_DIR" "$IMAGE_REPOSITORY" "$IMAGE_TAG" "$SERVICE_CSV" <<'REMOTE_DEPLOY' set -eu remote_dir="$1" image_repository="$2" image_tag="$3" service_csv="$4" services=$(printf '%s' "$service_csv" | tr ',' ' ') cd "$remote_dir" export DEPLOY_ENV=development export IMAGE_REPOSITORY="$image_repository" export IMAGE_TAG="$image_tag" docker compose \ --project-name firstleg-development \ --env-file .env \ -f docker-compose.yml \ up -d --remove-orphans --pull never $services docker compose \ --project-name firstleg-development \ --env-file .env \ -f docker-compose.yml \ ps $services REMOTE_DEPLOY