배포와 테스트 자동화
이번 실습 또한 지난 글에서 하던 것에 이어서 진행한다.
실습 레포지토리: https://github.com/bestlalala/jenkins-practice.git
1. 컨테이너 생성 자동화
Jenkinsfile에 Docker 컨테이너를 생성하고 실행하는 코드를 추가하여 CI/CD 파이프라인을 완성할 수 있다.
예를 들어, 컨테이너를 자동으로 생성하려면 Jenkinsfile에 다음과 같은 단계를 추가한다.
stage('Run Docker Container') {
steps {
sh 'docker run -d --name 컨테이너이름 -p 외부포트:내부포트 이미지이름'
}
}
- docker run 명령어는 Docker 이미지를 기반으로 컨테이너를 생성하고 실행한다.
-d
옵션은 컨테이너를 백그라운드에서 실행하도록 설정한다.--name
옵션은 컨테이너의 이름을 지정한다.-p
옵션은 외부와 내부 포트를 매핑하여 호스트에서 애플리케이션에 접근할 수 있도록 한다.
배포 단계에서 컨테이너 실행
Jenkinsfile의 deploy 단계에 아래와 같은 코드를 추가하면, 빌드된 이미지를 바로 실행할 수 있다.
stage('deploy'){
steps{
sh "docker run -d --rm -p 8765:8080 --name calculator bestlalala/calculator"
}
}
이 코드는 Jenkins 파이프라인에서 Docker 이미지를 배포 후 자동으로 실행하게 한다.
⛔️ 컨테이너 이름 충돌 해결
같은 이름의 컨테이너가 이미 실행 중이면 오류가 발생할 수 있다. 이를 방지하기 위해 기존 컨테이너를 중지하고 삭제해야 한다. 아래 명령어를 사용하면 된다:
docker ps # 실행 중인 컨테이너 목록 확인
docker stop calculator # 실행 중인 컨테이너 중지
docker rm calculator # 중지된 컨테이너 삭제
이 명령어로 이름 충돌 문제를 해결한 뒤 새 컨테이너를 생성하면 오류 없이 파이프라인이 동작한다.
🪄 기존 컨테이너 제거 후 새 컨테이너 실행 자동화
매번 빌드할 때마다 컨테이너를 삭제하고 빌드할 필요 없이, deploy
단계에서 실행 중인 컨테이너를 중지 및 제거한 후 새 컨테이너를 실행하게 할 수 있다. 이러한 방식은 안정적인 배포 환경을 유지하는 데 매우 유용하다. 이를 통해 포트 충돌이나 리소스 중복 문제를 방지할 수 있다.
stage('deploy'){
steps{
sh 'docker rm -f calculator || true' // 기존 컨테이너 제거
sh "docker run -d --rm -p 8765:8080 --name calculator bestlalala/calculator"
}
}
2. 인수 테스트 자동화
1) 테스트 스크립트 작성
루트 디렉터리에 테스트 스크립트를 작성하여 애플리케이션의 주요 기능을 자동으로 검증할 수 있다.
예시로 다음과 같이 작성한다: acceptance\_test.sh
#!/bin/bash
response=$(curl -s "http://localhost:8765/sum?a=10&b=3")
echo "Server response: $response"
if [ "$response" -eq 13 ]; then
echo "Test passed"
else
echo "Test failed"
exit 1
fi
- curl 명령어를 사용해 특정 API 엔드포인트를 호출하고, 응답값을 변수로 저장한다.
- 조건문으로 응답값이 예상값(13)과 일치하는지 확인하여, 테스트 성공 여부를 판단한다.
2) Jenkinsfile에 테스트 단계 추가
Jenkinsfile에 해당 스크립트를 실행하는 단계를 추가한다:
stage('acceptance test'){
steps{
sleep 60
sh 'chmod +x acceptance_test.sh && ./acceptance_test.sh'
}
}
- sleep 60은 컨테이너가 완전히 실행될 때까지 60초를 기다리는 역할을 한다.
여기서 sleep
을 사용하는 이유는 컨테이너가 실행이 되고나서 다음 명령어를 실행하도록 하기 위해서다.
docker run -d
명령은 비동기 방식으로 실행되기 때문에, 연속해서 테스트하는 명령을 사용하면 컨테이너가 만들어지기 전에 테스트를 해서 실행은 제대로 되는데 테스트 단계에서 실패로 판정하는 경우가 발생할 수 있다.
젠킨스 빌드 로그 확인
Jenkins의 Console Output에서 파이프라인의 각 단계가 제대로 실행되었는지 확인할 수 있다.
sleep 60
명령 때문에 도커 컨테이너를 생성하고 나서 1분동안 기다리는 것을 확인할 수 있다.
콘솔 확인
Pipeline console을 확인해보면 다음과 같이 테스트 스크립트 실행이 성공한 것을 확인할 수 있다.
3. Post 블록으로 리소스 관리
Jenkins 파이프라인에서 post
블록은 특정 스테이지나 전체 파이프라인의 실행이 완료된 후, 추가로 수행할 작업을 정의하는 데 사용된다. 파이프라인의 성공 여부와 관계없이 항상 실행되거나, 특정 조건에 따라 실행되도록 설정할 수 있다.
1) post 블록 구조 및 주요 요소
post {
always {
// 항상 실행되는 작업
}
success {
// 파이프라인이 성공했을 때만 실행
}
failure {
// 파이프라인이 실패했을 때만 실행
}
unstable {
// 빌드가 unstable 상태일 때 실행
}
aborted {
// 빌드가 중단되었을 때 실행
}
}
2) 자주 사용하는 옵션
- always: 파이프라인의 성공 여부와 상관없이 항상 실행되는 블록.
- 주로 리소스 정리 작업에 사용.
- success: 파이프라인이 성공했을 때만 실행.
- 성공 시 알림 발송, 결과 저장 등.
- failure: 파이프라인이 실패했을 때만 실행.
- 실패 원인 분석, 오류 로그 저장, 알림 발송 등.
- unstable: 테스트 실패 등으로 빌드가 불안정(unstable) 상태일 때 실행.
- aborted: 빌드가 사용자에 의해 중단되었을 때 실행.
3) Clean up 스테이지 예시
파이프라인 실행 후 리소스를 정리하여 서버를 효율적으로 관리하기 위해, post
블록을 사용하여 컨테이너를 중지하는 코드를 추가한다:
post {
always {
sh 'docker stop calculator || true' // 컨테이너 중지
}
}
- always 블록은 파이프라인 성공 여부와 관계없이 항상 실행된다.
- 중복 실행 오류를 방지하기 위해 || true를 추가하여 중지할 컨테이너가 없더라도 오류가 발생하지 않도록 설정한다.
이렇게 하면 파이프라인이 종료될 때마다 자동으로 리소스가 정리되며, 서버 상태를 깨끗하게 유지할 수 있다.