https://velog.io/@mooh2jj/Jenkins-pipeline-Docker-SpringBoot프로젝트-배포하기
이전 블로그에서는 Jenkins pipeline으로 jenkins가 설치되어 있는 인스턴스에 배포하는 작업을 하였습니다.
이번에는 pipeline으로 원격에 있는 AWS EC2 인스턴스에 SSH 원격 서버에 배포하는 작업을 구현하는 실습을 해봅시다.
구현도는 다음과 같습니다.
# jenkins 실행
docker run \
--name jenkins-docker \
-p 9000:8080 -p 50000:50000 \
-v /home/jenkins:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/bin/docker:/usr/bin/docker \
-u root \
-d \
jenkins/jenkins:lts
docker logs [jenkins 컨테이너ID]
jenkins 홈페이지에 들어가서 pipeline
설정으로 Item
을 만들어봅니다.
그 전 블로그에서는 Pipeline > Pipleline script from SCM
으로 Jenkinsfile을 설정했다면
Pipleline script
으로 파이프라인 문법으로 작성해보고 하는 것으로 시작해도록 하겠습니다.
이는 Pipeline Syntax
를 사용하기 위함입니다.
Pipeline Syntax
는 SSH나 기타 Credentials
설정에서 pipeline 문법에 맞게 설정해주는 데 아주 유용합니다.
Jenkins Credentials 설정은 ssh 원격 서버에 접속하기 위한 publish-over-ssh
또는 private Git 프로젝트
등등 필요합니다. 이와 관련한 작업은 아래 블로그를 참주해주세요.
1) ssh 원격 서버 Credentials 설정: https://velog.io/@mooh2jj/젠킨스-자동배포하기
2) Git 프로젝트 Credentials & webhook 설정: https://velog.io/@mooh2jj/Jenkins-Git-Credentials-Github-webhook-설정
작성한 pipeline 작성 순서는
git clone -> gradle build -> docker build -> docker push
docker pull -> docker run
순으로 작업을 진행합니다.
Jenkinsfile은 spring project 바로 아래에 놓여 있다. Dockerfile도 같은 위치에 놓여야 한다는 것을 주의한다.
# 다음과 같은 순서로 동작하는 파이프라인이 완성된다.
1. jenkins인스턴스 git clone
2. jenkins인스턴스 gradle build
3. jenkins인스턴스 docker build
4. jenkins인스턴스 docker push
5. jenkins인스턴스 -> server인스턴스 ssh접속
6. server인스턴스 docker pull
7. server인스턴스 docker run
https://www.jenkins.io/doc/book/pipeline/
// Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
stages {
stage('Checkout') {
steps {
git branch: 'master',
url: 'https://github.com/mooh2jj/docker-jenkins-pipeline-test2.git'
}
}
stage('Build') {
steps {
sh 'echo "빌드" 단계와 관련된 몇 가지 단계를 수행합니다.'
}
}
stage('Test') {
steps {
//
}
}
stage('Deploy') {
steps {
sh 'echo "배포" 단계와 관련된 몇 가지 단계를 수행합니다.'
}
}
}
}
Jenkinsfile 예시
pipeline{
agent any
stages {
stage('Checkout') {
agent any
steps {
// git credentialsId: 'git-creds', url: 'https://github.com/mooh2jj/docker-jenkins-pipleline-test.git'
git branch: 'master',
url: 'https://github.com/mooh2jj/docker-jenkins-pipeline-test2.git'
}
post {
success {
echo 'prepare success'
}
always {
echo 'done prepare'
}
cleanup {
echo 'after all other post conditions'
}
}
}
stage('Build Gradle') {
steps{
sh 'chmod +x gradlew'
sh './gradlew clean build'
sh 'ls -al ./build'
}
}
stage('Docker build image'){
steps{
sh 'docker build . -t mooh2jj/docker-jenkins-pipeline-test2'
}
}
stage('Docker push image') {
steps {
withCredentials([string(credentialsId: 'dockerHubPwd', variable: 'dockerHubPwd')]) {
sh "docker login -u mooh2jj -p ${dockerHubPwd}"
}
sh 'docker push mooh2jj/docker-jenkins-pipeline-test2'
}
post {
success {
echo 'success'
}
failure {
echo 'failed'
}
}
}
stage('Run Container on SSH Dev Server'){
steps{
echo 'SSH'
sshagent (credentials: ['ssh231112']) {
sh "ssh -o StrictHostKeyChecking=no ubuntu@172.31.38.217 'whoami'"
sh "ssh -o StrictHostKeyChecking=no ubuntu@172.31.38.217 'docker ps -q --filter name=docker-jenkins-pipeline-test2 | grep -q . && docker rm -f \$(docker ps -aq --filter name=docker-jenkins-pipeline-test2)'"
sh "ssh -o StrictHostKeyChecking=no ubuntu@172.31.38.217 'docker rmi -f mooh2jj/docker-jenkins-pipeline-test2'"
sh "ssh -o StrictHostKeyChecking=no ubuntu@172.31.38.217 'docker run -d --name docker-jenkins-pipeline-test2 -p 8083:8083 mooh2jj/docker-jenkins-pipeline-test2'"
}
}
}
}
}
**결과
여기서 dockerHubPwd는 jenkins 관리
> Credentials
> System
> Global credentials (unrestricted)
> Add credential
sceret text
Global
docker Hub 비밀번호
기입dockerHubPwd
로 기입withCredentials([string(credentialsId: 'dockerHubPwd', variable: 'dockerHubPwd')]) {
sh "docker login -u mooh2jj -p ${dockerHubPwd}"
}
해당 화면에서 Build Now
를 클릭하면 jenkins build가 실행되고 잠시 후 다음과 같이 Stage View에 진행 상황이 나오는 것을 확인 할 수 있습니다.
실패하면 좌측 하단 Build History를 통해 자세한 로그를 확인할 수 있고 console out 에서도 확인할 수 있습니다.
파이프라인이 실패없이 진행되었다면 docker hub에서 해당 image가 update된 것을 확인할 수 있습니다.
docker image pull 및 run 작업을 시켜줄려면jenkins 인스턴스에서 server인스턴스로 ssh server로 credentials 설정을 해줘야 합니다.
Jenkins에서 Publish Over SSH
를 지원종료했기 때문입니다. 대충 요약하자면, 아래 취약점이 발견되어 제공을 중지했다고 하네요.
기존 Plugin Docs 페이지(https://plugins.jenkins.io/publish-over-ssh/)
* SSH 서버 이름을 이스케이프 하지 않기 때문에 XSS 취약점 발생
* 연결 테스트 구현 시 권한 검사가 누락되어 공격자가 SSH서버에 접속 가능함
* 파일 존재 여부를 위한 경호 순회기능을 이용한 경로탐색 취약점 발생
* 일반 텍스트로 저장된 비밀번호, 암호화 되지 않았기 때문에 보안에 취약함
참고 - https://hye0-log.tistory.com/44
그래서 대체용으로 ssh agent
를 사용하고자 합니다.
서로 다른 Plugin 이기 떼문에 만약 Publish Over SSH 를 설치 이 플러그인으로 ssh 설정을 해도 ssh agent로 진행해야 합니다!
sshagent plugin
을 jenkins에 설치해줍시다.
pipeline 프로젝트 내 구성에서 바로 설정하는 방법을 설명
해드리겠습니다.
Dashboard -> Jenkins 관리
-> 플러그인 관리
> 설치가능
목록에서
ssh agent를 검색
하고 체크 및 Download now and install after restart 버튼 클릭 후 재시작하시면 됩니다.
server인스턴스에 ssh접속할 수 있도록 Credentials을 등록해주어야 합니다.
이 화면은 앞서 Pipeline Syntax
안으로 들어가면 해당 설정으로 들어갈 수 있습니다.
Pipeline Syntax
> Steps
> Sample Step(sshagent: SSH Agent
)
Kind 드롭박스에서 SSH Username with private key
를 선택해줍니다.
여기서 원격 접속할 ssh 서버를 jenkins인스턴스와 연동될 수 있도록 등록할 수 있습니다.
ID
: Credential 식별 값으로 ssh231112
로 만들었습니다.
Username
: server인스턴스의 유저명인데, (ec2 ubuntu의 경우 리눅스 명령어로 whoami로 나온 값으로, ubuntu
로 합니다.)
Private Key에서 적어줘야 되는 것은
✅ssh server 인스턴스의 pem 파일내용
입니다!(2022-12-27일자 재확인!)
-----BEGIN RSA PRIVATE KEY-----
~~~~~ ssh 인스턴스의 pem 파일을 클릭하면 나옵니다
-----END RSA PRIVATE KEY-----
이 내용을 모두 입력해주고 Add
눌러주면 됩니다.
그러면 여기서 pipeline 문법으로 generate한 내용을 그대로 jenkinsfile에 옯겨주시면 됩니다.
이렇게 정리한 ssh 접속 pipeline stage는 아래와 같습니다.
위 설정할 내용대로 잘 적어주어야 합니다.
stage('Run Container on SSH Dev Server'){
steps{
echo 'SSH'
sshagent (credentials: ['{ssh-server credentials ID}']) {
sh "ssh -o StrictHostKeyChecking=no ubuntu@{private aws IP} 'whoami'"
// docker 컨텐이너가 현재 돌아갈시에 실행해야함!, 처음 실행시 주석처리
// sh "ssh -o StrictHostKeyChecking=no ubuntu@{private aws IP} 'docker ps -q --filter name=docker-jenkins-pipeline-test2 | grep -q . && docker rm -f \$(docker ps -aq --filter name=docker-jenkins-pipeline-test2)'"
// sh "ssh -o StrictHostKeyChecking=no ubuntu@{private aws IP} 'docker rmi -f mooh2jj/docker-jenkins-pipeline-test2'"
sh "ssh -o StrictHostKeyChecking=no ubuntu@{private aws IP} 'docker run -d --name docker-jenkins-pipeline-test2 -p 8083:8083 mooh2jj/docker-jenkins-pipeline-test2'"
}
}
}
jenkins pipeline 실행이 되면
ssh 설정한 인스턴스에 docker ps 명령어로 서비스가 실행된 것을 확인할 수 있습니다.
그 다음, 기존에 script로 적어서 설정한 pipeline script를 프로젝트 내 jenkinsfile로 등극해서 설정해줍니다. 이제 jenkins는 git 프로젝트 내 jenkinsfile로 pipeline을 읽게 하는 겁니다.
구성 > pipeline script from SCM
체크 ,springboot 프로젝트 Jenkinsfile
이 있는 위치까지 등록해서 설정해줍니다.
jenkins pipeline script에서 slack Notification
을 설정할 수 있습니다.
Jenkins에서 slack 플러그인
및 Credential 설정
은 아래 블로그
https://velog.io/@mooh2jj/Jenkins-Slack-Notification-등록
에서 참고하시기 바랍니다.
Jenkins pipeline
### jenkins pipeline stage 추가
stage("Slack Notification") {
steps {
echo 'slack test'
}
post {
success {
slackSend channel: '#프로그래밍', color: 'good', message: "success deploy"
}
failure {
slackSend channel: '#프로그래밍', color: 'danger', message: "failure deploy"
}
}
}
결과