Files
api2/Jenkinsfile.pjt
T
sdw086 9c85d89f07 [api] Jenkinsfile.pjt
- 삭제정책 추가
2026-02-04 15:41:34 +09:00

307 lines
9.1 KiB
Plaintext

pipeline {
agent any
options {
timestamps()
disableConcurrentBuilds()
}
environment {
// ===== Registry =====
REGISTRY_HOST = "registry.pjt.kr"
IMAGE_REPO = "alist/api"
DOCKER_CRED = "registry-pjt"
// ===== api ssh =====
SSH_HOST = "121.160.234.222"
SSH_PORT = "2001"
SSH_USER = "bigfuntnp"
SSH_COMPOSE_DIR = "/srv/project/alist/compose"
SSH_COMPOSE_FILE = "api-compose.pjt.yml"
// ===== jenkins workspace path =====
WORK_COMPOSE_DIR = "deploy/pjt/compose"
WORK_COMPOSE_FILE = "api-compose.pjt.yml"
}
stages {
stage('1) Git check out') {
steps {
echo "[1/1] Git check out"
checkout scm
}
}
stage('2) Build (Gradle)') {
steps {
sh '''
set -e
echo "[1/1] Gradle build"
chmod +x ./gradlew
./gradlew clean build -x test
'''
}
}
stage('3) ImageTag create') {
steps {
script {
echo "[1/1] ImageTag create"
env.SHORT_SHA = sh(script: "git rev-parse --short HEAD", returnStdout: true).trim()
echo "SHORT_SHA = ${env.SHORT_SHA}"
env.IMAGE_TAG = "${env.BUILD_NUMBER}-${env.SHORT_SHA}"
echo "IMAGE_TAG = ${env.IMAGE_TAG}"
}
}
}
stage('4) Docker Build') {
steps {
sh '''
set -e
echo "[1/1] docker build"
docker build -t ${REGISTRY_HOST}/${IMAGE_REPO}:${IMAGE_TAG} .
'''
}
}
stage('5) Docker registry Login & Push') {
steps {
withCredentials([usernamePassword(
credentialsId: DOCKER_CRED,
usernameVariable: 'DOCKER_USER',
passwordVariable: 'DOCKER_PASS'
)]) {
sh '''
set -e
echo "[1/2] docker registry login"
echo "$DOCKER_PASS" | docker login ${REGISTRY_HOST} \
-u "$DOCKER_USER" --password-stdin
echo "[2/2] docker image push"
docker push ${REGISTRY_HOST}/${IMAGE_REPO}:${IMAGE_TAG}
docker logout ${REGISTRY_HOST}
'''
}
}
}
stage('6) Jenkins cleanup') {
steps {
sh '''
set -e
echo "[1/3] Remove pushed image from Jenkins"
docker rmi ${REGISTRY_HOST}/${IMAGE_REPO}:${IMAGE_TAG} 2>/dev/null || true
echo "[2/3] Remove dangling images"
docker image prune -f
echo "[3/3] Remove old build cache (safe-ish)"
docker builder prune -f || true
'''
}
}
stage('7) Copy compose') {
steps {
sshagent(['ssh-pjt']) {
sh '''
set -e
echo "[1/2] ssh login"
SRC="${WORK_COMPOSE_DIR}/${WORK_COMPOSE_FILE}"
DST="${SSH_USER}@${SSH_HOST}:${SSH_COMPOSE_DIR}/${SSH_COMPOSE_FILE}"
echo "[2/2] Copy compose $SRC -> $DST"
scp -P ${SSH_PORT} -o StrictHostKeyChecking=no "$SRC" "$DST"
'''
}
}
}
stage('8) Remote docker registry login') {
steps {
sshagent(['ssh-pjt']) {
withCredentials([usernamePassword(
credentialsId: DOCKER_CRED,
usernameVariable: 'DOCKER_USER',
passwordVariable: 'DOCKER_PASS'
)]) {
sh '''
set -e
echo "[1/1] docker registry login"
ssh -p ${SSH_PORT} \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
${SSH_USER}@${SSH_HOST} \
'set -e
REGISTRY_HOST='"${REGISTRY_HOST}"'
DOCKER_USER='"${DOCKER_USER}"'
DOCKER_PASS='"${DOCKER_PASS}"'
echo "$DOCKER_PASS" | docker login "$REGISTRY_HOST" -u "$DOCKER_USER" --password-stdin
'
'''
}
}
}
}
stage('9) Remote docker pull') {
steps {
sshagent(['ssh-pjt']) {
sh '''
set -e
ssh -p ${SSH_PORT} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
${SSH_USER}@${SSH_HOST} \
'set -e
cd '"${SSH_COMPOSE_DIR}"'
export IMAGE_TAG='"${IMAGE_TAG}"'
echo "[1/1] docker pull"
docker compose -p alist-api --env-file /srv/project/alist/env/api/.env -f '"${SSH_COMPOSE_FILE}"' pull
'
'''
}
}
}
stage('10) Remote docker down & up') {
steps {
sshagent(['ssh-pjt']) {
sh '''
set -e
ssh -p ${SSH_PORT} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
${SSH_USER}@${SSH_HOST} \
'set -e
cd '"${SSH_COMPOSE_DIR}"'
export IMAGE_TAG='"${IMAGE_TAG}"'
echo "[1/3] docker down (remove orphans)"
docker compose -p alist-api --env-file /srv/project/alist/env/api/.env -f "'"${SSH_COMPOSE_FILE}"'" down --remove-orphans
echo "[2/3] docker up"
docker compose -p alist-api --env-file /srv/project/alist/env/api/.env -f '"${SSH_COMPOSE_FILE}"' up -d
echo "[3/3] docker ps"
docker compose -p alist-api --env-file /srv/project/alist/env/api/.env -f '"${SSH_COMPOSE_FILE}"' ps
'
'''
}
}
}
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 {
withCredentials([usernamePassword(
credentialsId: DOCKER_CRED,
usernameVariable: 'DOCKER_USER',
passwordVariable: 'DOCKER_PASS'
)]) {
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}"
REPO="${IMAGE_REPO}"
KEEP=5
AUTH="'${DOCKER_USER}':'${DOCKER_PASS}'"
command -v jq >/dev/null 2>&1 || (sudo apt-get update -y && sudo apt-get install -y jq)
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)
echo "[2/5] Fetch tags from registry"
TAGS=$(curl -fsS -u "$AUTH" "$REGISTRY_URL/v2/$REPO/tags/list" | jq -r ".tags[]?" || true)
[ -z "$TAGS" ] && { echo "No tags found. Skip."; exit 0; }
echo "[3/5] Sort tags desc"
SORTED=$(echo "$TAGS" | sort -r)
KEEP_TAGS=$(echo "$SORTED" | head -n $KEEP)
DEL_CANDIDATES=$(echo "$SORTED" | tail -n +$((KEEP+1)))
echo "Keep tags:"
echo "$KEEP_TAGS" | sed "s/^/ - /"
echo "[4/5] Delete old tags except 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
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")
[ -z "$DIGEST" ] && { echo "digest not found. skip $TAG"; continue; }
curl -fsS -u "$AUTH" -X DELETE "$REGISTRY_URL/v2/$REPO/manifests/$DIGEST" || true
done
echo "[5/5] Garbage collect"
docker exec registry registry garbage-collect /etc/docker/registry/config.yml
echo "Registry cleanup done."
'
'''
}
}
}
}
}
}