스타트업 개발자 혼자 빠르게 싸게 서버 구축하기 - 4편 빌드와 배포



지난 3편에서는 애플리케이션을 빌드/배포할 때 호스트 서버에 쉘 스크립트Shell script를 만들어 사용했다.

워드프레스와 마찬가지로 개발 서버 역시 도커를 사용한다. 왜냐하면 하나의 서버에 여러 서비스를 올리는 경우 SDKSoftware development kit나 소프트웨어 라이브러리 버전 충돌 같은 문제가 일어날 수 있는데 도커를 사용하면 도커 컨테이너간 가상 머신처럼 서비스가 격리 되어 여러 서비스를 쉽게 올릴 수 있기 때문이다.
프로젝트마다 도커 이미지를 만드는 Dockerfile은 모두 다르기 때문에 이 글에서 다루지 않는다.
도커 이미지 저장소를 활용하거나 젠킨스 같은 빌드 도구를 이용할 수도 있겠지만 구성하는 것도 일이어서 필자는 호스트 서버에 아래와 같은 간단한 쉘 스크립트(deploy-api-server.sh)를 만들었다.
간단하게 설명하면 호스트 서버에서 최신 소스 코드를 받아 도커 이미지를 만들고 바로 실행하는 것이다.
- https://www.popit.kr/스타트업-개발자-혼자-빠르게-싸게-서버-구축하기-3편/

쉘 스크립트는 간단하다는 장점이 있지만 스크립트 실행 이력 관리가 어렵고 다른 개발자가 스크립트를 실행하기 위해 직접 호스트 서버에 접속해야 하는 불편함이 따른다.

이 글은 쉘 스크립트를 개발자가 직접 실행하는 대신 젠킨스Jenkins를 이용하고 더불어 사설 깃랩 저장소Private GitLab Repository로부터 소스코드를 체크아웃 받아 호스트 서버에 도커 이미지를 만들고 배포하는 방식을 소개한다.

image-20201109-222458

젠킨스 설치

젠킨스를 직접 호스트 서버에 설치하지 않고 도커 컨테이너 방식으로 설치하고 실행한다. 그 이유는 젠킨스를 실행하기 위한 의존성(예. Java)을 호스트 서버에서 격리시키기 위해서이다.

호스트 서버에 아래 도커 명령어를 실행한다.

1
2
3
4
5
6
7
# 1. 젠킨스 도커 이미지 다운로드
docker pull jenkins/jenkins:lts
# 2. 젠킨스 실행
docker run -d \
 -p 8181:8080 \
 -v /var/jenkins_home:/var/jenkins_home \
 --name jenkins -u root jenkins/jenkins:lts

여기서 주목해야 할 점은 '-v /var/jenkins_home:/var/jenkins_home' 부분이다. 도커를 실행(run)할 때 볼륨Volumes 옵션으로 호스트 디렉토리(/var/jenkins_home)와 도커 컨테이너 디렉토리(/var/jenkins_home)를 공유했다. 젠킨스 도커 컨테이너가 예기치 않게 중단되어 삭제되더라도 젠킨스에서 사용했던 데이터는 남아 있어야 하기 때문이다.

웹 브라우저로 젠킨스에 접속하면 아래와 같은 화면이 나타난다.

image-20201012-232410

Administrator password를 요구하는데 '/var/jenkins_home/secrets/initalAdminPassword'에서도 찾을 수 있지만 아래 명령어로 젠킨스 도커 컨테이너의 로그에서도 확인할 수 있다.

1
docker logs -f jenkins

image-20201109-231311

Administrator password를 입력하면 플러그인 선택 화면에 나오고 계속 진행한다.

image-20201012-232636

image-20201012-232645

마지막으로 Admin User를 생성한다.

image-20201012-232954

image-20201012-233013

사설 깃랩 저장소에서 코드 체크아웃 하기

공개 저장소에서 코드를 체크아웃 할 때에는 별도의 인증이 필요하지 않지만 사설 저장소는 인증이 필요하다.

다양한 인증 방식이 있지만 필자는 깃랩에서 제공하는 Deploy Keys 방식을 선택했다.

Deploy keys allow read-only or read-write (if enabled) access to one or more repositories, by importing an SSH public key to your GitLab instance.
This is useful for cloning repositories to your Continuous Integration (CI) server. By using deploy keys, you don’t have to set up a fake user account. - https://docs.gitlab.com/ee/user/project/deploy_keys/

SSHSecure Shell 키를 깃랩에 등록 후 젠킨스에서 코드 체크아웃을 받을 때 특정 사용자 계정이 아니라 SSH키를 사용한다.

1. SSH 키 생성

먼저 Deploy Key로 사용할 SSH 키를 생성한다. 호스트 서버에서 ssh-keygen 명령어로 생성한다. 여기서 passphrease를 물어보는데 입력하지 않고 계속 엔터를 쳐서 패스워드를 없게 만든다.

image-20201012-233134

홈디렉토리의 .ssh 디렉토리에 아래와 같이 SSH 개인키(id_rsa)와 공개키(id_rsa.pub) 한 쌍이 생성된 것을 확인할 수 있다.

image-20201012-233358

image-20201012-233513

2. 깃랩 리파지토리Repository에 Deploy Key 등록

깃랩 좌측 메뉴 Settings → Repository 를 선택하면 Deploy Keys를 등록할 수 있다. Title 항목에 이름을 입력하고 Key 항목에는 앞에서 생성한 공개키(id_rsa.pub)를 넣는다.

image-20201115-215530

3. 젠킨스 자격Credentials 등록과 사용

젠킨스 좌측 메뉴의 ‘새로운 Item’을 선택한다.

image-20201116-212645

image-20201013-000919

젠킨스 Item ‘소스 코드 관리’ 항목에 사설 깃랩 저장소를 입력하면 인증을 하지 않았기 때문에 아래와 같이 빨간 글씨로 에러가 나는 것을 확인할 수 있다. Credentials 항목 ‘Add’를 선택한다.

image-20201116-213008

Private Key 항목에 앞서 생성했던 SSH 개인키(id_rsa)를 등록한다.

image-20201116-213055

생성한 Credentials(gitlab)를 선택하면 오류가 없어진 것을 확인할 수 있으며 ‘저장’ 후 ‘Build Now’를 클릭하면 코드를 체크아웃 받는 것을 확인할 수 있다.

image-20201116-220312

젠킨스에서 도커 사용하기

도커 이미지 만들기 위해 젠킨스에서 docker 명령어를 사용하면 docker 명령어를 찾을 수 없다는 오류가 난다.

image-20201116-214618

그 이유는 젠킨스 도커 컨테이너 안에 도커가 없기 때문이다.

image-20201116-215148

젠킨스 도커 컨테이너 언에서 도커를 쓰려면 젠킨스 도커 컨테이너 안에 도커를 설치해야 한다.

젠킨스 도커 컨테이너에서 직접 도커를 설치[1]할 수도 있겠지만 이렇게 만들어진 이미지는 삭제되면 다시 작업을 해주어야 하기 때문에 유지보수를 위해서는 아래와 같이 Dockerfile을 하나 만들고 따로 이미지를 만들어서 사용하는 것이 좋다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
FROM jenkins/jenkins:lts
USER root
RUN apt-get update
RUN apt-get -y install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common
RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
RUN add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu cosmic stable"
RUN apt-get update
RUN apt-get -y install docker-ce docker-ce-cli containerd.io
ENTRYPOINT ["/sbin/tini", "--", "/usr/local/bin/jenkins.sh"]

위에서 만든 Dockefile 아래 명령어를 사용하여 빌드하고 빌드한 이미지로 다시 젠킨스를 실행한다.

1
2
3
4
5
6
7
# 1. 젠킨스 이미지 빌드
docker build --tag my-jenkins:latest .
# 2. 젠킨스 실행
docker run -d \
 -p 8181:8080 \
 -v /var/jenkins_home:/var/jenkins_home \
 --name jenkins -u root my-jenkins:latest

문제는 해결되었지만…

이제 젠킨스에서 Docker 명령어를 사용할 수 있지만 또 다른 중요한 문제가 남는다.

젠킨스에서 코드를 체크아웃 받아 Docker 명령어로 빌드하면 도커 이미지가 호스트 서버가 아닌 젠킨스 컨테이너 안에 생성된다. 그 이유는 젠킨스가 컨테이너 내부의 Docker Daemon을 따로 쓰고 있기 때문이다.

image-20201208-003901

필자가 바라는 것은 젠킨스 도커 컨테이너 안에서 애플리케이션이 실행되는 것이 아니다. 호스트 서버에서 도커로 실행하는 것이다.

/var/run/docker.sock

도커를 설치하면 '/var/run/docker.sock' 파일이 만들어진다. docker.sock은 유닉스 소켓으로 도커 데몬과 통신하는데 사용하는데 docker.sock을 공유하면 젠킨스 도커 컨테이너 안에서 호스트 서버의 도커 데몬을 사용할 수 있다.

젠킨스를 실행할 때 볼륨 옵션을 추가하여 호스트 서버의 docker.sock을 컨테이너에 공유한다.

1
2
3
4
5
docker run -d \
 -p 8181:8080 \
 -v /var/jenkins_home:/var/jenkins_home \
 -v /var/run/docker.sock:/var/run/docker.sock \
 --name jenkins -u root my-jenkins:latest

젠킨스 도커 컨테이너 안에서 docker ps 명령어를 실행하면 호스트 서버의 도커 컨테이너들을 확인할 수 있다.

image-20201105-235139

젠킨스를 사용하면서 한국 시간대로 보여지길 원한다면 젠킨스 실행할 때  '-e TZ=Asia/Seoul' 옵션을 추가한다.

1
2
3
4
5
6
docker run -d \
 -p 8181:8080 \
 -v /var/jenkins_home:/var/jenkins_home \
 -v /var/run/docker.sock:/var/run/docker.sock \
 -e TZ=Asia/Seoul \
 --name jm_jenkins -u root my-jenkins:latest

주석

[1] https://docs.docker.com/engine/install/ubuntu/


Popit은 페이스북 댓글만 사용하고 있습니다. 페이스북 로그인 후 글을 보시면 댓글이 나타납니다.