자동 배포 스크립트 생성
이 단계에서는 RHEL 컨테이너를 일관되고 반복적으로 배포하는 방법을 보여주는 자동화 스크립트를 생성합니다. 이 스크립트는 VM 자동화를 위해 Kickstart 파일을 사용하는 것과 동일한 역할을 하지만, 컨테이너화된 RHEL 배포에 맞게 조정되었습니다. 이 스크립트는 이미지 빌드, 컨테이너 배포 및 기본적인 상태 검사를 처리합니다.
먼저, 프로젝트 디렉토리에 있는지 확인합니다.
cd ~/project
Kickstart 및 virt-install을 사용하여 달성할 수 있는 자동화 기능을 모방하는 배포 자동화 스크립트를 생성합니다.
nano deploy-rhel-container.sh
포괄적인 배포 스크립트를 생성하려면 다음 내용을 추가합니다.
#!/bin/bash
## RHEL 컨테이너 자동 배포 스크립트
## 이 스크립트는 컨테이너 기반 RHEL 배포 자동화를 시연합니다.
## VM용 Kickstart 자동화와 유사하지만 컨테이너용입니다.
set -e ## 오류 발생 시 종료
## 구성 변수
IMAGE_NAME="rhel9-automated"
IMAGE_TAG="latest"
CONTAINER_NAME="rhel9-production"
HOST_PORT="8080"
CONTAINER_PORT="8080"
DOCKERFILE="rhel9-automated.dockerfile"
## 출력용 색상 코드
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' ## 색상 없음
## 색상 출력을 인쇄하는 함수
print_status() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
## Docker가 실행 중인지 확인하는 함수
check_docker() {
print_status "Docker 가용성 확인..."
if ! docker info > /dev/null 2>&1; then
print_error "Docker가 실행 중이거나 액세스할 수 없습니다."
exit 1
fi
print_success "Docker를 사용할 수 있습니다."
}
## 이미지를 빌드하는 함수
build_image() {
print_status "RHEL 컨테이너 이미지 빌드..."
if [ ! -f "$DOCKERFILE" ]; then
print_error "Dockerfile '$DOCKERFILE'을(를) 찾을 수 없습니다."
exit 1
fi
docker build -t "${IMAGE_NAME}:${IMAGE_TAG}" -f "$DOCKERFILE" .
print_success "이미지 '${IMAGE_NAME}:${IMAGE_TAG}'가 성공적으로 빌드되었습니다."
}
## 기존 컨테이너를 중지하고 제거하는 함수
cleanup_existing() {
print_status "기존 컨테이너 확인..."
if docker ps -a | grep -q "$CONTAINER_NAME"; then
print_warning "기존 컨테이너 '$CONTAINER_NAME'을(를) 중지하고 제거합니다."
docker stop "$CONTAINER_NAME" > /dev/null 2>&1 || true
docker rm "$CONTAINER_NAME" > /dev/null 2>&1 || true
fi
}
## 컨테이너를 배포하는 함수
deploy_container() {
print_status "RHEL 컨테이너 배포..."
docker run -d \
--name "$CONTAINER_NAME" \
-p "${HOST_PORT}:${CONTAINER_PORT}" \
--restart unless-stopped \
"${IMAGE_NAME}:${IMAGE_TAG}"
print_success "컨테이너 '$CONTAINER_NAME'이(가) 성공적으로 배포되었습니다."
}
## 배포를 확인하는 함수
verify_deployment() {
print_status "컨테이너 배포 확인..."
## 컨테이너가 시작될 때까지 대기
sleep 5
## 컨테이너가 실행 중인지 확인
if ! docker ps | grep -q "$CONTAINER_NAME"; then
print_error "컨테이너가 실행 중이 아닙니다."
docker logs "$CONTAINER_NAME"
exit 1
fi
## 웹 서비스가 응답하는지 확인
print_status "웹 서비스 테스트..."
for i in {1..10}; do
if curl -s "http://localhost:${HOST_PORT}" > /dev/null; then
print_success "웹 서비스가 응답합니다."
break
fi
if [ $i -eq 10 ]; then
print_error "10번 시도 후에도 웹 서비스가 응답하지 않습니다."
exit 1
fi
sleep 2
done
}
## 배포 정보를 표시하는 함수
show_deployment_info() {
print_success "=== RHEL 컨테이너 배포 완료 ==="
echo "컨테이너 이름: $CONTAINER_NAME"
echo "이미지: ${IMAGE_NAME}:${IMAGE_TAG}"
echo "포트 매핑: ${HOST_PORT}:${CONTAINER_PORT}"
echo "액세스 URL: http://localhost:${HOST_PORT}"
echo ""
print_status "컨테이너 상태:"
docker ps | grep "$CONTAINER_NAME"
echo ""
print_status "샘플 내용:"
curl -s "http://localhost:${HOST_PORT}" | head -2
}
## 주 배포 프로세스
main() {
echo "=== RHEL 컨테이너 자동 배포 ==="
echo "이 스크립트는 RHEL 컨테이너 배포를 자동화합니다."
echo "기존 설치를 위한 Kickstart 자동화와 유사합니다."
echo ""
check_docker
build_image
cleanup_existing
deploy_container
verify_deployment
show_deployment_info
print_success "자동화된 RHEL 컨테이너 배포가 성공적으로 완료되었습니다!"
}
## 스크립트 인수 처리
case "${1:-deploy}" in
"deploy" | "")
main
;;
"cleanup")
print_status "배포 정리..."
cleanup_existing
docker rmi "${IMAGE_NAME}:${IMAGE_TAG}" 2> /dev/null || true
print_success "정리가 완료되었습니다."
;;
"status")
docker ps | grep "$CONTAINER_NAME" || print_warning "컨테이너가 실행 중이 아님"
;;
*)
echo "사용법: $0 [deploy|cleanup|status]"
echo " deploy - RHEL 컨테이너를 빌드하고 배포합니다(기본값)."
echo " cleanup - 컨테이너를 중지하고 이미지를 제거합니다."
echo " status - 컨테이너 상태를 표시합니다."
exit 1
;;
esac
파일을 저장하고 nano 를 종료합니다 (Ctrl+X, 다음 Y, 다음 Enter).
배포 스크립트 구조 이해
스크립트를 실행하기 전에 이 자동화 스크립트가 어떻게 작동하는지 이해해 보겠습니다. 이 섹션에서는 각 구성 요소에 대한 자세한 설명을 제공하여 초보자가 셸 스크립팅 및 컨테이너 자동화 개념을 더 쉽게 이해할 수 있도록 합니다.
스크립트 헤더 및 오류 처리
#!/bin/bash
set -e ## 오류 발생 시 종료
#!/bin/bash: 이것은 "shebang"이라고 불리며, 시스템에 이 스크립트를 실행하기 위해 Bash 셸을 사용하도록 지시합니다.
set -e: 이 명령은 명령이 실패하면 스크립트가 즉시 종료되도록 하여 잠재적으로 손상된 상태로 계속 진행하는 대신 첫 번째 오류에서 스크립트가 중지되도록 합니다.
구성 변수
## 구성 변수
IMAGE_NAME="rhel9-automated"
IMAGE_TAG="latest"
CONTAINER_NAME="rhel9-production"
HOST_PORT="8080"
CONTAINER_PORT="8080"
DOCKERFILE="rhel9-automated.dockerfile"
이러한 변수는 배포에 대한 모든 주요 매개변수를 정의합니다. 이러한 변수를 맨 위에 배치하면 스크립트 논리를 변경하지 않고도 배포 구성을 쉽게 수정할 수 있습니다. 이는 Kickstart 파일이 구성 매개변수를 사용하는 방식과 유사합니다.
사용자 친화적인 출력 시스템
## 출력용 색상 코드
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' ## 색상 없음
## 색상 출력을 인쇄하는 함수
print_status() {
echo -e "${BLUE}[INFO]${NC} $1"
}
이는 색상 출력을 사용하여 전문적인 로깅 시스템을 생성합니다.
\033[0;31m: 색상에 대한 ANSI 이스케이프 코드 (31 = 빨간색, 32 = 녹색 등)
echo -e: -e 플래그는 색상에 대한 백슬래시 이스케이프의 해석을 활성화합니다.
$1: 함수에 전달된 첫 번째 인수를 참조합니다.
핵심 배포 기능
1. Docker 환경 확인
check_docker() {
print_status "Docker 가용성 확인..."
if ! docker info > /dev/null 2>&1; then
print_error "Docker가 실행 중이거나 액세스할 수 없습니다."
exit 1
fi
print_success "Docker를 사용할 수 있습니다."
}
docker info > /dev/null 2>&1: docker info를 실행하고 출력 (>) 과 오류 (2>&1) 를 모두 /dev/null로 리디렉션합니다 (폐기).
!: 결과를 부정합니다. docker info가 실패하면 (0 이 아닌 값을 반환) 조건이 참이 됩니다.
- 이는 기존 VM 배포에서 가상화가 가능한지 확인하는 것과 같습니다.
2. 이미지 빌드 기능
build_image() {
print_status "RHEL 컨테이너 이미지 빌드..."
if [ ! -f "$DOCKERFILE" ]; then
print_error "Dockerfile '$DOCKERFILE'을(를) 찾을 수 없습니다."
exit 1
fi
docker build -t "${IMAGE_NAME}:${IMAGE_TAG}" -f "$DOCKERFILE" .
print_success "이미지 '${IMAGE_NAME}:${IMAGE_TAG}'가 성공적으로 빌드되었습니다."
}
[ ! -f "$DOCKERFILE" ]: Dockerfile 이 존재하지 않는지 테스트합니다 (!는 부정을 나타내고, -f는 파일 존재 여부를 테스트합니다).
docker build -t: 태그 (이름:버전) 가 있는 컨테이너 이미지를 생성합니다.
- 이는 ISO 미디어에서 기존 설치 프로세스를 대체합니다.
3. 정리 기능
cleanup_existing() {
print_status "기존 컨테이너 확인..."
if docker ps -a | grep -q "$CONTAINER_NAME"; then
print_warning "기존 컨테이너 '$CONTAINER_NAME'을(를) 중지하고 제거합니다."
docker stop "$CONTAINER_NAME" > /dev/null 2>&1 || true
docker rm "$CONTAINER_NAME" > /dev/null 2>&1 || true
fi
}
docker ps -a | grep -q: 모든 컨테이너를 나열하고 컨테이너 이름을 조용히 검색합니다.
|| true: 컨테이너가 존재하지 않더라도 명령이 항상 성공하도록 합니다 (0 반환).
- 이는 기존 배포와의 충돌을 방지합니다.
4. 컨테이너 배포
deploy_container() {
print_status "RHEL 컨테이너 배포..."
docker run -d \
--name "$CONTAINER_NAME" \
-p "${HOST_PORT}:${CONTAINER_PORT}" \
--restart unless-stopped \
"${IMAGE_NAME}:${IMAGE_TAG}"
print_success "컨테이너 '$CONTAINER_NAME'이(가) 성공적으로 배포되었습니다."
}
-d: 분리 모드 (백그라운드) 에서 컨테이너를 실행합니다.
-p "${HOST_PORT}:${CONTAINER_PORT}": 호스트 포트를 컨테이너 포트에 매핑합니다.
--restart unless-stopped: 컨테이너가 예기치 않게 중지되면 자동으로 다시 시작합니다 (수동 중지 제외).
\: 여러 줄 명령에 대한 줄 연속 문자
5. 상태 확인
verify_deployment() {
print_status "컨테이너 배포 확인..."
## 컨테이너가 시작될 때까지 대기
sleep 5
## 컨테이너가 실행 중인지 확인
if ! docker ps | grep -q "$CONTAINER_NAME"; then
print_error "컨테이너가 실행 중이 아닙니다."
docker logs "$CONTAINER_NAME"
exit 1
fi
## 웹 서비스가 응답하는지 확인
print_status "웹 서비스 테스트..."
for i in {1..10}; do
if curl -s "http://localhost:${HOST_PORT}" > /dev/null; then
print_success "웹 서비스가 응답합니다."
break
fi
if [ $i -eq 10 ]; then
print_error "10번 시도 후에도 웹 서비스가 응답하지 않습니다."
exit 1
fi
sleep 2
done
}
{1..10}: Bash 중괄호 확장 - 1, 2, 3... 10 시퀀스를 생성합니다.
curl -s: 무음 모드 HTTP 요청
break: 서비스가 응답하면 루프를 조기에 종료합니다.
- 이는 시간 초과와 함께 재시도 메커니즘을 구현합니다.
명령줄 인터페이스
case "${1:-deploy}" in
"deploy" | "")
main
;;
"cleanup")
print_status "배포 정리..."
cleanup_existing
docker rmi "${IMAGE_NAME}:${IMAGE_TAG}" 2> /dev/null || true
print_success "정리가 완료되었습니다."
;;
"status")
docker ps | grep "$CONTAINER_NAME" || print_warning "컨테이너가 실행 중이 아님"
;;
*)
echo "사용법: $0 [deploy|cleanup|status]"
exit 1
;;
esac
${1:-deploy}: 매개변수 확장 - $1(첫 번째 인수) 또는 "deploy"를 기본값으로 사용합니다.
case 문: 다른 언어의 switch/case와 유사합니다.
;;: 각 case 분기를 종료합니다.
$0: 스크립트 자체의 이름을 참조합니다.
이는 시스템 관리자가 배포, 유지 관리 및 모니터링에 다양한 도구를 사용하는 방식과 유사하게 여러 작업에 사용할 수 있는 다목적 스크립트를 생성합니다.
스크립트를 실행 가능하게 만듭니다.
chmod +x deploy-rhel-container.sh
이제 자동화된 배포 스크립트를 실행하여 전체 자동화 프로세스를 확인합니다.
./deploy-rhel-container.sh
전체 배포 프로세스를 보여주는 출력을 볼 수 있습니다.
=== RHEL 컨테이너 자동 배포 ===
이 스크립트는 RHEL 컨테이너 배포를 자동화합니다.
기존 설치를 위한 Kickstart 자동화와 유사합니다.
[INFO] Docker 가용성 확인...
[SUCCESS] Docker를 사용할 수 있습니다.
[INFO] RHEL 컨테이너 이미지 빌드...
[SUCCESS] 이미지 'rhel9-automated:latest'가 성공적으로 빌드되었습니다.
[INFO] 기존 컨테이너 확인...
[INFO] RHEL 컨테이너 배포...
[SUCCESS] 컨테이너 'rhel9-production'이(가) 성공적으로 배포되었습니다.
[INFO] 컨테이너 배포 확인...
[INFO] 웹 서비스 테스트...
[SUCCESS] 웹 서비스가 응답합니다.
[SUCCESS] === RHEL 컨테이너 배포 완료 ===
컨테이너 이름: rhel9-production
이미지: rhel9-automated:latest
포트 매핑: 8080:8080
액세스 URL: http://localhost:8080
다양한 스크립트 옵션을 테스트합니다.
./deploy-rhel-container.sh status
스크립트 실행 단계별 안내
스크립트를 실행하면 다음 시퀀스가 자동으로 실행됩니다.
1. 환경 유효성 검사 단계
스크립트는 먼저 Docker 를 사용할 수 있고 액세스할 수 있는지 확인합니다. 컨테이너 배포에는 작동하는 Docker 환경이 필요하므로 VM 배포에 작동하는 하이퍼바이저가 필요한 것과 유사합니다.
2. 이미지 빌드 단계
스크립트는 Dockerfile 에서 새 컨테이너 이미지를 빌드합니다. 이 프로세스는 다음과 같습니다.
rhel9-automated.dockerfile을 읽습니다.
- 이미 존재하지 않는 경우 기본 UBI9 이미지를 다운로드합니다.
- Dockerfile 의 각 명령을 실행합니다.
rhel9-automated:latest로 태그된 새 이미지를 생성합니다.
3. 정리 단계
배포하기 전에 스크립트는 동일한 이름을 가진 기존 컨테이너가 있는지 확인하고 제거합니다. 이는 이름 충돌 없이 깨끗한 배포를 보장합니다.
4. 배포 단계
스크립트는 다음을 사용하여 새 컨테이너를 생성하고 시작합니다.
- 분리 모드: 컨테이너가 백그라운드에서 실행됩니다.
- 포트 매핑: 호스트 포트 8080 이 컨테이너 포트 8080 에 매핑됩니다.
- 다시 시작 정책: 컨테이너가 예기치 않게 중지되면 자동으로 다시 시작됩니다.
- 명명된 컨테이너: 쉬운 식별 및 관리
5. 확인 단계
스크립트는 성공적인 배포를 보장하기 위해 상태 검사를 수행합니다.
- 컨테이너 상태 확인: 컨테이너가 실행 중인지 확인합니다.
- 서비스 가용성 확인: HTTP 서비스 응답을 테스트합니다.
- 재시도 메커니즘: 2 초 간격으로 최대 10 번 시도합니다.
- 자동 오류 감지: 확인에 실패하면 오류와 함께 종료됩니다.
6. 정보 표시 단계
마지막으로 스크립트는 컨테이너 세부 정보, 액세스 URL 및 샘플 콘텐츠를 포함한 포괄적인 배포 정보를 표시합니다.
실제 사용 예
이 스크립트를 다양한 방식으로 사용할 수 있습니다.
정상적인 배포:
./deploy-rhel-container.sh
## 또는 명시적으로
./deploy-rhel-container.sh deploy
배포 상태 확인:
./deploy-rhel-container.sh status
리소스 정리:
./deploy-rhel-container.sh cleanup
스크립트 도움말 보기:
./deploy-rhel-container.sh help
기존 방법보다 유리한 점
이 자동화 방식은 기존 Kickstart + VM 배포에 비해 몇 가지 장점을 제공합니다.
- 속도: 컨테이너 시작은 일반적으로 VM 부팅보다 10-100 배 빠릅니다.
- 리소스 효율성: 컨테이너는 호스트 커널을 공유하여 메모리와 CPU 를 덜 사용합니다.
- 일관성: 동일한 컨테이너가 서로 다른 환경에서 동일하게 실행됩니다.
- 확장성: 여러 인스턴스를 쉽게 생성하거나 수평적으로 확장할 수 있습니다.
- 이식성: Docker 가 설치된 모든 시스템에서 실행할 수 있습니다.
- 버전 관리: 컨테이너 이미지를 버전 관리하고 레지스트리에 저장할 수 있습니다.
이 자동화 스크립트는 최신 컨테이너 기반 RHEL 배포가 기존 Kickstart 기반 VM 설치와 동일한 수준의 자동화 및 일관성을 달성할 수 있음을 보여주지만, 더 빠른 배포, 더 나은 리소스 활용, 최신 클라우드 환경에서 더 쉬운 확정과 같은 컨테이너화의 추가적인 이점을 제공합니다.