실습(Docker & Jenkins)

유요한·2023년 11월 8일
0
post-thumbnail

EC2를 만드는 것은 이미 경험해봤으니 정리하지 않고 넘어가겠습니다. 다만 차이점은 있습니다. 여기서는 리눅스입니다. 완벽하지는 않지만 이론 공부하고 조사한 것을 토대로 시작이 반이라고 했으니 간단하게나마 도커와 리눅스, 젠킨스를 이용해서 배포하고자 합니다.

아쉬운점은 AWS 프리티어를 너무 일찍 만들어서 프리티어 기간이 만료가 되어서 깊게 진행하지 못해서 부족한 부분이 남았다는 것입니다. 이 부분은 취업 후 더 깊이 공부할 생각입니다.

PuTTy로 리눅스를 연결하면 다음과 같은 화면이 나옵니다.

EC2 세팅

root 계정으로 변경

수월하게 작업하기 위해 슈퍼유저를 사용한다.

sudo su

ubuntu 계정에서 root 계정으로 변경

타임존

  1. 시간이 한국시간으로 되어있는지 확인한다.
timedatectl
  1. 세팅
sudo timedatectl set-timezone Asia/Seoul
sudo echo Asia/Seoul > /etc/timezone
  1. 확인
timedatectl

다음과 같이 떠야합니다.

  1. 리파지토리 목록을 업데이트
sudo yum update

여기까지는 리눅스의 시간을 정했습니다.

환경변수

ls -al

여기서 .bashrc를 찾습니다.

nano .bashrc 를 입력하면 위와 같은 화면이 나오는데 제일 밑으로 이동합니다.

export MYSQL_SECRET=123456789

export를 붙여서 환경변수를 세팅할 수 있습니다.

변경 사항을 저장합니다. ( Ctrl+x ,누른 뒤 Y 를 누르고 Enter를 누른다) '.bashrc' 파일에서 설정한 환경 변수를 사용할 수 있도록 변경 사항을 적용하기 위해 다음 명령어를 입력합니다.

source .bashrc

마지막으로 환경변수가 제대로 저장됐는지 확인해보면 끝입니다!

echo $MYSQL_SECRET
123456789

EC2로 설치

자바다운

리스트 확인

sudo  yum list java* 

다운

sudo yum install java-11-amazon-corretto-devel.x86_64

환경 변수

openjdk를 설치하면 기본적으로 시스템에 등록돼 자바를 사용할 수 있지만 버전 충돌 등으로 문제가 발생할 수 있으니 환경변수를 설정해주는게 좋습니다.

환경변수가 설정되어 있지 않으면 자바가 설치된 경로를 확인하고 환경변수 파일에 등록해줘야합니다. 먼저 자바가 설치된 위치를 확인해야 한다. which java(or javac)

그리고 ls -l [which java(or javac)의 경로] 명령어로 확인해 보면

심볼릭 링크로 나온다. 원본 위치를 찾기 위해 readlink -f /usr/bin/java 를 실행하면

위처럼 java의 원본 위치를 알 수 있다.

java의 원본 위치를 복사하여 /etc/profile~/.bashrc 파일에서 맨 아래에 아래처럼 추가해주면 된다.

파일을 찾는 방법은 다음과 같습니다.

ls -al

nano .bashrc

여기로 들어가면 설정을 할 수 있는 곳이 나오는데 맨 아래로 내려서

export JAVA_HOME=/usr/lib/jvm/java-11-amazon-corretto.x86_64/bin/java
export PATH=$JAVA_HOME/bin:$PATH

설정을 적어주고 컨트롤+x누르고 y를 누르고 엔터를 누르면 나와진다.
그리고 .bashrc' 파일에서 설정한 환경 변수를 사용할 수 있도록 변경 사항을 적용하기 위해 다음 명령어를 입력합니다.

source .bashrc

환경변수가 적용되는 것을 볼 수 있습니다.

Git 설치

sudo yum update
sudo yum install git
git --version

젠킨스 다운

도커 이미지 없이 다운받는 방법

  1. Jenkins GPG Key 설치

    rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key

  2. Jenkins repo 등록
    dnf config-manager --add-repo https://pkg.jenkins.io/redhat-stable/jenkins.repo

  3. dnf install jenkins

  4. systemctl start jenkins

    참고 - 젠킨스 시작 및 중지 방법
    sudo systemctl stop jenkins.service
    sudo systemctl start jenkins.service
    sudo systemctl enable jenkins.service

EC2 Jenkins 인스턴스의 인바운드 규칙에 8080을 열어줍니다.

jenkins 인스턴스의 인바운드 규칙에 8080 포트를 여는 이유는 jenkins는 기본적으로 8080 포트를 사용합니다.

docker없이 젠킨스를 사용할 때 비번 확인
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
이 명령어로 비밀번호 확인이 가능하다.


프리티어 EC2 메모리 부족 해결하기

현재 젠킨스 서버로 사용하는 프리티어 EC2는 젠킨스를 버틸 수 없습니다. 젠킨스를 도커로 띄우고 설정까지는 문제가 없으나 깃허브 웹훅으로 젠킨스를 이용해 spring을 빌드하는 과정에서 램을 1기가 이상(프리티어 EC2 램은 1기가) 사용하게 되면서 EC2가 먹통이 되어버립니다. 이 문제의 해결 방안으로는 리눅스의 하드디스크를 가상 메모리로 전환시켜 사용할 수 있다는 점을 이용하면 됩니다.AWS에서는 메모리의 양에 따라 스왑 메모리의 크기를 아래와 같이 권장하고 있습니다.

  1. 스왑 파일 생성하기
    아래 명령은 시간이 약 10~20초 정도 걸리므로 여유있게 기다리면 됩니다.
sudo dd if=/dev/zero of=/swapfile bs=128M count=16

  1. 스왑 파일에 대한 일기 쓰기 권한 업데이트하기
sudo chmod 600 /swapfile
  1. Linux 스왑 영역 설정하기
sudo mkswap /swapfile

  1. 스왑 공간에 스왑 파일을 추가하여 스왑 파일을 즉시 사용할 수 있도록 하기
sudo swapon /swapfile
  1. 절차가 성공했는지 확인하기
sudo swapon -s

  1. /etc/fstab 파일을 편집하여 부팅 시 스왑 파일을 활성화하기
# 1.파일 열기
sudo nano /etc/fstab

# 2.파일 가장 마지막에 다음을 추가하고 :wq로 저장하고 종료
/swapfile swap swap defaults 0 0
  1. free 명령어로 메모리 확인하기
free

도커 사용

도커 다운

  1. 설치

    sudo yum install docker

  2. 시작

    sudo systemctl start docker

  3. 명령은 시스템 부팅 시에 Docker 서비스가 자동으로 시작되도록 설정하는 것입니다.

    sudo systemctl enable docker

  1. 설치확인

    sudo docker run hello-world

Docker 자바 이미지 다운

docker pull openjdk:11

git 설치

docker는 별도의 git 이미지를 제공하지 않아서 리눅스에 다운받았습니다.

sudo yum install git

도커로 젠킨스 이미지 다운

  1. 도커 허브에서 젠킨스 이미지 다운로드

    docker pull jenkins/jenkins:lts
    도커 허브 계정이 없어도 이미지가 다운로드 됩니다.
    jenkins:lts는 jdk8로 실행이 된다.
    자바 11을 주로 사용하므로 jdk11로 실행하는 이미지를 내려받자.
    docker pull jenkins/jenkins:jdk11

  1. 다운로드된 이미지 조회

    docker images

  1. 젠킨스 이미지를 컨테이너로 실행
docker run -d -p 8080:9090 -p 50000:50000 -v /home/jenkins:/var/jenkins_home -v /usr/bin/docker:/usr/bin/docker -v /var/run/docker.sock:/var/run/docker.sock -u root jenkins/jenkins:jdk11
  • -d : 컨테이너를 백그라운드에서 실행하는 옵션입니다.
  • -p : 호스트의 포트와 컨테이너의 포트를 연결하는 옵션입니다.

    사용법: p [호스트 포트번호]:[컨테이너 포트번호]
    호스트번호는 ec2 포트와 젠킨스 포트입니다. 컨테이너 포트번호는 도커의 포트번호입니다.

  • -v : 호스트의 디렉토리와 컨테이너 디렉토리를 볼륨으로 매핑합니다. 쉽게 말해서 서로 지정된 디렉토리를 공유한다는 뜻입니다.
  • -u : 컨테이너의 실행 사용자를 지정합니다.

run : 이미지를 기반으로 컨테이너를 실행시킵니다. 위에서는 jenkins/jenkins:lts 이미지를 실행

  • -p 8080:9090 : 호스트서버의 9090포트와 컨테이너의 8080포트를 연결
  • -p 50000:50000 : 젠킨스 마스터 노드는 빌드 에이전트와 통신할 때 JNLP(Java Network Launch Protocol)을 사용. 기본적으로 50000번 포트. JNLP통신은 TCP/IP기반으로 이뤄지는데, 컨테이너는 기본적으로 격리된 환경에서 실행되기때문에 젠킨스 마스터 노드와 빌드 에이전트가 통신하려면 같은 컨테이너에 있더라도 호스트 서버를 통해 통신하게 된다. 통신관계를 간단하게 표현하면 (빌드에이전트 ↔ 호스트서버 ↔ 마스터노드)
  • -v /home/jenkins:/var/jenkins_home : 젠킨스 컨테이너의 설정을 호스트 서버와 공유함으로써, 컨테이너가 삭제되는 경우에도 설정을 유지할수 있게 해줍니다. 호스트의 /home/jenkins 디렉토리와, 컨테이너의 /var/jenkins_home 디렉토리를 연결합니다 (연결한다는 의미는 호스트의 /home/jenkins에 test.txt파일을 추가하면 컨테이너의 /var/jenkins_home경로에도 test.txt파일이 추가된다는 의미입니다. 반대로도 동일)
  • -v /usr/bin/docker:/usr/bin/docker -v /var/run/docker.sock:/var/run/docker.sock
    젠킨스 컨테이너에서도 호스트 서버의 도커를 사용하기 위한 바인딩입니다.

이렇게 컨테이너 내부에서 호스트 서버의 도커를 사용하는 방식을 DooD(Docker out of Docker)라고합니다.

  • -u root : 호스트 서버의 디렉토리를 공유하기때문에 권한 문제가 있을수있어 root사용자로 실행

오류1

위와 같은 에러가 발생했는데 해당 볼륨의 위치가 Mount 권한이 없어 실행에 실패를 했다고 한다.

해결 방법은 Docker Client를 실행하여 Preferences -> Resources -> FILE SHARING 메뉴에서 마운트 할 경로를 추가해주면 된다고 한다.

오류2
rror response from daemon: driver failed programming external connectivity on endpoint ~ 에러가 나왔을때 해결하는 방법입니다.

외부로 오픈하는 포트가 겹쳐서 컨테이너가 실행되지 않는 오류였다. 이전에 다른 컨테이너를 실행하다가 종료하는 과정에서 제대로 종료되지 않아 아직 그 포트에서 실행되어 발생하였다.

도커가 가지고 있는 캐시 때문에 해당 포트를 사용중이라고 인식했던 것 같다. 아래의 명령어를 통해 도커의 캐시를 삭제하여 문제를 해결했고, Spring Boot 서버에서도 DB와 연결을 할 수 있었다.

컨테이너 실행 확인

docker ps

만약 docker ps 를 쳤는데 컨테이너 조회가 안된다면 docker ps -a 명령어를 실행해보면 정지되어있는 컨테이너도 조회가 됩니다. 거기서

docker logs [컨테이너ID]

를 실행해서 해당 컨테이너가 왜 실행이 안됐는지 조회할수있습니다.

이미 컨테이너가 실행되어있다고 한다면, 기존에 에러가 나면서 실행되었던 컨테이너는 제거해주자. docker rm [컨테이너 ID]
해당 명령어를 통해 컨테이너를 삭제해주자.

젠킨스 페이지 접속

docker exec -it <container_id_or_name> cat /var/jenkins_home/secrets/initialAdminPassword

<container_id_or_name>은 단계 1에서 확인한 Jenkins 컨테이너의 ID나 이름으로 대체되어야 합니다.

웹브라우저로 로그인 페이지 접속

비밀번호를 입력하여 젠킨스 접속. 이후 install suggested plugins를 눌러서 설치

젠킨스의 URL 설정
젠킨스에 접속할 수 있는 url을 설정할 수 있습니다. 기본적으로 따로 설정을 하지 않는것이 좋습니다.

User Defined Time Zone을 Asia/Seoul로 변경

젠킨스에 사용할 플러그인을 설치해야 합니다. 

젠킨스는 조금 더 편하게? 사용할 수 있도록 많은 플러그인을 제공해주고 있습니다. 여기서 우리는 Publish Over SSH를 다운 받아야합니다.

먼저 아래 사이트로 들어가서 설치할 플러그인의 파일을 찾아서 받습니다 (.hpi 파일)

http://updates.jenkins-ci.org/download/plugins/

다음으로 Jenkins 관리 > 플러그인 관리 > 고급 으로 들어간 후 사진처럼 위에서 받은 파일을 등록하고 올리기 버튼을 클릭하여 젠킨스 서버에 배포합니다.

파일을 등록하여 서버에 배포한 후 플러그인을 확인해보면 정상적으로 설치가 된 걸 확인할 수 있습니다.

지금까지 우리는 젠킨스를 설치하고 젠킨스 페이지에 접속하여 기초적으로 필요한 플러그인을 설치하는 과정을 진행하였습니다. 지금부터는 젠킨스 서버에 SSH 키를 생성하고 등록하는 방법을 알아보겠습니다.

Jenkins Server SSH Key 생성 및 등록

왜 SSH Key를 생성하고 어디에 사용을 할까?

  • Jenkins에서 GitHub에 접근하기 위해서는 SSH 키를 깃허브에 등록해야 합니다.
  • Docker에서 Jenkins를 적재할때는 볼륨(v) 옵션을 사용하여 마운트를 해둔 상태이므로 호스트 PC에서 SSH 키 생성을 대행할 수 있습니다.

디렉토리 생성 : sudo mkdir -p /home/jenkins/.ssh
권한 부여 : sudo chmod 700 /home/jenkins/.ssh
SSH 키를 생성하는 명령어 : sudo ssh-keygen -t rsa

ssh-keygen: SSH 키를 생성하는 명령어입니다. SSH 키는 안전한 원격 로그인 및 데이터 전송을 위해 사용됩니다.

-t rsa: 사용할 알고리즘을 지정하는 옵션으로, 이 경우 RSA 알고리즘을 선택합니다. RSA는 공개 키 및 개인 키를 사용하여 암호화와 서명을 위한 키 쌍을 생성하는 알고리즘 중 하나입니다. RSA 키 쌍은 데이터를 안전하게 전송하고 인증하는 데 사용됩니다.

nano /etc/sudoers
맨 아래 추가
jenkins ALL=(ALL) NOPASSWD: ALL

  • ALL=(ALL): jenkins 사용자에 대해 모든 호스트와 모든 사용자에게 sudo 권한을 부여합니다.

  • NOPASSWD: ALL: jenkins 사용자가 sudo 명령을 실행할 때 비밀번호를 묻지 않도록 합니다. 이 부분이 비밀번호 없이 진행하게 하는 것

Jenkins 서버의 id_rsa.pub의 키를 복사하여 개발 서버에 등록합니다.

/home/jenkins/.ssh위치를 보면

이렇게 2개가 생성된 것을 확인할 수 있습니다.

cat id_rsa.pub

으로 키를 가져와서

cd ~
cd .ssh/
nano authorized_keys

맨 밑에 키를 등록해줍니다.

젠킨스의 키 → 개발서버(authorized_keys)

깃허브에서 webhook 설정하기

여기서 포트는 ec2에서 접속하는 포트로 사용해야합니다. 예를들어 docker run -p 8081:8082면 8081로 포트를 설정해줘야 합니다.

webhook 사용이유

웹훅(Webhook)은 소프트웨어 개발 및 지속적인 통합/배포(CI/CD) 프로세스에서 사용되는 중요한 도구 중 하나입니다. 웹훅은 이벤트 기반의 통신 방식으로, 어떤 이벤트가 발생했을 때 다른 시스템에 알려주는 메커니즘입니다. Git 리포지토리와 Jenkins와 같은 CI/CD 도구 간에 웹훅을 설정하는 이유는 다음과 같습니다.

자동화된 빌드 및 배포:

  • 웹훅을 사용하면 코드가 변경될 때마다 Git 리포지토리에서 해당 이벤트를 Jenkins 서버로 알릴 수 있습니다.
  • Jenkins는 이 이벤트를 감지하고 자동으로 빌드 및 배포 작업을 시작할 수 있습니다.
  • 결과적으로, 개발자는 소스 코드를 업데이트할 때마다 수동으로 빌드 및 배포 작업을 실행할 필요가 없습니다.

Git Token 발급

Github Settings -> Developer settings -> Personal access token 항목에 들어갑니다

jeknins로 repository의 코드를 build, deploy등을 할 거여서 repo 권한 전체를 주었습니다.

생성된 키 ⇒ xxxxYYYYzzz
키는 다음에 다시 확인할 수 없으니 반드시 복사하여 어딘가 저장해두어야 합니다.

Git Token 발급 + Jenkins Credential 등록

Credential 추가를 해주면 됩니다

  • Kind : SSH Username with private key
  • Username : 본인의 깃 허브 아이디를 입력합니다.
  • Password : 이전에 발급받은 GutHub Token 값을 입력합니다.
  • ID : 원하는 값으로 설정하며, git이 jenkins에게 Credenial을 줄 때 인식할 수 있도록 합니다.
  • private Key : id_rsa 파일내용

보안상 SSH로 하는게 좋다.

지금부터는 젠킨스에 Git Hub Repository를 등록하고 젠킨스 서버와 어떻게 연동을 하는지 알아보겠습니다.

젠킨스 관리 > 시스템 설정을 클릭해줍니다.

Publish Over SSH 설정

  • 맨 아래쪽으로 이동하면 Publish Over SSH를 설정하는 공간이 있습니다. 여기에 Remote 서버에 대한 정보를 입력해야합니다.

  • Key는 젠킨스 서버에서 생성한 /home/jenkins/.ssh 경로에 있는 id_rsa 파일에 있는 내용을 입력해야 합니다.

  • SSH Servers에 대한 내용

    • Name은 본인이 사용하고자 하는 임의의 이름을 설정해주면 됩니다.
    • HostName에 사용할 주소는 Jenkins 서버에서 원격 서버로의 SSH 연결을 설정할 때 사용되는 것이므로, 주로 접근 가능한 주소를 사용하는 것이 일반적입니다.
    • UserName 은 접속할 원격 서버의 user 이름입니다.
      리눅스는 ec2-user입니다.
    • directory : 인스턴스 디렉토리
      . Amazon Linux 및 일부 기타 리눅스 기반 AMI의 기본 사용자는 ec2-user이며, 홈 디렉토리 경로는 /home/ec2-user입니다. Ubuntu AMI의 기본 사용자는 ubuntu이며, 홈 디렉토리 경로는 /home/ubuntu입니다.

스프링 부트 프로젝트 연동

1. 개발 서버에 8080 포트 열어주기

2. Dockerfile 작성

Spring boot 최상단에 Dockerfile을 만들고 아래와 같은 코드를 작성합니다.

FROM openjdk:11-jre-slim-buster
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
  1. FROM openjdk:11-jre-slim-buster:
    이 라인은 기반 이미지로 openjdk:11-jre-slim-buster 이미지를 사용한다는 것을 나타냅니다. 이 이미지는 OpenJDK 11 JRE가 설치된 Debian 기반 이미지입니다.

  2. ARG JAR_FILE=build/libs/.jar:
    이 라인은 Docker 빌드 중에 환경 변수 JAR_FILE을 사용할 것이며, 기본값으로 build/libs/
    .jar를 사용한다는 것을 정의합니다. 이렇게 함으로써, 빌드 시에 다른 JAR 파일을 지정할 수 있습니다.

  3. COPY ${JAR_FILE} app.jar:
    빌드 컨텍스트 내에서 JAR_FILE에 지정된 경로의 JAR 파일을 Docker 이미지 내부의 /app.jar로 복사합니다. 따라서 실제로는 빌드된 어플리케이션의 JAR 파일이 여기에 복사됩니다.

  4. ENTRYPOINT ["java","-jar","/app.jar"]:
    이 라인은 Docker 컨테이너가 시작될 때 실행되는 명령을 지정합니다. 여기서는 java -jar /app.jar 명령을 실행하여 어플리케이션을 시작합니다. java -jar는 Java 어플리케이션을 실행하는 일반적인 방법입니다.

이 Dockerfile을 사용하여 이미지를 빌드하면, 해당 이미지는 Java 11 JRE와 지정된 JAR 파일을 포함하며, 컨테이너가 시작될 때 자동으로 어플리케이션이 실행됩니다.

3. 프로젝트 생성(Freestyle)

Jenkins 홈 -> 새로운 Item -> ID 입력, Freestyle project 클릭 후 Ok 버튼 클릭

여기서 에러가 발생

원인1
Jenkins가 설치된 server에 git이 설치되어있지 않아서이다.

해결
아래와 같이 jenkins server에 git을 설치하면 된다.

sudo yum install git

이제 다시 jenkins에 repository를 등록하면 아래와 같이 에러가 사라졌다.

원인2

git은 설치되어 있지만 git에 SSH를 등록을 안함

SSH 경로를 붙혀넣기하면 git@github.com: Permission denied (publickey) 오류가 발생하는데 아래의 설정을 따라 입력합니다.

5번의 작업을 해주면 됩니다.

아까 발급받은 id_rsa를 찾아와야 합니다.

cat .ssh/id_rsa.pub

Credentials에 있는 Add 버튼을 클릭하고 Jenkins를 선택한다.

Username에는 Github의 ID를, Password에는 Github의 비밀번호를 입력하고 아래 Add를 누르면 저장된다.

Branches to build는 젠킨스에서 빌드를 진행할 저장소의 브랜치를 입력한다.

아래 빌드 환경의 Add timestamps to the Console Output을 선택하면 빌드 로그에서 시간을 확인할 수 있다.

Add build step의 Invoke Gradle script를 선택한다.

Use Gradle Wrapper를 선택하고 Make gradlew executable를 체크한다.
이어서 Tasks에 build -x test를 입력한다.

gradle 빌드를 진행하면서 테스트는 수행하지 않는다는 의미이며 테스트 코드가 정상으로 수행되는 프로젝트라면 -x test는 제외하고 build만 입력하자.

이후 다른 값은 선택하지 않고 저장을 눌러 마무리한다.

3-2 파이프라인으로 젠킨스

파이프라인으로 하는 방법은 다음과 같습니다.

  1. 생성

  2. Pipeline 설정
    Do not allow the pipeline to resume if the controller restarts(파이프라인 충돌 방지 옵션) 체크

  3. Pipeline script 작성
    이 부분은 Spring boot + Gradle 프로젝트 기준입니다.

    예시에서 사용한 프로젝트의 Pipeline script입니다.

pipeline {
    agent any
    stages {
        stage('Checkout') {
            steps {
                git branch: '원하는 브랜치명', url: '본인의 깃 레파지토리 URL(.git으로 끝나는링크)'
            }
        }
        stage('Build') {
            steps {
                sh './gradlew build'
            }
        }
        stage('Dockerize') {
            steps {
                sh '''
                    docker stop my_container_name || true
                    docker rm my_container_name || true
                    docker rmi my_image_name || true
                    docker build -t my_image_name .
                '''
            }
        }
        stage('Deploy') {
            steps {
                sh 'docker run -d --name my_container_name -p 8080:8080 my_image_name'
            }
        }
    }
}

my_container_name과 my_image_name은 원하시는 이름으로 대체하시면 됩니다. 하지만 각각의 my_container_name과 my_image_name이 들어있는 위치는 맞춰주셔야 됩니다.

  1. Pipeline 빌드시 실행 순서

#Dockerfile 내용
FROM openjdk:11-jre-slim
COPY build/libs/everything-shop-0.0.1-SNAPSHOT.jar app.jar
CMD ["java", "-jar", "app.jar"]

FROM openjdk:11-jre-slim : Java 11 실행 환경이 설치된 리눅스 기반 이미지를 만든다는 의미입니다.

COPY build/libs/YOUR_PROJECT-0.0.1-SNAPSHOT.jar app.jar : build/libs/YOUR_PROJECT-0.0.1-SNAPSHOT.jar 파일을 이미지에 app.jar로 포함시킵니다. 저희는 stage('build') 단계에서 빌드를 진행했기때문에 그래들 빌드를 진행하면 자동으로 build/libs 경로에 본인의 프로젝트 명이 들어간 YOUR_PROJECT-0.0.1-SNAPSHOT.jar 파일이 생성됩니다. 그래서 그 파일을 이미지에 app.jar란 이름으로 포함시키는 것입니다.

CMD ["java", "-jar", "app.jar"] : CMD명령어는 컨테이너가 실행됐을때 실행되는 기본 명령어를 지정합니다. ["java", "-jar", "app.jar"]는 app.jar파일을 실행시키는 명령어입니다.

따라서 ④ 명령어는 위의 도커파일 내용을 기반으로 이미지파일을 생성합니다 (-t my_image_name 옵션에 의해 이미지 이름은 my_image_name이 됩니다.)

→ stage('Deploy')에선 이전 단계에서 생성된 이미지 파일을 기반으로 컨테이너를 실행시킵니다. sh명령어를 살펴보면

docker run -d --name my_container_name -p 8080:8080 my_image_name

-d : 컨테이너를 백그라운드에서 실행시키는 옵션

--name my_container_name : 컨테이너의 이름을 my_container_name으로 지정하는 옵션

-p 8080:8080: 호스트포트(8080)와 컨테이너포트(8080)를 연결하는 옵션

my_image_name : 컨테이너로 실행시킬 이미지 파일을 적어줍니다

→ Pipeline빌드 완료

위의 순서대로 Pipeline 빌드가 이뤄지고 배포 또한 완료됩니다.

  1. 깃허브에서 webhook 설정하기

    http://젠킨스가설치된서버:포트/github-webhook/을 입력합니다!
    이때 /github-webhook/ 를 모두 입력해주세요!
    그리고나서 Add Webhook 버튼을 클릭하면 깃허브 설정은 끝입니다!

  2. Pipeline 설정

4. 프로젝트 빌드 확인

젠킨스 프로젝트가 완료되면 아래 화면을 확인할 수 있다.

이제 레파지토리에 새롭게 푸시를 해보겠습니다!
이렇게 새롭게 푸시를 한 다음 젠킨스를 확인해보면!

제가 빌드를 실행하지않아도 자동으로 배포를 시작합니다!

추가적인 설정

  • 구성 파일 수정전 먼저 젠킨스 서버에서 도커 허브에 로그인을 해줍니다.

  • 이때 미리 도커 허브에 가입이 되어 있어야 로그인이 가능합니다.

  • 로그인에 성공한다면 다시 젠킨스 구성 파일로 가서 Build 부분을 수정해줍니다.

  • 저는 Spring boot 배포시 Gradle을 사용하므로 Use Gradle Wrapper 클릭 후 Tasks에 build를 입력합니다.

  • Add build step을 클릭하고 Execute shell을 클릭하여 추후 설정을 해줍니다.

도커 허브에 dev라는 repository를 만들고 진행해야합니다.

./gradlew clean build
echo " Execute shell start"

# 도커 빌드와 개시 삭제
sudo docker build --no-cache -t cova1256/dev .

# 기존 서버에 있는 컨테이너 중지
sudo docker stop spring-container || true

#기존 서버에 있는 컨테이너 삭제
sudo docker rm -f spring-container || true

# 도커 로그인
sudo docker login -u cova1256 -p password 입력

# 도커 이미지 태그 설정 및 태그가 없다면 오류가 발생해도 넘어가도록 true 처리
sudo docker image tag dev cova1256/dev || true

# 도커 허브에 나의 레포지토리에 도커 푸시
sudo docker push cova1256/dev

# 푸시 후 빌드한 이미지 삭제
sudo docker rmi -f cova1256/dev || true

echo " Execute shell end"

빌드 후 조치

echo " 빌드 후 조치 start"

# 기존에 있는 이미지를 삭제합니다.
sudo docker rmi -f cova1256/dev || true

# 기존에 있는 컨테이너를 중지합니다.
sudo docker stop spring-container || true

# 기존에 있는 컨테이너를 삭제합니다.
sudo docker rm -f spring-container || true

# 컨테이너를 설치하고 실행합니다.
sudo docker run -d -p 8080:8080 --name spring-container cova1256/dev

# none인 이미지 삭제
sudo docker rmi $(docker images -q -f dangling=true)

echo " 빌드 후 조치 end"

빌드 성공 시 개발 서버에서의 도커 확인

젠킨스 서버에서 빌드 시 개발 서버에 자동으로 구축이 되도록 하였습니다. 그래서 docker ps 명령어 입력시 cova1256/dev가 있는것을 확인할 수 있습니다.

접속이 되는지 확인해 봅니다.

개발 서버의 퍼블릭 IPv4 주소:8080으로 접속하면 됩니다.


Docker에서 MySQL 설정

MySQL 이미지 다운

아래 명령어를 통해 MySQL 8.0.28 태그 이미지를 다운로드한다.태그에는 MySQL 버전을 명시하며. 만약 태그에 버전을 명시하지 않으면, 최신 버전인 latest를 가져옵니다.

docker pull mysql:8.0.28

Mysql Docker 이미지 다운로드시 실행 권한이 없어 오류가 발생하는 경우

  • docker group에 해당 유저를 추가해줘야합니다.
  • 보통 docker group이 생겼을거지만 sudo groupadd docker 명령어를 통해 한번 더 확인을 해줍니다.
  • sudo usermod -aG docker $USER 명령어를 입력하여 해당 유저를 추가해줍니다.
  • newgrp docker 명령어를 입력하여 적용이 완료됩니다. 또는 로그아웃 후 다시 로그인해도 됩니다.

Docker Mysql 컨테이너 생성 및 실행

docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=12345 --name mysql-container -v /home/mysql/:/var/lib/mysql mysql:8.0.28 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-allowed-packet=1073741824
  • -d : 백그라운드에서 실행

  • -p : 3306:3306 한것은 포트 포워딩, 실제 내 서버로 들어온 3306 포트는 도커의 3306 포트로 보내겠다는 의미

  • -e : mysql을 도커로 실행할 때 반드시 있어야 하는 옵션 중 하나, root 의 패스워드를 지정

  • --name : 컨테이너의 이름을 설정, 이 부분을 설정하지 않는다면 랜덤하게 설정됨

  • -v : 내 서버와 mysql 서버의 특정 폴더를 공유하겠다는 의미인데, 이 부분이 필요한 이유는 db 데이터를 컨테이너가 삭제되어도 보존하기 위해서 설정하는 것

  • mysql:8.0.28 : docker images 했을 경우 repository와 tag명

  • --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci : 한글 출력을 위한 인코딩

Docker 컨테이너 목록 출력

docker ps -a

Mysql 컨테이너 bash shell 접속

docker exec 명령을 사용하여 docker 컨테이너에 접근한 다음 MySQL에 로그인합니다.

docker exec -it mysql-container bash

Mysql 서버 접속

 mysql -u root -p

이렇게 하면 그냥 단순히 mysql을 다운받는거다.

외부에서 Mysql에 접근할 수 있도록 Mysql 컨테이너 내부에 사용자 생성 후 권한 부여

# 외부에서 접속 할 수 있도록 권한을 부여하도록 합니다.
GRANT ALL PRIVILEGES ON *.* TO 'kdg'@'%';
# 변경된 권한을 적용합니다.
flush privileges;
mysql -u <사용자명> -p -h <RDS 엔드포인트>

이렇게하면 MySQL을 연결하면서 RDS랑 연결하는 겁니다.

이렇게하면 도커에 MySQL을 연결을 했고 RDS랑도 연결이 되었습니다. 여기까지 진행이 된다면 젠킨스가 연결이 되었고 젠킨스에 프로젝트를 git으로 연결했고 전부 연결이 되었습니다.

이 때 MySQL 워크벤치에서 확인하려면 다음과 같이 진행합니다.

MySQLWorkbench에 RDS 연결


RDS에 연결하기 위해 채워야하는 칸들입니다.

  • Connection Name은 식별 가능한 이름을 아무거나 입력합니다.
  • Hostname은 RDS의 엔드포인트를 입력합니다.
  • Username은 RDS를 생성할 때 유저 이름으로 설정했던 것을 입력합니다. (default : admin)
  • Password는 RDS를 생성할 때 비밀번호로 설정했던 것을 입력합니다.
  • Default Schema는 비워놔도 무방합니다.


    여기서 만약에 오류가 발생할 수 있습니다.

    여기서 이런 오류가 발생하면 먼저 EC2에서 연결된 RDS인바운드 규칙을 수정하고 RDS에서 인바운드 규칙을 추가해준다.

    그리고 RDS의 퍼블릭 액세스 여부를 허용하고, 보안 그룹에서 3306 포트까지 열어줬지만 여전히 외부 연결이 안되는 사람들은 대부분 RDS가 사용하는 서브넷이 Public이 아닌 Private이라서 문제가 생기는 것이다. 그래서 서브넷을 Public으로 변경하는 방법에 대해 알려드리고자 한다.

EC2 보안 그룹 인바운드 설정

  • 인바운드란 EC2 인스턴스로 들어오는 트래픽에 대한 규칙입니다. 쉽게 설명하면 특정 프로토콜, 포트를 탑재한 차량이 시내로 접근할 수 있도록하는 보안 장치에 대한 설명입니다.

  • 3306 포트를 열어줍니다.

인스턴스 ping 테스트

Aws Ec2의 인스턴스의 탄련적 아이피 및 퍼블릭 IPv4의 주소를 입력하면 됩니다.

ex) ping 123.12.56.123

MySQL 시작/중지/재시작

# MySQL Docker 컨테이너 실행
$docker start mysql-container

# MySQL Docker 컨테이너 중지
$docker stop mysql-container 

# MySQL Docker 컨테이너 재시작
$docker restart mysql-container
profile
발전하기 위한 공부

0개의 댓글