[api] Jenkinsfile.pjt

- 삭제정책 추가
This commit is contained in:
2026-02-04 15:20:27 +09:00
parent a3be7202a3
commit 5618d54a7c
+153 -4
View File
@@ -95,7 +95,27 @@ pipeline {
} }
} }
stage('6) Copy compose') { stage('6) Jenkins cleanup') {
steps {
sh '''
set -e
echo "[1/4] Remove pushed image from Jenkins"
docker rmi ${REGISTRY_HOST}/${IMAGE_REPO}:${IMAGE_TAG} 2>/dev/null || true
echo "[2/4] Remove dangling images"
docker image prune -f
echo "[3/4] Remove old build cache (safe-ish)"
# 빌드 캐시만 정리: 다른 컨테이너/볼륨에는 영향 적음
docker builder prune -f || true
echo "[4/4] Skip docker system prune --volumes (too aggressive on shared nodes)"
'''
}
}
stage('7) Copy compose') {
steps { steps {
sshagent(['ssh-pjt']) { sshagent(['ssh-pjt']) {
sh ''' sh '''
@@ -113,7 +133,7 @@ pipeline {
} }
} }
stage('7) Remote docker registry login') { stage('8) Remote docker registry login') {
steps { steps {
sshagent(['ssh-pjt']) { sshagent(['ssh-pjt']) {
withCredentials([usernamePassword( withCredentials([usernamePassword(
@@ -143,7 +163,7 @@ pipeline {
} }
} }
stage('8) Remote docker pull') { stage('9) Remote docker pull') {
steps { steps {
sshagent(['ssh-pjt']) { sshagent(['ssh-pjt']) {
sh ''' sh '''
@@ -162,7 +182,7 @@ pipeline {
} }
} }
stage('9) Remote docker down & up') { stage('10) Remote docker down & up') {
steps { steps {
sshagent(['ssh-pjt']) { sshagent(['ssh-pjt']) {
sh ''' sh '''
@@ -187,5 +207,134 @@ pipeline {
} }
} }
stage('11) Remote cleanup') {
steps {
sshagent(['ssh-pjt']) {
sh '''
set -e
ssh -p ${SSH_PORT} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
${SSH_USER}@${SSH_HOST} \
'set -e
echo "[0] Collect images used by running containers"
RUNNING_IMAGES=$(docker ps -q | xargs -r docker inspect --format="{{.Image}}" | sort -u)
echo "[1/3] Remove old registry images (except running ones)"
docker images '"${REGISTRY_HOST}/${IMAGE_REPO}"' --format "{{.ID}} {{.CreatedAt}}" | \
sort -k2 -r | \
awk "{print \$1}" | \
while read IMAGE_ID; do
echo "$RUNNING_IMAGES" | grep -q "$IMAGE_ID" && continue
docker rmi -f "$IMAGE_ID" 2>/dev/null || true
done
echo "[2/3] Remove dangling images (safe)"
docker image prune -f
echo "[3/3] Remove unused volumes (safe)"
docker volume prune -f
'
'''
}
}
}
stage('12) Registry cleanup (keep last 5 + protect running)') {
steps {
sshagent(['ssh-pjt']) {
sh '''
set -e
ssh -p ${SSH_PORT} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
${SSH_USER}@${SSH_HOST} \
'set -e
REGISTRY_URL="https://'${REGISTRY_HOST}'" # 예: https://registry.pjt.kr
REPO="'${IMAGE_REPO}'" # 예: alist/api
KEEP=5
# (옵션) Basic Auth 쓰면 아래 활성화하고 curl에 -u "$AUTH" 추가
# AUTH="user:pass"
echo "[0/5] Ensure jq exists"
if ! command -v jq >/dev/null 2>&1; then
sudo apt-get update -y
sudo apt-get install -y jq
fi
echo "[1/5] Collect running tags to protect"
# 현재 서버에서 실행 중인 컨테이너가 사용하는 해당 레포 이미지 태그만 추출
RUNNING_TAGS=$(docker ps --format "{{.Image}}" | \
grep -E "^'${REGISTRY_HOST}'/'${IMAGE_REPO}':" | \
awk -F: "{print \\$2}" | sort -u || true)
if [ -n "$RUNNING_TAGS" ]; then
echo "Running tags (protected):"
echo "$RUNNING_TAGS" | sed "s/^/ - /"
else
echo "No running tags found for ${REGISTRY_HOST}/${IMAGE_REPO} (ok)"
fi
echo "[2/5] Fetch tags from registry: $REPO"
TAGS=$(curl -fsS "$REGISTRY_URL/v2/$REPO/tags/list" | jq -r ".tags[]?" || true)
# Basic Auth 쓰면 위 curl을 아래로 바꿔:
# TAGS=$(curl -fsS -u "$AUTH" "$REGISTRY_URL/v2/$REPO/tags/list" | jq -r ".tags[]?" || true)
if [ -z "$TAGS" ]; then
echo "No tags found in registry. Skip."
exit 0
fi
echo "[3/5] Sort tags desc (tag must be sortable for 'latest' semantics)"
SORTED=$(echo "$TAGS" | sort -r)
KEEP_TAGS=$(echo "$SORTED" | head -n $KEEP)
DEL_CANDIDATES=$(echo "$SORTED" | tail -n +$((KEEP+1)))
echo "Keep tags (latest $KEEP):"
echo "$KEEP_TAGS" | sed "s/^/ - /"
echo "[4/5] Delete old tags except protected running tags"
for TAG in $DEL_CANDIDATES; do
# 실행 중 태그는 무조건 스킵
if [ -n "$RUNNING_TAGS" ] && echo "$RUNNING_TAGS" | grep -qx "$TAG"; then
echo "Skip running tag: $REPO:$TAG"
continue
fi
echo "Deleting $REPO:$TAG"
DIGEST=$(curl -fsSI \
-H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
"$REGISTRY_URL/v2/$REPO/manifests/$TAG" \
| awk -F": " "/Docker-Content-Digest/ {print \\$2}" | tr -d "\\r")
# Basic Auth 쓰면 위 curl을 아래로 바꿔:
# DIGEST=$(curl -fsSI -u "$AUTH" \
# -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
# "$REGISTRY_URL/v2/$REPO/manifests/$TAG" \
# | awk -F": " "/Docker-Content-Digest/ {print \\$2}" | tr -d "\\r")
if [ -z "$DIGEST" ]; then
echo " digest not found. skip $TAG"
continue
fi
curl -fsS -X DELETE "$REGISTRY_URL/v2/$REPO/manifests/$DIGEST" || true
# Basic Auth 쓰면:
# curl -fsS -u "$AUTH" -X DELETE "$REGISTRY_URL/v2/$REPO/manifests/$DIGEST" || true
done
echo "[5/5] Garbage collect (reclaim disk space)"
# push가 진행 중이면 위험할 수 있으니, 배포 성공 후 마지막 단계에서만 실행 추천
docker exec registry registry garbage-collect /etc/docker/registry/config.yml
echo "Registry cleanup done."
'
'''
}
}
}
} }
} }