GitLab CI/CD가 뭔지 궁금해서 만든 것.
push 하면 서버에서 자동으로 pull 받고, docker compose 다시 띄우는 구조.
폴더 구조.
setup/
install-runner.sh
register-runner.sh
scripts/
deploy.sh
healthcheck.sh
notify.sh
rollback.sh
templates/
gitlab-ci-build-deploy.yml
gitlab-ci-pull-deploy.yml
gitlab-ci-static.yml
pull-deploy 템플릿.
stages:
- deploy
variables:
DEPLOY_SCRIPTS: /home/opc/0014-deploy-pipeline/scripts
PROJECT_HOME: /home/opc
COMPOSE_FILE: docker/docker-compose.yml
deploy:
stage: deploy
tags:
- production
only:
- main
script:
- cd $PROJECT_HOME/$CI_PROJECT_NAME
- git pull
- docker compose -f $COMPOSE_FILE pull
- docker compose -f $COMPOSE_FILE up -d
- $DEPLOY_SCRIPTS/healthcheck.sh $PROJECT_HOME/$CI_PROJECT_NAME $COMPOSE_FILE
after_script:
- |
if [ "$CI_JOB_STATUS" = "success" ]; then
$DEPLOY_SCRIPTS/notify.sh "$CI_PROJECT_NAME" success
else
$DEPLOY_SCRIPTS/notify.sh "$CI_PROJECT_NAME" failed "파이프라인 실패"
fi
일단 main 브랜치에 push 되면 production runner가 배포.
deploy.sh
#!/usr/bin/env bash
set -euo pipefail
# 공통 배포 스크립트
# 사용법: deploy.sh <프로젝트 경로> [compose 파일]
# 예시: deploy.sh /home/ioniere/workspaces/0008-bingbingsubway
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_DIR="${1:?프로젝트 경로를 지정하세요}"
COMPOSE_FILE="${2:-docker-compose.yml}"
cd "${PROJECT_DIR}"
echo "==> 배포 시작: ${PROJECT_DIR}"
echo " Compose 파일: ${COMPOSE_FILE}"
BACKUP_FILE="${PROJECT_DIR}/.deploy-backup-images"
docker compose -f "${COMPOSE_FILE}" images -q 2>/dev/null | sort -u > "${BACKUP_FILE}" || true
echo "==> docker compose build"
docker compose -f "${COMPOSE_FILE}" build --pull
echo "==> docker compose up -d --force-recreate"
docker compose -f "${COMPOSE_FILE}" up -d --force-recreate
echo "==> 헬스체크 실행"
if ! "${SCRIPT_DIR}/healthcheck.sh" "${PROJECT_DIR}" "${COMPOSE_FILE}"; then
echo "ERROR: 헬스체크 실패, 롤백 실행"
"${SCRIPT_DIR}/rollback.sh" "${PROJECT_DIR}" "${COMPOSE_FILE}"
exit 1
fi
echo "==> 배포 완료: ${PROJECT_DIR}"
build 하고 up 한 다음 헬스체크.
실패하면 rollback.sh 실행.
healthcheck.sh
#!/usr/bin/env bash
set -euo pipefail
# 헬스체크 스크립트: 컨테이너 상태 및 HTTP 응답 확인
# 사용법: healthcheck.sh <프로젝트 경로> [compose 파일]
PROJECT_DIR="${1:?프로젝트 경로를 지정하세요}"
COMPOSE_FILE="${2:-docker-compose.yml}"
MAX_RETRIES="${HEALTHCHECK_RETRIES:-10}"
RETRY_INTERVAL="${HEALTHCHECK_INTERVAL:-3}"
cd "${PROJECT_DIR}"
echo "==> 컨테이너 상태 확인 (최대 ${MAX_RETRIES}회, ${RETRY_INTERVAL}초 간격)"
for i in $(seq 1 "${MAX_RETRIES}"); do
TOTAL=$(docker compose -f "${COMPOSE_FILE}" ps -q | wc -l)
RUNNING=$(docker compose -f "${COMPOSE_FILE}" ps --status running -q | wc -l)
if [[ "${TOTAL}" -gt 0 && "${TOTAL}" -eq "${RUNNING}" ]]; then
echo " 컨테이너 상태 OK (${RUNNING}/${TOTAL} running)"
break
fi
if [[ "${i}" -eq "${MAX_RETRIES}" ]]; then
echo "ERROR: 컨테이너가 정상 상태가 아닙니다 (${RUNNING}/${TOTAL} running)"
docker compose -f "${COMPOSE_FILE}" ps
exit 1
fi
echo " 대기 중... (${i}/${MAX_RETRIES}) ${RUNNING}/${TOTAL} running"
sleep "${RETRY_INTERVAL}"
done
HEALTHCHECK_URL_FILE="${PROJECT_DIR}/.healthcheck-url"
if [[ -f "${HEALTHCHECK_URL_FILE}" ]]; then
URL="$(cat "${HEALTHCHECK_URL_FILE}")"
echo "==> HTTP 헬스체크: ${URL}"
fi
컨테이너 running 상태 확인.
.healthcheck-url 파일이 있으면 HTTP 응답도 확인.
GitLab CI/CD는 그냥 “자동 배포” 정도로 생각했는데,
실제로는 runner, branch, script, healthcheck, rollback까지 같이 봐야 했다.
댓글 0
| 번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
|---|---|---|---|---|
| 공지 | 2025 일본 여행 계획 | 김영훈 | 2024.10.10 | 4119 |
| 공지 | 현금, 저축, 투자, 지출, 예산, 보험 내역(2024-05-30) | 김영훈 | 2024.03.10 | 3752 |
| 297 | DGX Spark LLM 벤치마크 | 김영훈 | 2026.02.11 | 132 |
| 296 | GPU 모니터링 대시보드 구축 | 김영훈 | 2026.02.11 | 150 |
| 295 | Docker Ollama 트러블슈팅 | 김영훈 | 2026.02.11 | 128 |
| 294 | 원격 LLM 챗봇 테스트 | 김영훈 | 2026.02.11 | 140 |
| 293 | DGX Ollama 구축 | 김영훈 | 2026.02.11 | 183 |
| 292 | OpenClaw cron regression 대응 | 김영훈 | 2026.02.08 | 186 |
| 291 | WAF honeypot 설정 | 김영훈 | 2026.02.07 | 104 |
| 290 | smtp-relay 설정 | 김영훈 | 2026.02.06 | 195 |
| 289 | openclaw 구축 작업 노트 [2] | 김영훈 | 2026.02.01 | 341 |
| 288 | Traefik 설정 | 김영훈 | 2026.01.28 | 353 |
| » | GitLab CI/CD 테스트 | 김영훈 | 2026.01.28 | 216 |
| 286 | OpenVPN 구축 | 김영훈 | 2026.01.28 | 143 |
| 285 | ollama-chatbot 테스트 메모 | 김영훈 | 2026.01.27 | 355 |
| 284 | monitoring 설정 | 김영훈 | 2026.01.23 | 130 |
| 283 | 임시 파킹 페이지 | 김영훈 | 2026.01.20 | 308 |
| 282 | infra-base 기본 서버 설정 메모 | 김영훈 | 2026.01.20 | 171 |
| 281 | [바이브코딩 - 클로드] kospiAlarm 작업 메모 | 김영훈 | 2025.10.29 | 109 |
| 280 | [바이브코딩 - 클로드] fullstack_template 작업 메모 | 김영훈 | 2025.10.18 | 243 |
| 279 | [바이브코딩 - 클로드] reminder_android 작업 메모 | 김영훈 | 2025.10.17 | 85 |
| 278 | [바이브코딩 - 클로드] bingbingsubway 작업 메모 | 김영훈 | 2025.10.12 | 165 |