본문으로 건너뛰기

Docker in Docker를 이용해 CI/CD 구축하기 (with jenkins, slack)

 · reading-time-plural · 

docker in docker 테크닉을 이용해 docker로 실행된 jenkins 환경에 또 docker를 이용해 웹 애플리케이션을 띄어보도록 하겠습니다.

jenkins 설치

docker를 이용하여 jenkins를 설치합니다.

jenkins가 docker 컨테이너에서 돌아가고 빌드 유발시 컨테이너안에서 또 하나의 컨테이너가 생성되기 때문에 docker in docker 방식으로 구현됩니다.

Dockerfile 작성

기본적으로 jenkins에는 dockerdocker-compose 가 없습니다. 초기에 쉽게 설정할 수 있도록 Dockerfile 을 작성하도록 합니다.

Dockerfile
FROM jenkins/jenkins:lts

USER root

RUN apt-get update

# docker install
RUN curl -fsSL https://get.docker.com/ | sh

# docker-compose install
RUN curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && \
chmod +x /usr/local/bin/docker-compose
jenkins docker image

jenkins 도 있지만 2.60.3 이후에 더 이상 업데이트가 종료되었습니다. jenkins/jenkins 는 최신 jenkins 버전을 지원합니다. jenkins/jenkins 는 Jenkins의 기본 이미지만을 제공하기 때문에, 추가적인 작업이 필요하다면, 따로 Dockerfile을 세팅해야 합니다.

jenkins 사용시 마운트 이유

/var/run/docker.sock 파일만 공유를 하면 Local에 설치된 Docker를 컨테이너 내부에서 사용할 수 있고, 또한 컨터에너 내부에 설치된 Docker를 다른 컨테이너 내부에서 사용이 가능해집니다. 덕분에, 젠킨스 파일을 모두 백업할 수 있습니다.

자세한 설명은 Docker in docker 를 참고허세요.

docker-compose 작성

이미지 빌드 및 파라미터를 문서화 할 수 있도록 docker-compose 를 작성합니다.

docker-compose.yml
version: "3.8"
services:
jenkins:
build: .
image: jenkins/jenkins
restart: always
container_name: jenkins
user: root
ports:
- 8080:8080
volumes:
- ./jenkins_home:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock
environment:
TZ: "Asia/Seoul"

실행

docker-compose 의 파일 경로로 이동하여 docker-compose -p jenkins up -d 으로 실행하도록 합니다.

info

windows에서 설치하면 아래의 사진처럼 WSL이 가능하므로 Docker Desktop for Windows으로 설치하라고 많은 Warning message가 출력되는데 무시하고 좀 기달리면 정상적으로 설치됩니다.

파일 관리 전략

현재 jenkins 컨테이어의 볼륨은 호스트 디렉토리와 바인딩 되어있습니다.
앞으로 생길 docker resource를 쉽게 관리하기 위해 하나의 디렉토리에 Dockerfile , docker-compose , config 파일을 관리하도록 합니다.

// Ex

docker
└ jenkins
ㅤ└ Dockerfile
ㅤ└ docker-compose.yml
ㅤ└ jenkins_home
└ mysql
ㅤ└ Dockerfile
ㅤ└ docker-compose.yml
ㅤ└ config 파일

확인

실행한 컨테이너로 들어가 dockerdocker-compose version을 출력하여 정상적으로 설치된 것을 확인할 수 있습니다.

jenkins 접속

호스트 PC에서 8080 으로 접속하도록 설정했음으로 http://{Server IP}:8080 으로 접속하도록 합니다.

그러면 비밀번호를 요구하는데 비밀번호는 docker-compose logs 혹은 해당 컨테이너 logs에 적혀있습니다.

필수 플러그인을 설치하도록 합니다.

admin 계정을 설정합니다.

jenkins의 TCP 포트를 앞으로 계속 같은 포트로 쓸 것인지 물어봅니다. 여기서 현재의 포트를 사용한다고 하면 jenkins 호출시 현재 포트번호로 호출해야합니다. 일단은 같은 포트를 사용할 예정이므로 Save하여 사용하도록 합니다.

이로써 docker를 이용하여 jenkins 설치는 끝났습니다. 이제 ci/cd를 위한 소스코드를 작성하도록 하겠습니다.

소스코드 작성

실습이 진행된 코드는 parkgang/helloworld-docker-cicd 에서 확인하실 수 있습니다.

Webhook 설정

github에서 소스코드 변화가 감지되면 알아서 빌드되도록 Webhook을 설정해야합니다.

info

Github에 Webhooks 설정

jenkins item 생성

~\jenkins_home\workspace 에 프로젝트 파일단위가 저장됩니다.

public repose이므로 github 계정은 입력하지 않았습니다.

info

shell의 pwd는 /var/jenkins_home/workspace/~ 입니다.

Webhook 확인

먼저 강제로 trigger으로 스트립트와 github pull하는데 문제가 없는지 확인합니다.

tip

만약 github repos가 권한이 필요한 경우 혹은 item이 잘못된 경우 Console Output을 통해 수정합니다.

문제가 없다면 소스 수정 후 Github에 Push하여 jenkins에서 자동으로 빌드가 유발되는지 확인합니다.

Webhook이외 원격 빌드

token을 이용해서 API처럼 원격으로 빌드를 수행할 수 있습니다.

note

http://kyungeun.koreacentral.cloudapp.azure.com:8080/job/helloworld-docker-cicd/build?token=rebuild_token

소스코드 docker 컨테이너화

이제 소스코드를 컨테이너화 시켜서 배포해보도록 하겠습니다. 소스코드는 Webbook때 사용한 코드와 동일합니다.

Execute shell에 추가

아래의 shellscript를 jenkins item의 Execute shell에 추가합니다.

컨테이너를 종료하지 않으면 같은 이름의 컨테이너가 실행되지 않음으로 삭제하고 다시 이미지 빌드 후 컨테이너화 하는 script입니다.

docker rm -f tomcat-cicd || true

docker-compose -p jenkins-helloworld-docker-cicd up -d --build
info

위의 shellscript는 docker-compose 를 이용한 방법입니다. 아래의 script와 동일합니다.

docker rm -f tomcat-cicd || true

docker build -t tomcat-cicd-image:practice .
docker run -d --name tomcat-cicd -p 8888:8080 tomcat-cicd-image:practice

확인

push후 정상적으로 컨테이너가 실행되는 것을 확인할 수 있습니다.

slack 연동

  1. docker를 이용한 CI 구축 연습하기 (젠킨스, 슬랙)글을 참고합니다
  2. 해당 글으로 성공했습니다

docker in docker issue

docker in docker으로 사용시 생기는 몇가지 문제점이 있습니다.

파일 마운트의 경로가 host pc으로 잡히는 문제가 있는 걸로 확인됩니다. 주의해서 사용바랍니다.

자세한 설명은 Docker in Docker cannot mount volume 를 참고하세요.

기타 빌드 도구 설정

gradle

jenkins에서 gradle shell 활성화

yarn

note
  1. yarn plugin이 없어서 npm을 통해 설치 후 사용하는 것으로 확인됩니다.
  2. node script에 하면 안됩니다.
  1. gradle + yarn 설정
  2. job 설정 부분 참고함

NodeJS Plugin을 설치합니다.

설치 후 config에 들어갑니다.

node에 대한 이름과 버전을 선택합니다.

NodeJS script는 실제로 node.js로 js를 실행하기 위한 script만 가능한 것으로 확인됩니다.

아래의 체크박스를 선택 후 Execute shell 에 쉘을 작성합니다.

note

만약에 또 yarn: not found 출력된다면 node script만 실행가능한 item을 생성&실행을 통해서 강제로 yarn만을 설치하도록 합니다.

깔끔하지 않은 방법이며 이럴꺼면 처음 docker image에서 yarn을 추가하는 것이 깔끔해 보입니다.

추후 jenkins 재설치시 한번 더 확인하도록 합니다.