All checks were successful
deploy-dev / deploy (push) Successful in 36s
웹 티어(211.37.173.197 / Rocky 8): - csv.wise.ai.kr nginx vhost + Let's Encrypt SSL - WAS는 SSH 터널(arko-was-tunnel.service)로 연결 — 개발서버가 NAT 뒤라 8088이 포워딩되지 않고 Tomcat도 127.0.0.1 바인딩이기 때문이다. 키는 WAS에서 restrict,permitopen="127.0.0.1:8088" 로 묶어 셸 접근 불가. - 정적 리소스는 운영 웹이 직접 서빙하고 없으면 @was 폴백 — 전환 중에도 깨지지 않는다. 파이프라인: git push -> 개발 WAS 배포 -> 개발 헬스체크 -> 운영 웹 정적 배포 -> 운영 검증 개발 헬스체크를 통과한 뒤에만 운영으로 넘어간다. 접속 방향은 개발->운영(개발서버는 NAT 뒤라 역방향 접속이 불가능하다).
77 lines
3.5 KiB
Bash
77 lines
3.5 KiB
Bash
#!/usr/bin/env bash
|
|
# 개발서버(zio-server)에서 실행 — 운영 웹서버로 정적 리소스를 배포한다.
|
|
#
|
|
# 설치 위치: /opt/arko-dev/bin/arko-prodweb-deploy.sh
|
|
# 호출 주체: Gitea Actions(.gitea/workflows/deploy-dev.yml) 마지막 단계, 또는 수동
|
|
#
|
|
# 흐름: git push → CI → 개발 WAS 배포 → (헬스체크 통과) → 이 스크립트 → 운영 웹 반영
|
|
#
|
|
# 방향이 개발 → 운영이다. 운영 웹서버(211.37.173.197)는 NAT 밖 공인망에 있고
|
|
# SSH 9271이 열려 있어 개발서버에서 바로 접속할 수 있다.
|
|
# 반대로 개발서버는 NAT 뒤라 운영에서 먼저 접속할 수 없다.
|
|
#
|
|
# 배포 대상은 방금 개발 WAS에 전개된 ROOT의 정적 리소스다.
|
|
# WAR를 다시 풀지 않고 실제 서비스 중인 파일을 그대로 복사하므로
|
|
# 개발과 운영 웹이 항상 같은 산출물을 바라본다.
|
|
set -euo pipefail
|
|
|
|
PROD_HOST=211.37.173.197
|
|
PROD_PORT=9271
|
|
PROD_USER=root
|
|
KEY=/root/.ssh/id_arko_prodweb
|
|
SRC_ROOT=/opt/arko-dev/tomcat/webapps/ROOT
|
|
DEST=/var/www/csv.wise.ai.kr/static
|
|
SITE=https://csv.wise.ai.kr/
|
|
DIRS="images css js fonts new"
|
|
|
|
log() { echo "[$(date +'%F %T')] $*"; }
|
|
die() { echo "[$(date +'%F %T')] ERROR: $*"; exit 1; }
|
|
|
|
SSH_OPTS="-p $PROD_PORT -i $KEY -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new -o ConnectTimeout=20 -o BatchMode=yes"
|
|
|
|
# ------------------------------------------------------------ 1. 사전 확인
|
|
[ -f "$KEY" ] || die "배포 키가 없다: $KEY"
|
|
[ -d "$SRC_ROOT" ] || die "전개된 ROOT가 없다: $SRC_ROOT (개발 배포가 선행되어야 한다)"
|
|
|
|
log "운영 웹서버 접속 확인 ($PROD_HOST:$PROD_PORT)"
|
|
ssh $SSH_OPTS "$PROD_USER@$PROD_HOST" "test -d $DEST" \
|
|
|| die "접속 또는 대상 디렉토리 확인 실패 — 운영 웹에서 05-prodweb-prepare.sh 를 먼저 실행할 것"
|
|
|
|
# ------------------------------------------------------------ 2. 동기화
|
|
# --delete 는 쓰지 않는다. 운영 웹에만 있는 파일(수동 배치분)을 지워버릴 수 있고,
|
|
# 정적 리소스는 누적되어도 문제가 없다. 대신 크기·시각이 다른 것만 전송한다.
|
|
TOTAL=0
|
|
for d in $DIRS; do
|
|
if [ ! -d "$SRC_ROOT/$d" ]; then
|
|
log "건너뜀(원본 없음): $d"
|
|
continue
|
|
fi
|
|
SIZE=$(du -sh "$SRC_ROOT/$d" | cut -f1)
|
|
log "동기화: $d ($SIZE)"
|
|
OUT=$(rsync -az --stats --human-readable \
|
|
-e "ssh $SSH_OPTS" \
|
|
"$SRC_ROOT/$d/" "$PROD_USER@$PROD_HOST:$DEST/$d/" 2>&1) || die "rsync 실패: $d"
|
|
N=$(echo "$OUT" | grep -oE "Number of regular files transferred: [0-9,]+" | grep -oE "[0-9,]+$" | tr -d ',')
|
|
N=${N:-0}
|
|
TOTAL=$((TOTAL + N))
|
|
log " 전송 $N 개"
|
|
done
|
|
log "총 전송 파일 수: $TOTAL"
|
|
|
|
# ------------------------------------------------------------ 3. 검증
|
|
log "운영 웹 확인"
|
|
CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 30 "$SITE" || echo 000)
|
|
log "$SITE → HTTP $CODE"
|
|
[ "$CODE" = "200" ] || [ "$CODE" = "302" ] || die "운영 웹이 정상 응답하지 않는다 (HTTP $CODE)"
|
|
|
|
# 정적 파일이 실제로 운영 웹에서 나오는지 표본 확인.
|
|
# X-Cache 헤더가 없으므로 nginx access_log 대신 응답 코드로만 판단한다.
|
|
SAMPLE=$(find "$SRC_ROOT/images" -maxdepth 2 -type f \( -name "*.png" -o -name "*.jpg" -o -name "*.gif" \) 2>/dev/null | head -1)
|
|
if [ -n "$SAMPLE" ]; then
|
|
REL=${SAMPLE#$SRC_ROOT}
|
|
SCODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 20 "https://csv.wise.ai.kr$REL" || echo 000)
|
|
log "표본 정적 파일 $REL → HTTP $SCODE"
|
|
fi
|
|
|
|
log "운영 웹 배포 완료"
|