Docker Swarm 실습 가이드
1. 소개
Docker Swarm은 Docker의 네이티브 클러스터링 솔루션으로, 여러 Docker 호스트를 단일 가상 호스트로 전환하여 애플리케이션을 쉽게 확장할 수 있게 해줍니다.
2. 사전 요구사항
- Amazon Linux 2023 EC2 인스턴스
- 적절한 IAM 권한 (EC2 태그 접근 권한 필요)
- 인스턴스 간 네트워크 통신이 가능한 보안 그룹 설정
2.1. 권장 EC2 인스턴스 타입
- Manager 노드: t3.medium (2 vCPU, 4 GiB RAM) 또는 t3.small (최소 사양)
- Worker 노드: t3.small 또는 t3.micro (최소 사양)
- 스토리지: 최소 8GB EBS 볼륨 (gp3 타입 권장)
2.2. 보안 그룹 설정
Docker Swarm 통신을 위해 다음 포트를 개방해야 합니다:
- TCP 2377: 클러스터 관리 통신
- TCP/UDP 7946: 노드 간 통신
- UDP 4789: 오버레이 네트워크 트래픽
3. Docker Swarm 설정 스크립트 (설치, 초기화, 조인, 리셋)
3.1. 스크립트 개요 및 파일 목록
Docker Swarm 환경을 쉽게 구성할 수 있도록 다음 스크립트 파일들을 제공합니다. 각 스크립트는 특정 역할을 수행하며, 필요에 따라 실행하면 됩니다.
파일명 목적 실행 대상 노드
setup-docker-swarm-node.sh | Docker 설치 및 기본 설정 | 모든 노드 (Manager, Worker) |
setup-swarm-manager.sh | Swarm 클러스터 초기화 및 조인 토큰 생성 | Manager 노드 |
setup-swarm-worker.sh | Swarm 클러스터에 Worker 노드로 조인 | Worker 노드 |
reset-swarm.sh | Swarm 모드 비활성화 및 노드 분리 | 모든 노드 (필요시) |
아래는 각 스크립트의 전체 코드입니다. 스크립트를 생성할 때 아래 내용을 복사하여 사용하세요.
3.2. Docker 설치 스크립트 (setup-docker-swarm-node.sh)
이 스크립트는 Amazon Linux 2023 인스턴스에 Docker를 설치하고 기본 설정을 수행합니다. 모든 노드(Manager와 Worker 모두)에서 실행해야 합니다.
vi setup-docker-swarm-node.sh
#!/bin/bash # Amazon Linux 2023에 Docker 설치 스크립트 (모든 노드용) # 터미널 설정에 따라 색상 사용 여부 결정 if [ -t 1 ]; then # 색상 정의 GREEN='\033[0;32m' BLUE='\033[0;34m' YELLOW='\033[0;33m' CYAN='\033[0;36m' NC='\033[0m' # No Color else # 색상 없음 GREEN='' BLUE='' YELLOW='' CYAN='' NC='' fi echo -e "${GREEN}============================================================${NC}" echo -e "${BLUE}Docker 기본 설치 스크립트 - Amazon Linux 2023${NC}" echo -e "${GREEN}============================================================${NC}" # 목차 출력 echo -e "\n${CYAN}[스크립트 수행 작업 목차]${NC}" echo -e "${CYAN}1. 시스템 패키지 업데이트${NC}" echo -e "${CYAN}2. AWS CLI 설치${NC}" echo -e "${CYAN}3. 호스트명 설정 (EC2 Name 태그 기반)${NC}" echo -e "${CYAN}4. Docker 패키지 설치${NC}" echo -e "${CYAN}5. Docker 서비스 시작 및 자동 시작 설정${NC}" echo -e "${CYAN}6. 사용자를 docker 그룹에 추가${NC}" echo -e "${CYAN}7. Docker 설치 확인${NC}" echo -e "\n${GREEN}작업을 시작합니다...${NC}\n" # IMDSv2 토큰 받기 - 스크립트 초반에 한 번만 생성 TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") # 1단계: 시스템 패키지 업데이트 echo -e "\n${GREEN}[1/7] 시스템 패키지 업데이트 중...${NC}" sudo dnf update -y echo -e "${GREEN}✓ 시스템 패키지 업데이트 완료${NC}" # 2단계: AWS CLI 설치 echo -e "\n${GREEN}[2/7] AWS CLI 설치 중...${NC}" sudo dnf install -y aws-cli echo -e "${GREEN}✓ AWS CLI 설치 완료${NC}" # 3단계: 호스트명 설정 echo -e "\n${GREEN}[3/7] 호스트명 설정 중...${NC}" # 인스턴스 ID 가져오기 INSTANCE_ID=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/instance-id) # 인스턴스의 리전 가져오기 REGION=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/placement/region) # 인스턴스의 Name 태그 가져오기 INSTANCE_NAME=$(aws ec2 describe-tags --region $REGION --filters "Name=resource-id,Values=$INSTANCE_ID" "Name=key,Values=Name" --query "Tags[0].Value" --output text) # 만약 Name 태그가 없다면 인스턴스 ID를 hostname으로 사용 if [ -z "$INSTANCE_NAME" ] || [ "$INSTANCE_NAME" == "None" ]; then INSTANCE_NAME=$INSTANCE_ID fi # hostname 설정 sudo hostnamectl set-hostname $INSTANCE_NAME # hostname을 /etc/hosts 파일에 추가 echo "127.0.0.1 $INSTANCE_NAME" | sudo tee -a /etc/hosts echo -e "${GREEN}✓ 호스트명이 '$INSTANCE_NAME'으로 설정되었습니다${NC}" # 4단계: Docker 패키지 설치 echo -e "\n${GREEN}[4/7] Docker 패키지 설치 중...${NC}" sudo dnf install -y docker echo -e "${GREEN}✓ Docker 패키지 설치 완료${NC}" # 5단계: Docker 서비스 시작 및 부팅 시 자동 시작 설정 echo -e "\n${GREEN}[5/7] Docker 서비스 시작 및 자동 시작 설정 중...${NC}" sudo systemctl start docker sudo systemctl enable docker echo -e "${GREEN}✓ Docker 서비스 시작 및 자동 시작 설정 완료${NC}" # 6단계: 사용자를 docker 그룹에 추가 echo -e "\n${GREEN}[6/7] 사용자를 docker 그룹에 추가 중...${NC}" sudo usermod -aG docker $USER # 현재 세션에 docker 그룹 권한 적용 if ! groups $USER | grep -q docker; then echo "docker 그룹 권한을 현재 세션에 적용합니다..." exec sg docker -c "bash -c 'cd $(pwd) && $0'" exit 0 fi echo -e "${GREEN}✓ 사용자를 docker 그룹에 추가 완료 (현재 세션에 적용됨)${NC}" # 7단계: Docker 설치 확인 echo -e "\n${GREEN}[7/7] Docker 설치 확인 중...${NC}" docker --version docker info | grep "Swarm:" | awk '{print $2}' echo -e "${GREEN}✓ Docker 설치 확인 완료${NC}" echo -e "\n${GREEN}============================================================${NC}" echo -e "${BLUE}Docker 기본 설치가 성공적으로 완료되었습니다!${NC}" echo -e "${BLUE}Manager 노드는 이제 'setup-swarm-manager.sh' 스크립트를 실행하세요.${NC}" echo -e "${BLUE}Worker 노드는 Manager에서 생성된 조인 토큰으로 Swarm에 참여하세요.${NC}" echo -e "${GREEN}============================================================${NC}"
chmod +x setup-docker-swarm-node.sh
./setup-docker-swarm-node.sh



3.3. Swarm Manager 초기화 스크립트 (setup-swarm-manager.sh)
이 스크립트는 Manager 노드에서 Docker Swarm을 초기화하고 Worker 및 Manager 조인 토큰을 생성합니다.
vi setup-swarm-manager.sh
#!/bin/bash # Docker Swarm Manager 초기화 스크립트 (Manager 노드용) # 터미널 설정에 따라 색상 사용 여부 결정 if [ -t 1 ]; then # 색상 정의 GREEN='\033[0;32m' BLUE='\033[0;34m' YELLOW='\033[0;33m' CYAN='\033[0;36m' RED='\033[0;31m' NC='\033[0m' # No Color else # 색상 없음 GREEN='' BLUE='' YELLOW='' CYAN='' RED='' NC='' fi echo -e "${GREEN}============================================================${NC}" echo -e "${BLUE}Docker Swarm Manager 초기화 스크립트${NC}" echo -e "${GREEN}============================================================${NC}" # 목차 출력 echo -e "\n${CYAN}[스크립트 수행 작업 목차]${NC}" echo -e "${CYAN}1. Docker Swarm 상태 확인${NC}" echo -e "${CYAN}2. Docker Swarm 초기화${NC}" echo -e "${CYAN}3. Worker 노드 조인 토큰 생성 및 저장${NC}" echo -e "${CYAN}4. Manager 노드 조인 토큰 생성 및 저장${NC}" echo -e "\n${GREEN}작업을 시작합니다...${NC}\n" # 1단계: Docker Swarm 상태 확인 echo -e "\n${GREEN}[1/4] Docker Swarm 상태 확인 중...${NC}" SWARM_STATUS=$(docker info | grep "Swarm:" | awk '{print $2}') echo -e "현재 Swarm 상태: ${YELLOW}$SWARM_STATUS${NC}" if [ "$SWARM_STATUS" == "active" ]; then echo -e "${RED}이 노드는 이미 Swarm 모드가 활성화되어 있습니다.${NC}" echo -e "${YELLOW}기존 Swarm 설정을 유지하려면 스크립트를 종료하세요.${NC}" read -p "기존 Swarm을 초기화하고 새로 설정하시겠습니까? (y/n): " RESET_SWARM if [[ "$RESET_SWARM" != "y" && "$RESET_SWARM" != "Y" ]]; then echo -e "${GREEN}스크립트를 종료합니다. 기존 Swarm 설정이 유지됩니다.${NC}" exit 0 else echo -e "${YELLOW}기존 Swarm을 초기화하고 새로 설정합니다...${NC}" docker swarm leave --force fi fi # 2단계: Docker Swarm 초기화 echo -e "\n${GREEN}[2/4] Docker Swarm 초기화 중...${NC}" # IMDSv2 토큰 받기 TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") # 프라이빗 IP 가져오기 PRIVATE_IP=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/local-ipv4) # IP가 제대로 가져와졌는지 확인 if [ -z "$PRIVATE_IP" ]; then echo -e "${YELLOW}프라이빗 IP를 가져오는데 실패했습니다. 다른 방법으로 시도합니다...${NC}" PRIVATE_IP=$(hostname -I | awk '{print $1}') fi echo -e "Swarm 초기화에 사용할 IP 주소: ${YELLOW}$PRIVATE_IP${NC}" # Swarm 초기화 docker swarm init --advertise-addr $PRIVATE_IP # Swarm 초기화 성공 여부 확인 if [ $? -ne 0 ]; then echo -e "${RED}Swarm 초기화에 실패했습니다. 오류를 확인하세요.${NC}" exit 1 fi echo -e "${GREEN}✓ Docker Swarm이 성공적으로 초기화되었습니다${NC}" # 현재 시간 가져오기 CURRENT_DATE=$(date +"%Y%m%d-%H%M") EXPIRE_DATE=$(date -d "+24 hours" +"%Y%m%d-%H%M") # 토큰 디렉토리 설정 TOKEN_DIR="./swarm-tokens" # 기존 토큰 디렉토리가 있는지 확인하고 처리 if [ -d "$TOKEN_DIR" ]; then echo -e "${YELLOW}기존 토큰 디렉토리가 존재합니다: $TOKEN_DIR${NC}" echo -e "${YELLOW}이 디렉토리에는 이전 토큰 정보가 포함되어 있을 수 있습니다.${NC}" read -p "기존 디렉토리를 삭제하고 새로 생성하시겠습니까? (y/n): " DELETE_DIR if [[ "$DELETE_DIR" == "y" || "$DELETE_DIR" == "Y" ]]; then echo -e "${YELLOW}기존 토큰 디렉토리를 삭제합니다...${NC}" rm -rf $TOKEN_DIR echo -e "${GREEN}✓ 기존 토큰 디렉토리가 삭제되었습니다${NC}" else echo -e "${YELLOW}기존 토큰 디렉토리를 유지합니다. 새 토큰 파일이 추가됩니다.${NC}" fi fi # 토큰 디렉토리 생성 (존재하지 않는 경우에만 생성됨) mkdir -p $TOKEN_DIR echo -e "토큰 저장 디렉토리: ${YELLOW}$TOKEN_DIR${NC}" # 3단계: Worker 노드 조인 토큰 생성 및 저장 echo -e "\n${GREEN}[3/4] Worker 노드 조인 토큰 생성 및 저장 중...${NC}" WORKER_TOKEN=$(docker swarm join-token worker -q) WORKER_JOIN_CMD=$(docker swarm join-token worker | grep "docker swarm join") # 토큰과 조인 명령어를 파일로 저장 WORKER_TOKEN_FILE="$TOKEN_DIR/worker-token-$CURRENT_DATE-to-$EXPIRE_DATE.txt" echo "===== Docker Swarm Worker 노드 조인 정보 =====" > $WORKER_TOKEN_FILE echo "생성 일시: $(date)" >> $WORKER_TOKEN_FILE echo "만료 예정: $(date -d "+24 hours")" >> $WORKER_TOKEN_FILE echo "Worker 토큰: $WORKER_TOKEN" >> $WORKER_TOKEN_FILE echo "" >> $WORKER_TOKEN_FILE echo "조인 명령어:" >> $WORKER_TOKEN_FILE echo "$WORKER_JOIN_CMD" >> $WORKER_TOKEN_FILE echo -e "${GREEN}✓ Worker 노드 조인 토큰이 생성되어 $WORKER_TOKEN_FILE 에 저장되었습니다${NC}" ls -la $WORKER_TOKEN_FILE # 4단계: Manager 노드 조인 토큰 생성 및 저장 echo -e "\n${GREEN}[4/4] Manager 노드 조인 토큰 생성 및 저장 중...${NC}" MANAGER_TOKEN=$(docker swarm join-token manager -q) MANAGER_JOIN_CMD=$(docker swarm join-token manager | grep "docker swarm join") # 토큰과 조인 명령어를 파일로 저장 MANAGER_TOKEN_FILE="$TOKEN_DIR/manager-token-$CURRENT_DATE-to-$EXPIRE_DATE.txt" echo "===== Docker Swarm Manager 노드 조인 정보 =====" > $MANAGER_TOKEN_FILE echo "생성 일시: $(date)" >> $MANAGER_TOKEN_FILE echo "만료 예정: $(date -d "+24 hours")" >> $MANAGER_TOKEN_FILE echo "Manager 토큰: $MANAGER_TOKEN" >> $MANAGER_TOKEN_FILE echo "" >> $MANAGER_TOKEN_FILE echo "조인 명령어:" >> $MANAGER_TOKEN_FILE echo "$MANAGER_JOIN_CMD" >> $MANAGER_TOKEN_FILE echo -e "${GREEN}✓ Manager 노드 조인 토큰이 생성되어 $MANAGER_TOKEN_FILE 에 저장되었습니다${NC}" ls -la $MANAGER_TOKEN_FILE # 요약 정보 출력 echo -e "\n${GREEN}============================================================${NC}" echo -e "${BLUE}Docker Swarm Manager 초기화가 성공적으로 완료되었습니다!${NC}" echo -e "${GREEN}============================================================${NC}" echo -e "${YELLOW}Worker 노드 조인 명령어:${NC}" echo -e "$WORKER_JOIN_CMD" echo -e "\n${YELLOW}Manager 노드 조인 명령어:${NC}" echo -e "$MANAGER_JOIN_CMD" echo -e "\n${BLUE}토큰 정보는 다음 위치에 저장되었습니다:${NC}" echo -e "Worker 토큰: ${CYAN}$WORKER_TOKEN_FILE${NC}" echo -e "Manager 토큰: ${CYAN}$MANAGER_TOKEN_FILE${NC}" echo -e "${BLUE}토큰은 24시간 동안 유효합니다.${NC}" echo -e "${GREEN}============================================================${NC}"
chmod +x setup-swarm-manager.sh
./setup-swarm-manager.sh
3.4. Worker 노드 조인 스크립트 (setup-swarm-worker.sh)
이 스크립트는 Worker 노드에서 Docker Swarm 클러스터에 조인하기 위해 사용합니다.
vi setup-swarm-worker.sh
#!/bin/bash # Docker Swarm Worker 노드 조인 스크립트 # 터미널 설정에 따라 색상 사용 여부 결정 if [ -t 1 ]; then # 색상 정의 GREEN='\033[0;32m' BLUE='\033[0;34m' YELLOW='\033[0;33m' CYAN='\033[0;36m' RED='\033[0;31m' NC='\033[0m' # No Color else # 색상 없음 GREEN='' BLUE='' YELLOW='' CYAN='' RED='' NC='' fi echo -e "${GREEN}============================================================${NC}" echo -e "${BLUE}Docker Swarm Worker 노드 조인 스크립트${NC}" echo -e "${GREEN}============================================================${NC}" # 목차 출력 echo -e "\n${CYAN}[스크립트 수행 작업 목차]${NC}" echo -e "${CYAN}1. Docker Swarm 상태 확인${NC}" echo -e "${CYAN}2. Docker Swarm 클러스터 조인${NC}" echo -e "\n${GREEN}작업을 시작합니다...${NC}\n" # 1단계: Docker Swarm 상태 확인 echo -e "\n${GREEN}[1/2] Docker Swarm 상태 확인 중...${NC}" SWARM_STATUS=$(docker info | grep "Swarm:" | awk '{print $2}') echo -e "현재 Swarm 상태: ${YELLOW}$SWARM_STATUS${NC}" if [ "$SWARM_STATUS" == "active" ]; then echo -e "${RED}이 노드는 이미 Swarm 모드가 활성화되어 있습니다.${NC}" # 노드 역할 확인 IS_MANAGER=$(docker info | grep "Is Manager:" | awk '{print $3}') if [ "$IS_MANAGER" == "true" ]; then echo -e "${YELLOW}이 노드는 현재 Manager 역할로 구성되어 있습니다.${NC}" echo -e "${YELLOW}Manager 노드를 떠나려면 --force 옵션이 필요합니다.${NC}" fi echo -e "${YELLOW}기존 Swarm 설정을 유지하려면 스크립트를 종료하세요.${NC}" read -p "기존 Swarm에서 나가고 새로 조인하시겠습니까? (y/n): " RESET_SWARM if [[ "$RESET_SWARM" != "y" && "$RESET_SWARM" != "Y" ]]; then echo -e "${GREEN}스크립트를 종료합니다. 기존 Swarm 설정이 유지됩니다.${NC}" exit 0 else echo -e "${YELLOW}기존 Swarm에서 나가고 새로 조인합니다...${NC}" # 노드 역할에 따라 적절한 leave 명령 실행 if [ "$IS_MANAGER" == "true" ]; then echo -e "${YELLOW}Manager 노드를 강제로 제거합니다...${NC}" docker swarm leave --force else echo -e "${YELLOW}Worker 노드를 제거합니다...${NC}" docker swarm leave fi # leave 명령 성공 여부 확인 if [ $? -ne 0 ]; then echo -e "${RED}Swarm 떠나기에 실패했습니다. 수동으로 'docker swarm leave --force' 명령을 실행한 후 다시 시도하세요.${NC}" exit 1 fi # Swarm 상태 재확인 SWARM_STATUS=$(docker info | grep "Swarm:" | awk '{print $2}') if [ "$SWARM_STATUS" == "active" ]; then echo -e "${RED}Swarm을 떠나는 데 실패했습니다. 수동으로 확인이 필요합니다.${NC}" exit 1 else echo -e "${GREEN}✓ Swarm을 성공적으로 떠났습니다.${NC}" fi fi fi # 2단계: Docker Swarm 클러스터 조인 echo -e "\n${GREEN}[2/2] Docker Swarm 클러스터 조인 중...${NC}" # 조인 토큰 입력 받기 read -p "Manager에서 제공한 전체 조인 명령어를 입력하세요: " JOIN_CMD # 조인 명령어 확인 if [[ $JOIN_CMD != *"docker swarm join"* ]]; then echo -e "${RED}유효한 조인 명령어가 아닙니다. 'docker swarm join'으로 시작하는 명령어를 입력하세요.${NC}" exit 1 fi # 명령어 실행 echo -e "${YELLOW}다음 명령어를 실행합니다: $JOIN_CMD${NC}" eval $JOIN_CMD # 조인 성공 여부 확인 if [ $? -ne 0 ]; then echo -e "${RED}Swarm 클러스터 조인에 실패했습니다. 오류를 확인하세요.${NC}" exit 1 fi # Swarm 상태 재확인 NEW_SWARM_STATUS=$(docker info | grep "Swarm:" | awk '{print $2}') NODE_ROLE=$(docker info | grep "Is Manager:" | awk '{print $3}') echo -e "${GREEN}✓ Docker Swarm 클러스터 조인이 성공적으로 완료되었습니다${NC}" echo -e "현재 Swarm 상태: ${YELLOW}$NEW_SWARM_STATUS${NC}" if [ "$NODE_ROLE" == "true" ]; then echo -e "노드 역할: ${YELLOW}Manager${NC}" else echo -e "노드 역할: ${YELLOW}Worker${NC}" fi echo -e "\n${GREEN}============================================================${NC}" echo -e "${BLUE}Docker Swarm Worker 노드 설정이 성공적으로 완료되었습니다!${NC}" echo -e "${GREEN}============================================================${NC}"
chmod +x setup-swarm-worker.sh
./setup-swarm-worker.sh
3.5. Swarm 초기화 취소 스크립트 (reset-swarm.sh)
이 스크립트는 Docker Swarm 모드를 비활성화하기 위해 사용합니다.
vi reset-swarm.sh
#!/bin/bash # Docker Swarm 모드 초기화 취소 스크립트 # 터미널 설정에 따라 색상 사용 여부 결정 if [ -t 1 ]; then # 색상 정의 GREEN='\033[0;32m' BLUE='\033[0;34m' YELLOW='\033[0;33m' CYAN='\033[0;36m' RED='\033[0;31m' NC='\033[0m' # No Color else # 색상 없음 GREEN='' BLUE='' YELLOW='' CYAN='' RED='' NC='' fi echo -e "${GREEN}============================================================${NC}" echo -e "${RED}Docker Swarm 모드 초기화 취소 스크립트${NC}" echo -e "${GREEN}============================================================${NC}" # 1단계: Docker Swarm 상태 확인 echo -e "\n${GREEN}[1/3] Docker Swarm 상태 확인 중...${NC}" SWARM_STATUS=$(docker info | grep "Swarm:" | awk '{print $2}') echo -e "현재 Swarm 상태: ${YELLOW}$SWARM_STATUS${NC}" if [ "$SWARM_STATUS" != "active" ]; then echo -e "${YELLOW}Swarm 모드가 이미 비활성화되어 있습니다. 추가 작업이 필요하지 않습니다.${NC}" exit 0 fi # 2단계: 노드 역할 확인 echo -e "\n${GREEN}[2/3] 노드 역할 확인 중...${NC}" IS_MANAGER=$(docker info | grep "Is Manager:" | awk '{print $3}') if [ "$IS_MANAGER" == "true" ]; then echo -e "현재 노드 역할: ${YELLOW}Manager${NC}" # 매니저 노드 수 확인 MANAGER_COUNT=$(docker node ls --filter "role=manager" | grep -c "Ready") if [ "$MANAGER_COUNT" -eq 1 ]; then echo -e "${RED}경고: 이 노드는 클러스터의 유일한 Manager입니다!${NC}" echo -e "${RED}이 노드를 제거하면 전체 클러스터가 파괴되며 복구가 불가능합니다.${NC}" else echo -e "${YELLOW}주의: Manager 노드를 제거하면 클러스터 관리가 일부 제한될 수 있습니다.${NC}" echo -e "${YELLOW} 현재 클러스터에는 총 $MANAGER_COUNT 개의 Manager가 있습니다.${NC}" fi else echo -e "현재 노드 역할: ${YELLOW}Worker${NC}" fi # 확인 요청 read -p "정말로 이 노드를 Swarm에서 제거하고 Swarm 모드를 비활성화하시겠습니까? (y/n): " CONFIRM if [[ "$CONFIRM" != "y" && "$CONFIRM" != "Y" ]]; then echo -e "${GREEN}스크립트를 종료합니다. Swarm 설정이 유지됩니다.${NC}" exit 0 fi # 3단계: Swarm 모드 비활성화 echo -e "\n${GREEN}[3/3] Swarm 모드 비활성화 중...${NC}" if [ "$IS_MANAGER" == "true" ]; then echo -e "${YELLOW}Manager 노드를 강제로 제거합니다...${NC}" docker swarm leave --force else echo -e "${YELLOW}Worker 노드를 제거합니다...${NC}" docker swarm leave fi # 결과 확인 if [ $? -ne 0 ]; then echo -e "${RED}Swarm 모드 비활성화에 실패했습니다. 오류를 확인하세요.${NC}" echo -e "${YELLOW}수동으로 'docker swarm leave --force' 명령을 실행해보세요.${NC}" exit 1 fi # Swarm 상태 재확인 NEW_SWARM_STATUS=$(docker info | grep "Swarm:" | awk '{print $2}') if [ "$NEW_SWARM_STATUS" == "active" ]; then echo -e "${RED}Swarm 모드 비활성화에 실패했습니다.${NC}" echo -e "${YELLOW}Docker 데몬을 다시 시작해보세요: 'sudo systemctl restart docker'${NC}" exit 1 fi echo -e "현재 Swarm 상태: ${YELLOW}$NEW_SWARM_STATUS${NC}" echo -e "${GREEN}✓ Swarm 모드가 성공적으로 비활성화되었습니다${NC}" echo -e "\n${GREEN}============================================================${NC}" echo -e "${BLUE}Docker Swarm 모드가 성공적으로 비활성화되었습니다!${NC}" echo -e "${GREEN}============================================================${NC}"
chmod +x reset-swarm.sh
./reset-swarm.sh
4. 기본 Docker Swarm 명령어
4.1. Swarm 초기화 및 관리
Swarm 상태 확인:
docker info | grep Swarm

Swarm 모드 초기화하기 (Manager 노드에서):
docker swarm init --advertise-addr <Manager IP>
Worker 노드 조인 토큰 생성:
docker swarm join-token worker
Manager 노드 조인 토큰 생성:
docker swarm join-token manager
Swarm 떠나기 (Worker 노드에서):
docker swarm leave
Swarm 떠나기 (Manager 노드에서):
docker swarm leave --force
4.2. 노드 관리
노드 목록 보기:
docker node ls

쉘 변수로 워커 노드 ID 저장하기
WORKER_NODE_ID=gscjt15xvt545yfs07ysoimb5
특정 노드 상세 정보 보기:
docker node inspect $WORKER_NODE_ID

노드 역할 변경 (Worker -> Manager):
docker node promote $WORKER_NODE_ID

노드 역할 변경 (Manager -> Worker):
docker node demote $WORKER_NODE_ID

노드 가용성 변경 (drain: 컨테이너 배포 불가):
docker node update --availability drain $WORKER_NODE_ID

노드 가용성 변경 (active: 컨테이너 배포 가능):
docker node update --availability active $WORKER_NODE_ID

노드에 라벨 추가:
docker node update --label-add environment=production $WORKER_NODE_ID
노드 라벨 조회:
# 노드의 모든 정보 확인(라벨 포함) docker node inspect $WORKER_NODE_ID # 라벨만 추출하여 조회 docker node inspect $WORKER_NODE_ID --format '{{ .Spec.Labels }}' # grep으로 라벨 부분만 추출 docker node inspect $WORKER_NODE_ID | grep Labels -A5

4.3. 서비스 배포 및 관리
기본 서비스 명령어
서비스 생성하기:
docker service create --name <서비스명> --replicas <복제본수> <이미지명>
서비스 목록 보기:
docker service ls
서비스 상세 정보 보기:
docker service inspect <서비스명>
서비스의 태스크(컨테이너) 목록 보기:
docker service ps <서비스명>
서비스 확장하기 (복제본 수 조절):
docker service scale <서비스명>=<복제본수>
서비스 업데이트 (이미지 변경):
docker service update --image <새 이미지> <서비스명>
서비스 삭제하기:
docker service rm <서비스명>
실제 Nginx 웹 서비스 배포 및 테스트
Nginx 웹 서버 서비스 배포:
# 포트 80을 외부에 노출하는 Nginx 서비스 생성 (3개 복제본) docker service create --name webserver \ --replicas 3 \ --publish published=80,target=80 \ nginx:latest
서비스 상태 확인:
# 서비스 목록 확인 docker service ls # 서비스 상세 정보 확인 docker service inspect webserver # 서비스 태스크(컨테이너) 상태 확인 docker service ps webserver
서비스 접속 테스트 (Manager 노드에서):
# curl로 웹 서버 접속 테스트 curl http://localhost:80 # 또는 간단히 curl localhost # 응답 헤더 확인 curl -I localhost # 접속 반복 테스트 (부하 분산 확인) for i in {1..10}; do curl -s localhost | grep -o "<title>.*</title>"; sleep 1; done
서비스 스케일링:
# 서비스 복제본 수 조정 (5개로 증가) docker service scale webserver=5 # 스케일링 결과 확인 docker service ps webserver
서비스 업데이트:
# 서비스 이미지 변경 (httpd로 변경) docker service update --image httpd:latest webserver # 업데이트 상태 확인 docker service ps webserver
시각화 도구 배포 (선택사항):
# Docker Swarm 시각화 도구 배포 docker service create \ --name=visualizer \ --publish=8080:8080 \ --constraint=node.role==manager \ --mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \ dockersamples/visualizer # 접속 테스트 curl localhost:8080 # 또는 웹 브라우저에서 http://<manager-ip>:8080 접속
4.4. 네트워크 관리
네트워크 변수 설정
# 네트워크 이름 변수 저장 OVERLAY_NETWORK=my-overlay-net
오버레이 네트워크 생성:
# 기본 오버레이 네트워크 생성 docker network create --driver overlay $OVERLAY_NETWORK
암호화된 오버레이 네트워크 생성:
# 암호화된 오버레이 네트워크 생성 docker network create --driver overlay --opt encrypted ${OVERLAY_NETWORK}-secure
네트워크 목록 보기:
docker network ls | grep overlay
특정 네트워크 상세 정보 보기:
docker network inspect $OVERLAY_NETWORK
서비스를 특정 네트워크에 연결:
# 생성된 오버레이 네트워크를 사용하는 웹 서비스 배포 docker service create --name webapp \ --network $OVERLAY_NETWORK \ --replicas 3 \ nginx:latest
멀티 네트워크 서비스 예제
# 프론트엔드 네트워크 생성 docker network create --driver overlay frontend # 백엔드 네트워크 생성 docker network create --driver overlay backend # 프론트엔드와 백엔드 네트워크에 모두 연결된 API 서비스 생성 docker service create --name api-gateway \ --network frontend \ --network backend \ --replicas 3 \ nginx:latest # 네트워크 연결 확인 docker service inspect api-gateway --format '{{.Spec.TaskTemplate.Networks}}'
5. 고급 Docker Swarm 기능
5.1. 스택 배포 (Compose 파일 사용)
샘플 compose 파일 생성:
# 샘플 docker-compose.yml 파일 생성 cat > docker-compose.yml << 'EOL' version: '3.8' services: web: image: nginx:latest ports: - "80:80" deploy: replicas: 2 visualizer: image: dockersamples/visualizer ports: - "8080:8080" deploy: placement: constraints: [node.role == manager] volumes: - /var/run/docker.sock:/var/run/docker.sock EOL # 파일 확인 cat docker-compose.yml
스택 배포하기:
# my-stack이라는 이름으로 스택 배포 docker stack deploy -c docker-compose.yml my-stack
스택 목록 보기:
docker stack ls
스택의 서비스 목록 보기:
docker stack services my-stack
스택의 태스크 목록 보기:
docker stack ps my-stack
접속 테스트:
# 웹 서비스 접속 테스트 curl localhost # 시각화 도구 접속 테스트 curl localhost:8080
스택 삭제하기:
docker stack rm my-stack
5.2. 비밀 데이터(Secret) 관리
비밀 데이터 파일 생성 및 저장:
# 비밀 데이터 파일 생성 echo "MySecretPassword123!" > db_password.txt # 비밀 데이터 생성 docker secret create db_password db_password.txt # 생성 후 로컬 파일 제거 (보안) rm db_password.txt
비밀 데이터 목록 보기:
docker secret ls
비밀 데이터 상세 정보 보기:
docker secret inspect db_password
서비스 생성 시 비밀 데이터 사용:
# 비밀 데이터를 환경 변수로 노출 docker service create \ --name mysql-db \ --secret source=db_password,target=mysql_root_password \ --env MYSQL_ROOT_PASSWORD_FILE=/run/secrets/mysql_root_password \ mysql:8.0 # 서비스 상태 확인 docker service ps mysql-db
5.3. 설정 데이터(Config) 관리
설정 데이터 파일 생성:
# Nginx 설정 파일 생성 cat > nginx.conf << 'EOL' server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; add_header Content-Type text/plain; return 200 'Hello from Docker Swarm! Config works!\n'; } } EOL # 설정 파일 확인 cat nginx.conf
설정 데이터 생성:
docker config create nginx_config nginx.conf
설정 데이터 목록 보기:
docker config ls
설정 데이터 상세 정보 보기:
docker config inspect nginx_config
서비스 생성 시 설정 데이터 사용:
# 설정 파일을 사용하는 Nginx 서비스 생성 docker service create \ --name web-with-config \ --config source=nginx_config,target=/etc/nginx/conf.d/default.conf \ --publish 8000:80 \ nginx:latest # 서비스 상태 확인 docker service ps web-with-config # 접속 테스트 curl localhost:8000
5.4. 업데이트 및 롤백 전략
롤백 기능이 있는 서비스 생성:
# 롤백 및 업데이트 전략이 정의된 서비스 생성 docker service create \ --name webapp-rollback \ --replicas 4 \ --publish 8001:80 \ --update-parallelism 2 \ --update-delay 10s \ --update-failure-action rollback \ --rollback-parallelism 2 \ --rollback-delay 5s \ nginx:1.20 # 서비스 상태 확인 docker service ps webapp-rollback
업데이트 병렬처리와 지연시간 설정:
# 서비스 업데이트 (성공 케이스) docker service update \ --image nginx:1.21 \ --update-parallelism 2 \ --update-delay 10s \ webapp-rollback # 업데이트 진행 관찰 watch docker service ps webapp-rollback
실패 시 자동 롤백 테스트:
# 존재하지 않는 이미지로 업데이트 (실패 케이스) docker service update \ --image nginx:invalid-tag \ webapp-rollback # 롤백 진행 관찰 watch docker service ps webapp-rollback
수동 롤백 실행:
# 수동으로 롤백 실행 docker service update --rollback webapp-rollback # 롤백 결과 확인 docker service ps webapp-rollback