다음 환경에서 진행되었다.
EC2 Ubuntu서버에서 Docker와 Docker compose를 사용하여 Spring Boot(Gradle)의 CI-CD 구축을 위하여 작성된 글이다.
해당 글에서 프로젝트는 Dockerfile과 Docker-compose를 기반으로 구성되어 있다.
배포할 프로젝트에 Dockerfile과 docker-compose는 이미 작성된 상태이고 나는 deploy폴더에 넣어 뒀다.
사전에 작성된 Dockerfile과 docker-compose.yml
Dockerfile
FROM openjdk:11-jre
COPY build/libs/spring-0.0.1-SNAPSHOT.jar spring.jar
EXPOSE 8080
ENTRYPOINT exec java -jar -Duser.timezone=Asia/Seoul spring.jar
docker-compose.yml
version: "3.7"
services:
redis:
container_name: redis
image: redis:alpine
ports:
- 6379:6379
volumes:
- ~/Desktop/redis/data/:/data
spring:
container_name: spring
image: [Username]/[이미지 이름] (DockerHub)
ports:
- 8080:8080
volumes:
- /var/log/:/logs/
depends_on:
- redis
먼저 그림을 보면서 대략적인 구조를 살펴보자
내 Spring Boot 서버에 Redis가 포함되므로 이 CI/CD 파이프라인에 Redis를 통합했다.
Dockerfile
을 이미지로 만들어 DockerHub에 Push한다.docker-compose.yml
파일을 EC2(Server)에 복사하고 실행한다.docker-compose.yml
이 실행되면서 내부에 있는 이미지를 Pull한다.다음과 같이 흘러가게 된다.
[Docker] EC2에 Docker 설치(Ubuntu, Docker-compose)
위의 글을 참고하여 두개의 서버에 모두 Docker, Docker-compose를 설치해 준다.
애플리케이션들의 관리는 Docker로 관리하는 것이 편하다고 생각하기 때문에 Jenkins를 사용할때 Container를 이용할 것이다.
docker-compose를 사용하여 만들어 줄 것이며, Image는 jenkins/jenkins:lts를 사용할 것이다.
해당 디렉토리에 docker-compose.yml 파일을 만든다.
vi docker-compose.yml
jenkins/jenkins:lts
이미지 사용jenkins
(본인이 하고 싶은 컨테이너명 작성)/var/run/docker.sock:/var/run/docker.sock
: jenkins container 내부에서 docker 명령어를 사용하기 위해 서버에 설치된 docker.sock을 사용할 것이다.포트는 변경 가능하다.<호스트 포트>:<컨테이너 포트>
version: '3'
services:
jenkins:
image: jenkins/jenkins:lts
container_name: jenkins_cicd
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ports:
- "8080:8080"
다음 명령어로 Jenkins Container 실행
docker-compose up -d
이미지의 다운로드가 끝나고 정상적으로 실행되면 [server ip]:8080
에 접속하면 다음과 같은 화면을 볼 수 있다.
해당 비밀번호는 컨테이너의 로그에서 확인할 수 있다.
docker logs jenkins
or
docker-compose logs
확인한 비밀번호를 사이트에 입력한 후 Continue
를 클릭한다.
그럼 플러그인 설치에 관한 내용이 나오는데, 왼쪽 Install suggested plugins
버튼을 누른다
그럼 젠킨스에서 제안하는 플러그인들을 설치한다. 5분 정도 소요된다.
진짜 가끔씩 플러그인 설치가 실패할 때가 있는데 이때는 답이 없다.
시간차를 두고 계속 시도하는 방법 뿐…
이 문제의 이유를 찾아보았지만 뚜렷한 이유가 없다.
그냥 어느정도 시간이 흐르면 해결 될 뿐.
다음과 같이 설치가 진행된다.
다 설치되면 관리자 계정을 생성할 수 있다. 계정명에는 로그인 시 사용할 ID를 입력해야한다.
정보 입력 후, Save and Continue
버튼을 누른다.
입력 후, 젠킨스 접속 URL을 확인해준다.
다음과 같이 [server 공인 ip]:8080
가 나온다.
확인 후 Save and Finish
버튼을 누른다.
이제 젠킨스를 사용할 준비가 다 되었다.
Start using Jenkins
버튼을 눌러준다
프로젝트의 CI/CD를 위한Jenkins Job 설정을 시작한다.
메인화면 좌측에서 새로운 Item
버튼을 누른다.
원하는 이름을 입력 후 Freestyle project
를 선택해서 job을 생성한다.
CI/CD를 위해서 Repository의 연결이 필요하다.
Public 설정인 Repository는 그냥 url만 넣어주면 된다.
Repository가 Private일 경우에만 다음의 과정을 추가해준다.
Repository가 Private일 경우 계정 정보를 포함해야 한다.
Jenkins
버튼을 누른다.
Username with password 항목을 선택해준다.
계정 정보가 틀리다면 Failed to connect to repository
이 문구가 뜬다.
아무 문구가 뜨지 않으면 인증 성공.
그 다음 CI/CD를 진행할 브랜치를 설정해준다.
나는 main branch
를 설정해 주었다.
github에 hook을 걸기 위해 다음 항목 선택
이 상태에서 해당 브랜치에 Push를 하게 되면 다음과 같이 성공하게 된다.
이후 해당 프로젝트의 Dockerfile을 기반으로 이미지를 만들어 DockerHub에 등록해야한다.
Docker Hub Container Image Library | App Containerization
도커 허브 사이트에 들어가서 회원가입, 로그인 후 Repository를 만들어 준다.
Create repository
버튼을 눌러준다.
Repository Name과 저장소의 Public, Private 여부를 체크하고 Create
버튼을 누른다.
Repository가 Private일 경우에만 다음의 과정을 추가해준다.
Docker Hub 홈페이지 - 우측 상단 프로필 - My Account - Security - New Access Token
위의 경로를 따라서 Token을 발급한다.
먼저 해당 프로젝트의 Dockerfile을 기반으로 이미지를 만들어야한다.
Container 내부에서 도커를 사용하는 방법에는 크게 두가지가 있다.
이번에는 Dood방식을 사용한다.
- /var/run/docker.sock:/var/run/docker.sock
아까 작성한 jenkins docker-compose.yml에서 이미 설정을 완료하였다.
Jenkins Container로 접속
docker exec -u root -it jenkins bash
그리고 Docker Cli를 설치한다.
apt-get update
apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
apt-get install docker-ce-cli
해당 명령어는 순서대로
이다.
중간중간 Y/n를 묻는데 모두 Y를 선택하면 된다.
그리고 docker ps를 입력하면 컨테이너 외부에 존재하는 도커 호스트의 기능을 빌려서 사용하는 방식이기 때문에 컨테이너 내부에서도 jenkins가 실행되는 모습을 볼 수 있다.
그리고 이미지를 만들어야 하는데 이미지를 만들기 위해서는 Dockerfile과 빌드된 Jar파일이 필요하다.
프로젝트는 컨테이너 내부의 다음 경로에 있다.
sudo chown -R jenkins:jenkins /var/jenkins_home/workspace/spring-ci-cd/.gradle
sudo chmod -R 755 /var/jenkins_home/workspace/spring-ci-cd/.gradle
cd /var/jenkins_home/workspace/spring-ci-cd (jenkins job 이름)
나는 도커 파일을 다음과 같이 최상단 폴더에 두었다.
그 후 Jenkins - job - Configuration으로 간 후
Build Steps에서 Execute shell을 선택 후 다음과 같이 입력한다.
cd /var/jenkins_home/workspace/spring-ci-cd
chmod +x ./gradlew
./gradlew clean build
docker build -t ([Username]/[이미지 이름] (DockerHub)) .
docker push ([Username]/[이미지 이름] (DockerHub))
##예)
docker build -t ichubtou/spring .
docker push ichubtou/spring
경로로 이동 후 권한을 얻고 빌드 해당 파일을 docker hub에 push
이렇게 하면 설정한 dockerhub repository에 등록이 된다.
나는 docker repository가 Private이기 때문에 로그인을 해야 Push가 가능하다.
exit
로 컨테이너를 나간 후 해당 명령어로 접속 docker exec -it jenkins bash
컨테이너 내부에 접속 후 다음 명령어를 입력한다.
docker login
username과 docker hub token을 입력하면 된다.
Docker Repository가 Private이라면 EC2(Server)에도 해당 작업을 수행한다.
해당 작업을 마친 후 실행하면 docker hub repository에 이미지가 올라간 것을 확인할 수 있다.
Jenkins - DashBoard - 젠킨스 관리 - Plugins - Available plugins
위의 경로에서 Publish Over SSH를 검색하여 설치한다.
먼저 Jenkins서버와 Spring서버의 연결을 위한 설정을 한다.
Dashboard-Jenkins 관리-System-Publish over SSH
Test Configuration을 이용하여 테스트가 가능하다.
Jenkins Job으로 이동하여
빌드 후 조치 - Send build artifacts over SSH를 선택한다.
나는 deploy의 docker-compose.yml를 전달하기 위해 deploy 내부 파일을 전송
# $JENKINS_HOME/workspace/$JOB_NAME/spring-ci-cd/test 파일 전송
Source files: test
# $JENKINS_HOME/workspace/$JOB_NAME/spring-ci-cd/deploy/ 폴더 속 모든 파일 전송
Source files: deploy/**
배포서버에도 docker와 docker-compose를 설치하고 docker login까지 마친 상태여야한다.
cd ~/deploy
docker-compose pull
docker-compose up --build -d
\deploy폴더로 이동 후 docker-compose에 있는 이미지 설치 후 실행
그리고 EC2(Server)에 접속하여 docker ps
명령어를 이용해 확인해 보면 잘 실행되는 것을 확인할 수 있다.
다음과 같은 과정을 모두 마쳤다.
좋은 글 감사합니다