-
Notifications
You must be signed in to change notification settings - Fork 1
[젠킨스 구축] 6. 자동 빌드, push
테스트가 완료된 소스코드는 자동으로 빌드 후, 저장소(Ncloud Container Repository)로 push 된다.
이번 글에서 다룰 작업은 다음과 같다.
- jenkins 컨테이너 내부에서 docker build
- push를 위한 Ncloud Container Repository 로의 docker login
하나씩 살펴보자.
현재 젠킨스는 docker 컨테이너로 돌아간다. 이 내부에서 docker 명령을 수행해야 했다.
하지만 굳이 컨테이너 내부에 docker가 있어야 하나 싶었다. 정확하게는 docker 서버가 또 있어야 하나 싶었다.
리눅스는 모든 자원이 파일로 표현된다. docker 서버와 통신을 위한 docker 소켓 또한 파일로 표현된다.
컨테이너 내부에서 호스트의 docker 소켓에 접근할 수 있다면, 컨테이너에서는 docker 명령만 설치해 호스트의 docker 서버를 사용할 수 있을것이라 생각했다.
컨테이너 내부에서 docker 를 설치하는 Dockerfile을 만들어 사용했다.
FROM jenkins/jenkins:latest
USER root
RUN apt-get update -y
RUN apt-get install -qqy apt-transport-https ca-certificates curl gnupg2 software-properties-common -y
RUN curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
RUN add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
RUN apt-get update -y
RUN apt-get -y install docker-ce
RUN usermod -aG docker jenkins
docker cli 설치 과정을 포함한다.
이후 해당 이미지를 컨테이너로 만들어 실행할때 호스트의 docker 소켓을 마운트 해줬다. (/var/run/docker.sock
)
docker run -d -p 8080:8080 -v /var/jenkins/:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock jenkins
해당 과정을 거치고, 새로 생성한 jenkins 컨테이너 내부에서 docker
명령을 수행하니 큰 어려움 없이 수행할 수 있었다.
젠킨스 컨테이너 내부에서 docker를 실행시키기 위한 준비가 끝났으니 Dockerfile 과, Jenkinsfile을 작성해보았다.
FROM openjdk:17-oracle
RUN microdnf install findutils
WORKDIR /app
COPY . /app
RUN chmod +x ./gradlew
RUN ./gradlew build
CMD tail -f /dev/null
테스트를 위해 실행 커멘드는 tail -f /dev/null
로 설정했다.
젠킨스 파이프라인 스크립트도 작성했다.
pipeline {
agent any
stage('Build') {
steps {
script {
dir('be') {
echo 'Deploying the project...'
sh 'docker build -t test .'
}
}
}
}
}
}
파이프라인에서 정상적으로 빌드가 된 모습이다.
젠킨스에서 빌드한 이미지를 네이버 클라우드 레포지토리로 push 하는 작업이다.
NCR은 AWS의 ECR와 같이 컨테이너 이미지를 저장하는 저장소다.
docker-hub 를 사용할 수 있지만 public으로만 사용해야 하고, 보안문제때문에 개인적으로 private repo를 선호한다.
NCR도 레포지토리에 로그인을 해야 사용할 수 있다.
로그인을 위해선 API 키가 필요하지만 이 키의 경우 외부로 노출되면 안되는 값이기 때문에 jenkins의 Credentials기능을 사용하기로 했다.
Ncloud 의 API key, Secret Key를 Credentials에 text로 등록하고, pipeline에서 이 키들을 사용함으로써, 외부 노출없이 사용할 수 있다.
pipeline {
agent any
environment {
NCLOUD_ACCESS_KEY_ID = credentials('NCLOUD_ACCESS_KEY_ID')
NCLOUD_SECRET_KEY = credentials('NCLOUD_SECRET_KEY')
}
stages {
stage('Build') {
steps {
script {
dir('be') {
echo 'Deploying the project...'
sh 'docker build -t test .'
}
}
}
}
stage('Push') {
steps {
script {
sh 'echo $NCLOUD_SECRET_KEY | docker login jshop.kr.ncr.ntruss.com -u ${NCLOUD_ACCESS_KEY_ID} --password-stdin'
}
}
}
}
}
등록된 Credentials를 사용하기 위해선 credentials()
를 사용해 환경변수에 값을 보관해 사용한다.
환경변수로 키, 비밀키를 저장하고 로그인에 사용한다.
그리고 특정 레지스트리에 push 하기 위해선 이미지 태그 이름이 {registry}/{image}[:TAG]
의 형태여야 한다.
즉 jshop:v1.0.0
이라는 이미지를 NCR에 push하기 위해선 이미지 이름을 jshop.kr.ncr.ntruss.com/jshop:v1.0.0
으로 만들어 줘야 한다.
파이프라인의 빌드 과정에서 이를 수정해준다. sh 'docker build -t jshop.kr.ncr.ntruss.com/jshop:v1.0.0 .'
이제 전체 파이프라인을 수행해보면 테스트 -> docker 빌드 -> NCR push 과정까지 수행되는것을 볼 수 있다.
처음엔 docker 내부에서 docker 를 어케 실행해야 하는지 고민을 했었다.
그러다 docker 소켓만 마운트 시켜준다면 컨테이너 내부에서도 호스트의 docker 서버에 접속할 수 있을것이라 생각했고, 실제로 이렇게 동작했다.
내부에서 docker 빌드를 수행할 수 있으니, 파이프라인에 docker 명령을 넣어주기만 하면 되었기 때문에 이과정도 크게 어렵지 않았다.
아래는 지금까지 만든 Jenkinsfile
이다.
pipeline {
agent any
environment {
NCLOUD_ACCESS_KEY_ID = credentials('NCLOUD_ACCESS_KEY_ID')
NCLOUD_SECRET_KEY = credentials('NCLOUD_SECRET_KEY')
IMAGE = 'jshop.kr.ncr.ntruss.com/jshop:v1.0.0'
}
stages {
stage('Test') {
steps {
script {
dir('be') {
echo 'Test'
sh './gradlew clean test'
}
}
}
}
stage('Build') {
steps {
script {
dir('be') {
echo 'build'
sh "docker build -t ${IMAGE} ."
}
}
}
}
stage('NCR_Push') {
steps {
script {
echo 'push'
sh "echo ${NCLOUD_SECRET_KEY} | docker login jshop.kr.ncr.ntruss.com -u ${NCLOUD_ACCESS_KEY_ID} --password-stdin"
sh "docker push ${IMAGE}"
}
}
}
}
}