SSH Server에 Build 결과물 넘기기

Violet_Evgadn·2023년 4월 25일
0

CI&CD 자동화

목록 보기
13/28

1. 3번째 프로젝트 Copy 해서 새 Item 생성

Jenkins Maven Project와 Tomcat 연동

위 사이트에서 만든 Item을 복사하여 새로 만든다.

2. 설정 변경

  • 빌드 유발 > Poll SCM 비활성화
    • 확인 과정은 위 링크에서 수행했으므로 이제 비활성화시키자
  • 빌드 후 조치 추가 > Deploy war/ear to a container 삭제
    • 원래라면 배포한 결과물을 Container(Local Computer의 Tomcat)에서 구동까지 했지만 지금은 빌드한 결과물을 SSH Server에 보내 구동시킬 것이므로 비활성화시키자
  • 빌드 후 조치 추가 > Send build artifacts over SSH 추가
    • 빌드한 결과물(WAR, JAR 파일)을 배포할 서버를 입력하자
    • Name : 이전 Section에서 Publish over SSH에 설정한 Name 중 원하는 Server 선택
      • 필자는 이전에 지정했던 docker-server를 활용하겠다
    • Source files : 원래 빌드된 결과물이 저장되는 공간
      • Maven Project의 결과물인 war파일은 target/hello-world.war 파일로 저장되므로 target/*.war로 입력
    • Remove prefix : Source files에서 설정한 부분 제거
      • 우리는 target/hello-world.jar로 저장하는 것이 아닌 hello-world.jar로 저장하고 싶다. 따라서 target을 삭제하자
    • Remote Directory : Prefix를 제공한 Source File을 저장할 디렉터리
      • 우리가 Prefix를 제공한 것은 Home directory에 바로 hello-world.jar를 저장하고 싶었기 때문이다. SSH를 통해 접근하면 기본적으로 Home Directory에 도착하므로 현재 디렉터리에 저장함녀 된다. 따라서 "."을 입력해주자.

3. docker-server에 접속해서 Home Directory에 있는 파일 확인

일단 지금은 war파일이 없음을 볼 수 있다.

참고로 docker-server에 접속하기 위한 명령어는 아래와 같다.

docker exec -it docker-server bash

4. Jenkins에 들어가 새로 생성한 Project 지금 빌드 클릭 & 빌드 성공 후 docker-server에 접속해 파일 확인

hello-world.war 파일이 생성되었음을 알 수 있다


WAR 파일을 실행시킬 Docekr Image 생성

1. Dockerfile 생성

FROM tomcat:9.0

COPY ./hello-world.war /usr/local/tomcat/webapps

우리는 Tomcat 9.0.x 버전을 활용할 것이므로 tomcat:9.0으로 설정했다.

또한 hello-world.war 파일을 /usr/local/tomcat/webapps 밑에 저장함으로써 Tomcat에서 hello-world.war 파일이 수행될 수 있도록 만들겠다.

2. Docker Image 생성

docker build -t docker-server -f Dockerfile .

Docker-Server 환경 자체를 Dockerfile 파일을 통해 Image로 만들 것이다.

명령어에 대해서는 Docker를 공부할 때 알아보자

3. "exit" 입력 & 실행 환경에서 Image 확인

"docker images" 명령어를 통해 존재하는 Image를 보면 docker-server라는 Image가 새로 생성되었음을 볼 수 있다.

이는 DooD 방식으로 Container를 생성했기 때문에 Host Machine 역할을 하는 Docker Desktop에서 docker-server Image를 생성한 것과 같은 역할이 수행되었기 때문이다

4. docker-server Image로 Container 생성

docker run -d -p 8081:8080 --name mytomcat docker-server:latest

필자는 Web 개발을 하면서 8080 Port를 많이 활용하기 때문에 8081 Port를 통해 접근할 수 있도록 했다.

5. localhost:8081/hello-world 접속

/hello-world를 붙이는 것은 Tomcat의 설정과 관련된 내용이다.

Tomcat의 기본 설정은 webapps 디렉터리를 기본 Directory로 간주하여 HTML 파일을 Search 한다.

우리는 위 설정에서 webapps/hello-world.war가 저장되도록 설정을 해놓았다.

즉, 실행되고 있는 hello-world 프로그램은 "/hello-world"로 입력해야지만 프로그램의 "/" Path로 접근할 수 있게 되는 것이다.

<Context> 명령을 통해 Tomcat의 Root Directory를 변경시켜줄 수도 있는데, 이는 Tomcat에 관련된 내용이니 여기선 넘어가겠다.


Jenkins를 통한 Docker Image 생성 & Container 생성 자동화

0. Jenkins에서 실행해야 할 명령들 재정리

docker build --tag=cicd-project -f Dockerfile .

docker run -d -p 8081:8080 --name mytomcat cicd-project:latest

1. Mytomcat Container 삭제 & 만들었던 이미지 삭제

중간 실수는 무시하자.(Container 다시 생성하기 너무 귀찮아요 ㅠㅠ)

docker stop mytomcat

docker rm mytomcat

docker rmi [삭제할 Image ID]

2. 생성했던 Item 설정 변경

Configuration > 빌드 후 조치 > Send build artifacts over SSH에서 Exec Command를 추가할 것이다.

위 사진에서 볼 수 있듯 0번에서 상기했던 명령어들이 그대로 입력되어 있다.

단지 docker build ~ 명령 이후 세미콜론(;)을 붙여 줘 2개의 명령어가 따로 실행되어야 함을 명시해줬다.

여기에서 가장 중요한 것은 "-d"를 docker run 뒤에 붙이는 것이다.

만약 -d Option을 붙여주지 않는다면 Daemon으로 Container가 실행되는 것이 아니라 일반 Process로 실행될 것이다.

이게 무슨 큰일이냐 싶겠지만 생각보다 심각한 일인 게 Build 수행이 완료되었는지 확인할 수가 없다.

Jenkins에서는 SUCCESS 문구가 떠야 성공임을 확인할 수 있는데, docker run 명령어를 통해 일반 Process가 계속 실행되고 있는 중이므로 CI/CD 과정이 Finish 되었음을 확인할 수 없다.

docker run 명령어 수행이 완료되어야지 command까지 모두 처리하고 Jenkins를 통한 배포가 완료되었음을 확인할 수 있을 텐데 Command 수행 과정에서 Container는 끝나면 안 되기 때문에 배포가 끝나지 않는 것이다.

따라서 -d를 통해 Daemon으로 처리함으로써 Console에서는 배포된 애플리케이션이 실행되는 것에 대한 Log를 보지 않도록 하는 것이다.

3. 지금 빌드 수행 & Build 완료 후 localhost:8081/hello-world 접속


문제점

여기에서 발생하는 문제점이 1가지가 있다.

지금 생성한 Item을 다시 빌드시켜보자. 그렇다면 아마 노란색 느낌표와 함께 Build가 실패할 것이다.

왜 그럴까?

이는 CMD창에서 docker conatiner를 실행하는 명령어를 입력해보면 된다.

이게 무슨 말이냐, 이미 docker-server라는 이름의 Container가 존재하므로 또다시 docker-server라는 Container를 생성할 수는 없다는 의미이다. 이런 상황은 Jenkins에서 Container를 생성할 때도 똑같이 벌어진다.

Jenkins를 활용하더라도 사용하는 방법에 차이가 있을 뿐 위 CMD 창에 docker run ~ 명령어를 입력하는 것과 동일한 과정이 수행되는 것이고, 당연히 오류 원인도 같을 것이다.

따라서 이를 해결하기 위해선 빌드를 수행하기 이전 존재하는 Docker Container 중 동일한 이름이 있는지 확인한 뒤 만약 동일한 이름의 Container가 존재한다면 이를 중지시키고 메모리 상에서 삭제해야 한다.

우리는 이 과정을 1번 과정(Mytomcat Container 삭제 & 만들었던 이미지 삭제)에서 수동으로 수행했던 것이다.

하지만 이를 수동으로 한다는 것은 자동화와는 거리가 먼 작업이다.

이제부터 이런 문제를 해결하기 위한 방법을 알아보자

profile
혹시 틀린 내용이 있다면 언제든 말씀해주세요!

0개의 댓글