Travis CI로 Express를 Docker Hub에 Push 하기

Jeongkuk Seo
sjk5766
Published in
11 min readJun 26, 2020

최근에 Travis를 가지고 이것저것 해보고 있습니다. 최종 목표는 Travis를 활용하여 무 중단 자동 배포를 하는 것인데 그 전에 Travis를 통해 Docker Hub에 image를 Push하는 내용을 정리하겠습니다.

본 포스팅은 크게 3가지 section 으로 나뉩니다.

  1. travis에 활용할 express 셋팅
  2. travis 셋팅 & 자동 테스트 & email notification
  3. build 성공 시, Docker Hub에 Image push

Express 환경구성

본 포스팅의 목적은 travis이기 때문에 express는 간단하게 설명합니다.

npm과 node는 이미 설치되어 있다고 가정하고 아래와 같이 express-generator를 설치 후 project를 생성합니다.

npm install -g express-generator
express myapp
cd myapp

아래와 같이 간단한 사칙연산 함수 4개를 정의한 파일을 추가합니다. 제 경우 models/calc 디렉토리를 만들고 그 내부에 calc.js 파일에 작성했습니다.

exports.plus = (a, b) => a + b;
exports.minus = (a, b) => a - b;
exports.multi = (a, b) => a * b;
exports.divisor = (a, b) => a / b;

package.json이 위치한 최 상위 경로에서 test 폴더를 만들고 하위에 test.js를 작성합니다.

const assert = require('assert');
const calc = require('../models/calc/calc')
suite('[TDD] calculator test', () => {
test('add two number test', () => {
const ret = calc.plus(1,2);
assert.equal(ret, 3);
})
test('minus two number test', () => {
const ret = calc.minus(3,2);
assert.equal(ret, 1);
})
test('multiple two number test', () => {
const ret = calc.multi(3,2);
assert.equal(ret, 6);
})
test('division two number test', () => {
const ret = calc.divisor(4, 2);
assert.equal(ret, 2);
})
})

테스트에 사용할 mocha를 설치하고 package.json에 아래와 같이 script에 test를 작성합니다.

{
"name": "travis-express",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "nodemon app.js",
"test": "mocha -ui tdd ./test/*.js"
},
"dependencies": {
"cookie-parser": "~1.4.4",
"debug": "~2.6.9",
"express": "~4.16.1",
"http-errors": "~1.6.3",
"jade": "~1.11.0",
"morgan": "~1.9.1"
},
"devDependencies": {
"mocha": "^8.0.1",
"nodemon": "^2.0.4"
}
}

Git Repo에 push할 때 최 상위 폴더에 package.json 파일이 존재 할 경우, travis가 자동으로 npm test를 실행하기 때문에 저도 script에 test를 정의해 mocha로 테스트 하도록 하였습니다.

만약 테스트 코드를 작성하기 귀찮다면 package.json의 npm test를 아래와 같이 사용해도 됩니다.

"scripts": {
"start": "nodemon app.js",
"test": "exit"
},

Travis CI

https://travis-ci.com/ 로 접속하여 github 계정으로 로그인합니다. 로그인 후, 화면 우측 상단의 프로필 화면을 클릭합니다.

Settings 버튼을 클릭하면 아래처럼 어떤 repo를 active 할지 선택하는 화면이 나옵니다.

저는 express-travis-example repo를 active 했고 github에 접속해 해당 repo의 setting-webhooks 부분을 보면 아래와 같이 travis 정보를 확인 할 수 있습니다.

위에서 준비한 express 소스의 최상위 경로에 .travis.yml 파일을 생성하고 아래와 같이 내용을 추가하고 git push를 실행합니다.

language: node_js
node_js:
- lts/*
before_script:
- npm install

git push를 수행 후 바로 Travis dashboard에 접속하면 아래와 같이 빌드가 진행 중인 상태를 볼 수 있습니다.

이 때 started된 부분을 클릭하면 실시간으로 진행되는 빌드 상황을 볼 수 있습니다.

실시간으로 빌드되는 로그

.travis.yml파일 내용 중lts/* 부분은 node의 버전을 lts 최신 버전을 의미하는데, 버전을 따로 명시하지 않으면 v0.10 버전이 깔려서 const 코드에 대한 에러가 아래처럼 발생하더군요

실패 시 build log

travis가 정상적으로 가상 환경에서 빌드를 수행하면 결과는 아래처럼 나옵니다. 로그 중간에 npm test를 수행하여 테스트 결과도 정상적으로 나온 것 을 알 수 있습니다.

성공 시 build log

만약 package.json 파일에 npm test가 정의되지 않을 경우 빌드 log에는 에러가 발생합니다.

다만 빌드의 최종 결과는 성공입니다. 아래와 같이 Passed 상태로 메일로 전달됩니다.

travis는 빌드에 대한 결과를 email, slack, 채팅 등 다양한 방법으로 notification 할 수 있습니다. default는 이메일인데 위 과정을 수행 후 Github에 등록된 메일로 build 결과를 수신 할 수 있었습니다.

실제로 저는 2번 fail 후 성공했습니다. 메일 내용을 보면 Failed, Still Failling, Fixed로 온 것을 볼 수 있습니다.

travis는 default로 빌드가 실패한 경우, 실패가 fix 된 경우에만 노티합니다. 만약 성공한 경우에도 노티를 받고 싶다면 .travis.yml 파일을 아래와 같이 수정하면 됩니다.

language: node_js
node_js:
- lts/*
before_script:
- npm install
notifications:
email:
on_success: always

만약 Github에 등록된 메일이 아니라 다른 메일, 혹은 다수의 메일에 전달하고 싶다면 .travis.yml 파일에 메일 주소를 명시합니다.

language: node_js
node_js:
- lts/*
before_script:
- npm install
notifications:
email:
recipients:
- example1@example.com
- example2@example.com

Docker Hub Image Push

전체 흐름은 아래와 같습니다.

  1. travis와 연동 된 repo에 push 한다.
  2. travis에서 빌드가 성공할 경우 docker hub에 image를 push한다.

우선 Docker Hub에 image를 올리려면 계정 정보가 필요합니다. .travis.yml 파일에 DOCKER_USER 정보를 기술합니다.

.
.
env:
global:
- DOCKER_USER=DOCKER_ID

패스워드를 평문으로 작성할 순 없으므로 암호화하여 추가 할 수 있도록 travis gem을 설치합니다. 우선 Windows 에서 Ruby를 설치합니다. 설치 후 아래 명령어로 travis gem을 설치합니다.

gem install travis

설치 후 encrypt 명령어로 패스워드를 암호화합니다.

travis encrypt DOCKER_PASS="DOCKER_PASSWORD" --add

그럼 .travis.yml 파일에 암호화 된 password가 secure 속성으로 추가됩니다.

env:
global:
- DOCKER_USER=DOCKER_ID
- secure: I87q0F+5I9Kx/IH/ZMT1zQ................................

.travis.yml 파일에 어떻게 배포할지 deploy 부분을 작성합니다. travis가 docker와 관련된 provider를 제공하지 않기 때문에 저는 script를 사용했습니다.

deploy:
provider: script
script: bash docker_push.sh

Docker 계정 정보와 deploy가 반영된 최종 .travis.yml 내용입니다.

다음은 travis가 deploy하는 시점에 실행 할 docker_push.sh 파일 내용입니다.

#!/bin/bash# docker.io 로그인
echo "$DOCKER_PASS" | docker login -u "$DOCKER_USER" --password-stdin
# Dockerfile 빌드
docker build -t express:0.0.1 .
# local image에 tag 추가
docker tag express:0.0.1 sjk5766/express:0.0.1
# docker hub에 push
docker push sjk5766/express:0.0.1

아래는 Dockerfile 내용입니다.

FROM node:12
MAINTAINER sjk5766 <wjdrnr6662@gmail.com>
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD [ "node", "app.js" ]

정리하면 travis가 빌드에 사용할 config 파일인 .travis.yml , docker hub에 배포하기 위한 명령어가 작성된 docker_push.sh , image를 생성 할Dockerfile 까지 준비되었고 Git에 commit & push 합니다.

Travis가 정상적으로 배포에 성공할 경우 Travis 로그에서 마지막은 아래와 같이 나타납니다.

Travis가 빌드 & 배포 종료 후 Docker Hub에도 정상적으로 보입니다.

Docker Hub에서 image를 local에 pull 받은 후 run 시켰을 때도 정상적으로 작동합니다.

결국 Travis를 활용하여 Docker Hub에 image는 배포했지만 실제로 운영하는 서버에 배포하기 위해선 수동적인 작업 or 자동 배포를 위한 추가적인 작업들이 필요하겠네요.

--

--