Docker, MySQL, Jenkins를 활용한 CI/CD 파이프라인 AWS 설정

조승빈·2024년 5월 23일

CI / CD

목록 보기
3/8

사전 준비 사항

  • Ubuntu를 실행하는 AWS EC2 인스턴스
  • Docker와 Jenkins에 대한 기본 지식
  • Spring Boot 애플리케이션용 Git 저장소

스왑 파일 생성

서버 성능을 향상시키기 위해 스왑 파일을 생성한다.

sudo dd if=/dev/zero of=/swapfile bs=128M count=16
sudo mkswap /swapfile
sudo swapon /swapfile
sudo swapon -s

Docker 설치

패키지 목록을 업데이트하고 Docker를 설치한다.

sudo apt-get update
sudo apt-get install docker.io -y
sudo systemctl start docker

Docker에서 MySQL 실행

최신 MySQL 이미지를 가져오고 루트 비밀번호를 설정하여 컨테이너를 실행한다.

sudo docker pull mysql
sudo docker run --name mysql-server -e MYSQL_ROOT_PASSWORD=[password] -p 3306:3306 -d mysql:latest

Docker에서 Jenkins 실행

Jenkins 컨테이너를 가져오고 실행하여 Docker와 상호작용할 수 있도록 설정한다.

sudo docker run -d --name jenkins -p 8080:8080 -v /jenkins:/var/jenkins_home -v /usr/bin/docker:/usr/bin/docker -v /var/run/docker.sock:/var/run/docker.sock -u root jenkins/jenkins:lts

Docker 컨테이너 접속

실행 중인 Docker 컨테이너와 상호작용하려면 다음 명령어를 사용한다.

sudo docker exec -it [container id] bash

Jenkins 설정

  1. Jenkins 접속:
  • 브라우저에서 http://<your-aws-ip>:8080으로 접속
  • sudo docker logs jenkins 를 ec2에 입력하면 비밀번호가 있다.
  1. Gradle 및 Node.js 버전 설정: 필요한 플러그인을 설치하고 환경 변수를 설정한다.
  • node.js 플러그인을 설치하고 적용한다.
  1. Git 연결 확인: Jenkins에서 Git 저장소에 접근할 수 있도록 설정한다.

  2. 파이프라인 생성: spring boot와 node.js의 파이프라인을 하나씩 생성하고 빌드한다.

  • web hook을 위해 GitHub hook trigger for GITScm polling 체크
  • script 입력
pipeline {
    agent any

    environment {
        GIT_URL = "your git url"
    }

    tools {
        nodejs "MyNodeJS" // Ensure you have a Node.js installation named 'MyNodeJS' configured in Jenkins
    }

    stages {
        stage('Checkout Code') {
            steps {
                git url: "${GIT_URL}", branch: "main"
            }
        }
        stage('Prepare secret file') {
            steps {
                script {
                    writeFile file: '.env', text: '''

                    '''
                }
            }
        }

        stage('Install Dependencies') {
            steps {
                script {
                    sh 'npm install'
                }
            }
        }

        stage('Run Tests') {
            steps {
                script {
                    try {
                        sh 'npm test || echo "No tests specified"'
                    } catch (Exception e) {
                        currentBuild.result = 'UNSTABLE'
                        echo "Tests failed but continue: ${e}"
                    }
                }
            }
        }

        stage('Build Docker Image') {
            steps {
                script {
                    sh 'docker build -t nodejs-app .'
                    sh 'docker tag nodejs-app:latest nodejs-app:latest'
                }
            }
        }

        stage('Deploy') {
            steps {
                script {
                    // Stop and remove any existing container with the name "nodejs-app"
                    def containerExists = sh(script: "docker ps -aq -f name=nodejs-app", returnStdout: true).trim()
                    if (containerExists) {
                        sh "docker stop nodejs-app"
                        sh "docker rm nodejs-app"
                    }

                    def containerRun = sh(script: 'docker run -d --name nodejs-app -p 8181:8181 nodejs-app', returnStatus: true)
                    if (containerRun != 0) {
                        error("Failed to start the nodejs-app container.")
                    }
                }
            }
        }

        stage('Verify Deployment') {
            steps {
                script {
                    def containerRunning = sh(script: "docker ps -q -f name=nodejs-app", returnStdout: true).trim()
                    if (!containerRunning) {
                        error("nodejs-app container is not running.")
                    } else {
                        echo "nodejs-app container is running successfully."
                    }
                }
            }
        }

        stage('Cleanup') {
            steps {
                sh 'docker images -qf dangling=true | xargs -r docker rmi'
            }
        }
    }
}

Git 저장소 Webhook 설정

Git 저장소에 Webhook을 설정하여 코드 변경 시 Jenkins가 자동으로 빌드를 트리거하도록 합니다.

dockerfile

# Use the official Node.js image from the Docker Hub
FROM node:16

# Create and change to the app directory
WORKDIR /usr/src/app

# Copy application dependency manifests to the container image.
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy the local code to the container image.
COPY . .

# Expose the port the app runs on
EXPOSE 8181

# Run the web service on container startup.
CMD ["node", "app.js"]

주의사항

AWS 설정

  • 인바운드 규칙 확인: 필요한 포트(예: 8080, 3306)가 열려 있는지 확인합니다.
  • 탄력적 IP 주소 사용: 고정 IP 주소를 사용하여 인스턴스에 접근합니다.

MySQL 설정

  • MySQL URL 설정: MySQL을 연결할 때 URL을 MySQL 컨테이너의 IP 주소로 설정합니다.
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <컨테이너 이름 또는 ID>

이유도 모르고 안될 때도 있다... AWS 설정 정보를 외부에 별도로 기록해 두자. 기록하는 습관을 가지자...

profile
평범

0개의 댓글