Menu
murmur blog
  • About me
  • Flutter
murmur blog

[bluemix]Dockerizing microservice

Posted on 2018년 11월 7일2019년 8월 28일 by JH Y
Table of Content

 
 

 
 

docker를 이용하여 개발과 test를 하는 방법에 대해 알아 보겠습니다.

microservice architecture 로 구현 해보겠습니다.

Docker, Microservice 개념에 대해서 기본적인 이해가 필요한 내용 입니다. .

 
 

 
 

 
 

본 실습은 아래와 같은 구성으로 진행 됩니다.

Contents

  • Project Setup
  • Docker Config
  • Postgres Setup
  • Users Service Setup
  • Locations Service Setup
  • Web Services Setup
  • Testing
  • Workflow
  • Test Setup
  • Next Steps

     
     

목표

  1. Microservice 를 위한 Docker 와 Docker componse 구성
  2. container에 volume 붙이기
  3. Docker container 내에서 unit test , integration test수행하기.
  4. functional test 수행
  5. running Docker container Debug 하기
  6. container 간의 통신 ( AJAX)

     
     

     
     

Project Setup

 
 

$ git clone https://github.ibm.com/yjh/node-docker-api.git
$ cd node-docker-api

 
 

아래와 같은 파일 구조를 갖고 있습니다.

├── services
│   ├── locations
│   │   ├── gulpfile.js
│   │   ├── knexfile.js
│   │   ├── package.json
│   │   ├── src
│   │   │   ├── app.js
│   │   │   ├── db
│   │   │   │   ├── connection.js
│   │   │   │   ├── create.sql
│   │   │   │   ├── migrations
│   │   │   │   │   └── 20170405114746_locations.js
│   │   │   │   ├── queries.js
│   │   │   │   └── seeds
│   │   │   │   └── locations.js
│   │   │   ├── routes
│   │   │   │   ├── _helpers.js
│   │   │   │   └── locations.js
│   │   │   └── server.js
│   │   └── tests
│   │   └── integration
│   │   ├── routes.index.test.js
│   │   └── routes.locations.test.js
│   └── users
│   ├── gulpfile.js
│   ├── knexfile.js
│   ├── npm-debug.log
│   ├── package.json
│   ├── src
│   │   ├── app.js
│   │   ├── auth
│   │   │   ├── _helpers.js
│   │   │   └── local.js
│   │   ├── db
│   │   │   ├── connection.js
│   │   │   ├── create.sql
│   │   │   ├── migrations
│   │   │   │   └── 20170403223908_users.js
│   │   │   └── seeds
│   │   │   └── users.js
│   │   ├── routes
│   │   │   └── users.js
│   │   └── server.js
│   └── tests
│   ├── integration
│   │   ├── routes.index.test.js
│   │   └── routes.users.test.js
│   └── unit
│   ├── auth.helpers.test.js
│   └── auth.local.test.js
├── tests
│   ├── main.test.js
│   └── package.json
└── web
├── gulpfile.js
├── package.json
└── src
├── app.js
├── public
│   ├── main.css
│   └── main.js
├── routes
│   ├── _helpers.js
│   └── index.js
├── server.js
└── views
├── _base.html
├── error.html
├── login.html
├── main.html
├── nav.html
├── register.html
└── user.html

 
 

폴더 구조를 살펴 보면 Service 와 web으로 나뉘어 있고 Service에 location 과 user 가 있습니다.

web ,location, user 3개의 application이 있다고 생각하면 됩니다.

 
 

 
 

docker로 application을 build 하기 전에 local 환경에서 바로 실행 해보겠습니다.

 
 

Users:

1. cd services/users

2. npm install

3. node src/server.js

4. 브라우저에서  http://localhost:3000/users/ping 로 접속

5. pong 이란 결과가 보이면 정상

6. ctrl + c 로 server 중지

 
 

Locations:

1. cd services/locations

2. npm install

3. node src/server.js

4. 브라우저에서 http://localhost:3001/locations/ping 로 접속

5. pong 이란 결과가 보이면 정상

6. ctrl + c 로 server 중지

 
 

Docker Config

위 application을 docker 환경에서 구동시켜 보겠습니다.

 
 

project root에 아래 파일을 추가 합니다.

/docker-compose.yml

/services/locations/.dockerignore

/services/locations/src/db/.dockerignore

/services/users/.dockerignore

/services/users/src/db/.dockerignore

/tests/.dockerignore

/web/.dockerignore

 
 

docker-compose.yml 파일에 아래 내용을 추가 합니다.

version: ‘2.1’

 
 

각 .dockerignore 파일에 아래 내용을 추가 합니다.

.git
.gitignore
README.md
docker-compose.yml
node_modules

 
 

Postgres Setup

 
 

Dockerfile을 추가 합니다.

/services/locations/src/db/Dockerfile

/services/users/src/db/Dockerfile

 
 

Dockerfile에 아래 내용을 추가 합니다.

FROM postgres

# run create.sql on init
ADD create.sql /docker-entrypoint-initdb.d

 
 

docker-compose.yml 파일을 아래와 같이 수정 합니다.

version: ‘2.1’

services:

users-db:
container_name: users-db
build: ./services/users/src/db
ports:
– ‘5433:5432’
environment:
– POSTGRES_USER=admin
– POSTGRES_PASSWORD=admin
healthcheck:
test: exit 0

locations-db:
container_name: locations-db
build: ./services/locations/src/db
ports:
– ‘5434:5432’
environment:
– POSTGRES_USER=admin
– POSTGRES_PASSWORD=admin
healthcheck:
test: exit 0

docker compose는 여러 container를 한번에 build , deploy 하는 것입니다.

docker-compose.yml는 그에 대한 내용을 정의 하는 파일 입니다.

user-db와 location-db라는 container를 정의 했습니다.

build 파라미터에 정의한 location에서 Dockerfile을 찾을 것이고 Dockerfile에 정의된 내용으로 build를 할 것입니다.

 
 

두 service를 build 해보겠습니다.

$ docker-compose up –build -d

 
 

build가 완료 되고 container가 running 될 것입니다.

$ docker ps

 
 

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

477a4c536c78 nodedockerapi_users-db “docker-entrypoint…” 9 seconds ago Up 6 seconds (health: starting) 0.0.0.0:5433->5432/tcp users-db

6997e2b6e707 nodedockerapi_locations-db “docker-entrypoint…” 9 seconds ago Up 5 seconds (health: starting) 0.0.0.0:5434->5432/tcp locations-db

 
 

container 상태를 확인하기 위하여 각 container에 shell로 접속 해보겠습니다.

이 단계에서는 container에 접속만 해보 겠습니다.

(container는 stateless 입니다. shell로 접속은 되지만 변경작업을 한다고 하여도 저장되지 않습니다. )

$ docker-compose run users-db bash
# exit
$ docker-compose run locations-db bash
# exit

 
 

 
 

Dockerfile을 추가 합니다.

/services/users/Dockerfile

 
 

 
 

Dockerfile에 아래 내용을 추가 합니다.

FROM node:latest

# set working directory
RUN mkdir /src
WORKDIR /src

# install app dependencies
ENV PATH /src/node_modules/.bin:$PATH
ADD package.json /src/package.json
RUN npm install

# start app
CMD [“npm”, “start”]

 
 

docker-compose.yml 파일에 아래내용을 추가 합니다. (service section에 포함되게 추가 해주세요.)

users-service:
container_name: users-service
build: ./services/users/
volumes:
– ‘./services/users:/src/app’
– ‘./services/users/package.json:/src/package.json’
ports:
– ‘3000:3000’
environment:
– DATABASE_URL=postgres://admin:admin@users-db:5432/node_docker_api_users_dev
– DATABASE_TEST_URL=postgres://admin:admin@users-db:5432/node_docker_api_users_test
– NODE_ENV=${NODE_ENV}
– TOKEN_SECRET=changeme
depends_on:
users-db:
condition: service_healthy
links:
– users-db

container_name: users-service 라는 container를 정의 했습니다.

build: build 위치를 지정했습니다.

voluem : volums을 지정했습니다. 실제 code가 있는 경로를 volume으로 지정함으로써 code 변경을 바로 바로 container에 적용 할 수 있습니다. voluem 이 없다면 source code가 바뀔때 마다 새로운 이미지 build를 하고 container를 다시 올려야 합니다. 이런 번거로움을 없애고자 container 에 source경로를 volume으로 붙였습니다.

일반적으로 development 단계에서는 code변화를 빠르게 적용하고 feedback을 보고자 이런 방식을 취합니다.

depends_on: user-service는 user-db 이 올라온 뒤에 running 될 것입니다.

links: user-service에서 user-db에 5423 port로 접근 가능. user-db:5423 형태.

 
 

 
 

NODE_ENV setup

$ export NODE_ENV=development

위와같이 완경변수로 NODE_ENV를 설정 하고 code 내에서 process.env.NODE_ENV 형태로 접근 할 수 있습니다.

development 일경우 production 일 경우 test 일 경우 등으로 환경설정을 나누어 하기위한 목적입니다.

 
 

새로추가한 service만 build 해보겠습니다.

$ docker-compose up –build -d users-service

 
 

Knex migrate를 위해 project root 경로에 migrate.sh 파일을 만들고 아래 내용을 추가 합니다.

(Knex.js는 Node.js SQL 빌더 및 query기능을 제공하는 라이브러리입니다. MySQL, MariaDB, PostgreSQL, SQLLite, Oracle, MSSQL과 같이 대부분의 RDBMS를 지원합니다.)

#!/bin/sh

docker-compose run users-service knex migrate:latest –env development –knexfile app/knexfile.js
docker-compose run users-service knex seed:run –env development –knexfile app/knexfile.js

Docker Compose에서 구동한 컨테이너에서 새로운 커맨드를 실행하고자 할 때에는 docker-compose run 커맨드를 사용합니다. 위 커맨드는 user-service 컨테이너의 knex 명령을 수행 합니다. db 정보를 code와 sync하는 migrate command와 기초data를 넣는 seed 커맨드 입니다.

knex에 대한 이해가 필요한 커맨드 이므로 간단하게만 설명하고 넘어가겠습니다.(ORM 방식을 생각하면 쉽습니다)

migrate라는 command로 code로 정의된 내용을 기반으로 실제 db의 table 또는 column 속성등을 update 할 수 있습니다.

seed는 기초data를 넣는 명령입니다. 일반적으로 test를 위해 사용하거나, initial data를 db에 넣기위해 사용됩니다.

 
 

본 과정은 docker 에 대해 알아보는 것이므로 구체적인 programming 관련 사항에대해 서는 참고만 하세요.

 
 

migrate.sh을 수행 해보겠습니다.

$ sh migrate.sh

warning이 나올 수 있는데 무시하고 넘어가겠습니다.

 
 

Test를 위한 API는 아래와 같이 구성되어 있습니다.

Endpoint

HTTP Method

CRUD Method

Result

/users/ping

GET

READ

pong

/users/register

POST

CREATE

add a user

/users/login

POST

CREATE

log in a user

/users/user

GET

READ

get user info

 
 

httpie를 이용하여 post action을 테스트 해보겠습니다.(curl 을 사용해도 되고, http request client program이 있다면 그것을 이용해도 됩니다.)

$ http POST http://localhost:3000/users/register
username=michael password=herman
$ http POST http://localhost:3000/users/login
username=michael password=herman

아래와 같이 success 결과를 보실 수 있습니다.

$ http POST http://localhost:3000/users/register username=michael password=herman

HTTP/1.1 200 OK

Access-Control-Allow-Headers: Content-Type

Access-Control-Allow-Methods: GET, PUT, POST, DELETE

Access-Control-Allow-Origin: *

Connection: keep-alive

Content-Length: 170

Content-Type: application/json; charset=utf-8

Date: Thu, 11 Oct 2018 08:55:35 GMT

ETag: W/”aa-U8XkufKkOlzHVt3cVQJUAw”

X-Powered-By: Express

{

“status”: “success”,

“token”: “eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NDA0NTc3MzUsImlhdCI6MTUzOTI0ODEzNSwic3ViIjoyfQ.mDziK5xtUpVNa7RwiWVdD_ti1e798ZyLknQS6BulyOc”

}

 
 

$ http POST http://localhost:3000/users/login username=michael password=herman

HTTP/1.1 200 OK

Access-Control-Allow-Headers: Content-Type

Access-Control-Allow-Methods: GET, PUT, POST, DELETE

Access-Control-Allow-Origin: *

Connection: keep-alive

Content-Length: 170

Content-Type: application/json; charset=utf-8

Date: Thu, 11 Oct 2018 08:55:54 GMT

ETag: W/”aa-1+JRC+koMwYxgq9slz+91w”

X-Powered-By: Express

{

“status”: “success”,

“token”: “eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NDA0NTc3NTQsImlhdCI6MTUzOTI0ODE1NCwic3ViIjoyfQ.aPWpmmT4SONNwUlgT051MNDhpA5-EU3eNxsqqABQYE8”

}

 
 

 
 

Locations Service Setup

 
 

Dockerfile을 추가 합니다.

/services/locations/Dockerfile

 
 

 
 

Dockerfile에 아래 내용을 추가 합니다.

FROM node:latest

# set working directory
RUN mkdir /src
WORKDIR /src

# install app dependencies
ENV PATH /src/node_modules/.bin:$PATH
ADD package.json /src/package.json
RUN npm install

# start app
CMD [“npm”, “start”]

 
 

docker-compose.yml 파일에 아래내용을 추가 합니다. (service section에 포함되게 추가 해주세요.)

locations-service:
container_name: locations-service
build: ./services/locations/
volumes:
– ‘./services/locations:/src/app’
– ‘./services/locations/package.json:/src/package.json’
ports:
– ‘3001:3001’
environment:
–
DATABASE_URL=postgres://admin:admin@locations-db:5432/node_docker_api_locations_dev
–
DATABASE_TEST_URL=postgres://admin:admin@locations-db:5432/node_docker_api_locations_test
– NODE_ENV=${NODE_ENV}
– TOKEN_SECRET=changeme
– WEATHER_HOST=${WEATHER_HOST}
depends_on:
locations-db:
condition: service_healthy
users-service:
condition: service_started
links:
– locations-db
– users-service

 
 

날씨 api 를 활용할 예정입니다.

IBM CLOUD의 weather company data service 를 사용 해보겠습니다.

  1. https://bluemix.net 에 가입 합니다.
  2. Catalog -> Weather Company Data 서비스 생성
  3. service credential 에서 url 확인, (service credential 이 없다면 파란색 New credential 버튼을 클릭 하여 credential을 생성 합니다.)
  4. url을 env 로 등록 합니다.

$ export WEATHER_HOST= [ibm cloud weather compay 서비스 url 정보 기입]

 
 

 
 

 
 

location service를 build 합니다.

$ docker-compose up –build -d locations-service

 
 

migrate.sh 파일에 아래 코드를 추가 합니다. (코드 내용은 이전에 설명한 것과 동일 합니다.)

docker-compose run locations-service knex migrate:latest –env development –knexfile app/knexfile.js
docker-compose run locations-service knex seed:run –env development –knexfile app/knexfile.js

 
 

migrate를 수행 합니다.

$ sh migrate.sh

 
 

Test를 위한 API는 아래와 같이 구성되어 있습니다.

Endpoint

HTTP Method

CRUD Method

Result

/locations/ping

GET

READ

pong

/locations

GET

READ

get all locations

/locations/user

GET

READ

get all locations by user

/locations/:id

GET

READ

get a single location

/locations

POST

CREATE

add a single location

/locations/:id

PUT

UPDATE

update a single location

/locations/:id

DELETE

DELETE

delete a single location

 
 

curl 또는 httpie를 이용하여 test 할 수 있습니다.

$ http GET http://localhost:3001/locations/ping

 
 

아래와 같은 결과가 나올 것입니다.

$ http GET http://localhost:3001/locations/ping

 
 

HTTP/1.1 200 OK

Access-Control-Allow-Headers: Content-Type

Access-Control-Allow-Methods: GET, PUT, POST, DELETE

Access-Control-Allow-Origin: *

Connection: keep-alive

Content-Length: 4

Content-Type: text/html; charset=utf-8

Date: Thu, 11 Oct 2018 11:03:34 GMT

ETag: W/”4-b9sIeqP7+8uCh6WToJGeYQ”

X-Powered-By: Express

 
 

pong

 
 

Web Services Setup

Dockerfile을 추가 합니다.

/web/Dockerfile

 
 

 
 

Dockerfile에 아래 내용을 추가 합니다.

FROM node:latest

# set working directory
RUN mkdir /src
WORKDIR /src

# install app dependencies
ENV PATH /src/node_modules/.bin:$PATH
ADD package.json /src/package.json
RUN npm install

# start app
CMD [“npm”, “start”]

 
 

docker-compose.yml 파일에 아래내용을 추가 합니다. (service section에 포함되게 추가 해주세요.)

web:
container_name: web
build: ./web/
volumes:
– ‘./web:/src/app’
– ‘./web/package.json:/src/package.json’
ports:
– ‘3003:3003’
environment:
– NODE_ENV=${NODE_ENV}
– SECRET_KEY=changeme
depends_on:
users-service:
condition: service_started
locations-service:
condition: service_started
links:
– users-service
– locations-service

 
 

web service를 build하겠습니다.

$ docker-compose up –build -d web

 
 

브라우저에서 http://localhost:3003/login 에 접속 합니다.

login 하라는 메뉴가 나오면 register 후에 login 합니다.

아래와 같은 페이지가 나올 것입니다.

 
 

본 웹페이지는 location-service 로 부터 (weather api 를 등록한 service) 정보를 받아서 출력하는 역할을 합니다.

web service의 코드를 좀 살펴보겠습니다.

/web/src/routes/index.js 에서 weather api 받아오는 값을 처리 합니다. ajax 방식으로 처리하는데 GET request의 uri 가

아래와 같습니다.

uri: ‘http://locations-service:3001/locations/‘

모든 서비스가 local에서 수행됨에서 request uri가 locations-service:3001 입니다. container base로 서비스가 동작 하기 때문입니다. web service에서 location-service:3001 형태로 접근 할 수 있는 이유는 docker-compose.yml 의 web service 정의 부분에서 links에 locations-service를 지정 해줬기 때문입니다.

 
 

Testing

 
 

docker 환경에서 unit testing 하는 방법을 알아보겠습니다.

test coding은 이미 되어 있습니다. code를 짜는 법이 아니라 docker 환경에서 test 를 구동하는 방법에 대해 알아보겠습니다.

 
 

환경변수를 test로 수정 합니다.

$ export NODE_ENV=test

 
 

container를 update 합니다.

새로 지정된 환경변수를 적용한다는 의미 입니다.

$ docker-compose up -d

 
 

test를 수행 합니다.

$ docker-compose run users-service npm test
$ docker-compose run locations-service npm test

 
 

test 결과가 console에 나타날 것입니다.

 
 

Workflow

 
 

container base환경에서 code가 어떻게 동작하는지 간단히 살펴 보겠습니다.

  1. container에 volume 형태로 source code를 mount 합니다.
  2. local 환경에서 source code를 수정합니다.
  3. container의 nodedaemon이 이 변화를 감지하고 app을 restart하여 변경된 code를 적용합니다.
  4. local 환경에서 debugging을 위해 사용하는 console.log 의 결과를 docker-compose logs -f 명령을 통해 확인 합니다.

 
 

Test Setup

 
 

functional test service를 만들어 보겠습니다.

 
 

Dockerfile을 추가 합니다.

/tests/Dockerfile

 
 

Dockerfile에 아래 내용을 추가 합니다.

FROM node:latest

# set working directory
RUN mkdir /src
WORKDIR /src

# install app dependencies
ENV PATH /src/node_modules/.bin:$PATH
ADD package.json /src/package.json
RUN npm install

 
 

docker-compose.yml 파일에 아래내용을 추가 합니다. (service section에 포함되게 추가 해주세요.)

tests:
container_name: tests
build: ./tests/
volumes:
– ‘./tests:/src/app’
– ‘./tests/package.json:/src/package.json’
depends_on:
users-service:
condition: service_started
locations-service:
condition: service_started
links:
– users-service
– locations-service
– web

 
 

tests service를 build 합니다.

$ docker-compose up –build -d tests

 
 

아래 명령을 통해 test를 수행 합니다.

$ export NODE_ENV=test
$ docker-compose up -d
$ docker-compose run tests npm test

 
 

ETC docker 환경에서 필요한 command

 
 

  • postgres psql 사용법

    container-id는 docker ps 명령으로 알 수 있습니다.

$ docker exec -ti <container-id> psql -U postgres

  • stop container

$ docker-compose stop

  • bring down container

$ docker-compose down

  • force build

$ docker-compose build –no-cache

  • remove image

$ docker rmi $(docker images -q)

  • unit test

$ export NODE_ENV=test
$ docker-compose up -d
$ docker-compose run users-service npm test
$ docker-compose run locations-service npm test

  • functional test

$ export NODE_ENV=test
$ docker-compose up -d
$ docker-compose run tests npm test

 
 

 
 

본 문서는 아래 원문을 편집하였습니다.

원문 : https://mherman.org/blog/developing-and-testing-microservices-with-docker/

이 글 공유하기:

  • 인쇄하기 (새 창에서 열림)
  • 페이스북에 공유하려면 클릭하세요. (새 창에서 열림)
  • 트위터로 공유하기 (새 창에서 열림)
  • LinkedIn으로 공유하기 (새 창에서 열림)
  • 구글 +1에서 공유하려면 클릭하세요 (새 창에서 열림)
  • 친구에게 전자우편으로 보내기 (새 창에서 열림)

관련

bluemix dockerizing microservice
a-Tech

답글 남기기 응답 취소

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.

카테고리

  • a-Tech
  • Aix
  • ETC
  • Flutter
  • Food
  • K_culture
  • Media
  • Power system
  • Storage

그 밖의 기능

  • 로그인
  • 글 RSS
  • 댓글 RSS
  • WordPress.org

최근 글

  • Box Constraint
  • Flutter responsive UI
  • Flutter 레이아웃
  • Flutter widget 소개
  • Write your first Flutter app, part 2
©2022 murmur blog | Powered by WordPress & Superb Themes
loading 취소
글이 전송되지 않았습니다. 이메일 주소를 확인하세요!
이메일 확인에 실패했습니다. 다시 시도하세요
죄송합니다. 귀하의 블로그에서 이메일로 글을 공유할 수 없습니다.