뉴질랜드 다이어리(NZ Diary) 라빠

[삽질포함] Docker 따라하기 #4 본문

카테고리 없음

[삽질포함] Docker 따라하기 #4

Donochi 2019. 9. 4. 09:04

지금까지는 Docker 로 하나의 Container 를 돌리는 실습을 해 보았습니다.
이번에는 Docker Compese 라는 툴을 이용하여, 두개 이상의 Container 를 구동하여 서비스를 만드는 연습을 해 보겠습니다.

최종 목표

Mysql Container 와 Node.js Container 를 각각 구동하고, Node.js 에서 Mysql Database 를 접근하는 서비스를 만들어봅니다.

간단하게 구조화하면 아래와 같습니다.

Browser (Host) -> Node.js (Container #1) -> Mysql(Container #2)

Node.js Image 만들기

Docker 따라하기 #3 에서는 단순하게 String 을 결과값으로 반환했으나, 이제는 MySql Database 에서 값을 로드하도록 변경해야 합니다.

'use strict';

const express = require('express');
const mysql = require('mysql');

const app = express();

const connection = mysql.createConnection({
  host: '0.0.0.0',
  user: 'root',
  post: 3306,
  password: 'password',
  database: 'engineer'
});

app.get('/', (req, res) => {
  connection.connect();  

  let sql = 'show tables';

  connection.query(sql, (err, rows) => {
    if (err) {
      res.send('Opps. Error happened\n');
    } else {
      res.send('Hello Engineers\n');
    }
  })
});

app.listen(8080, '0.0.0.0');
console.log(`Node Web App is Running on http://0.0.0.0:8080`);

Node.js 에서 MySql 을 사용할 수 있도록 package 에 mysql 을 dependency 를 추가하고, 이미지를 새로 만들어줍니다.

$ npm install mysql --save

결과적으로 package.json 은 아래와 같이 변경됩니다.

{
  "name": "node_web_app",
  "version": "1.0.0",
  "description": "Node.js on Docker",
  "author": "",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^4.16.3",
    "mysql": "^2.16.0"
  }
}

Docker Compose 설정하기

Docker Composer 는 하나 이상의 Docker Container 를 구동할 수 있게 도와주는 툴입니다. 이 어플리케이션처럼 두개 이상의 Container 를 구동할때, 각각을 구동하지 않고, Docker Composer 를 통해 한번에 구동할 수 있게 도와줍니다.

docker-compse.yml 은 node 와 mysql 이라는 두개의 container 를 어떻게 빌드하고 구동할지를 정의한 파일이라고 생각하시면 되겠네요.

version: '3'
services:
  node:
    build: .
    ports:
     - "8080:8080"    
    expose:
      - "8080"   
    links:
      - mysql
    depends_on:
      - mysql    
  mysql:
    image: "mysql/mysql-server"
    ports:
      - "3306:3306"    
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: engineer
      MYSQL_USER: root
      MYSQL_PASSWORD: password    
    expose:
      - "3306"

위와 같이 설정파일을 생성하고, 아래의 커맨드를 실행하면, 두개의 컨테이너가 동시에 구동됩니다.

$ docker-compose up
$ docker ps 
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS                            PORTS                               NAMES
dfdeaeeac0e1        compose_node             "npm start"              6 minutes ago       Up 4 seconds                      0.0.0.0:8080->8080/tcp              compose_node_1
45248769f312        mysql/mysql-server:5.7   "/entrypoint.sh mysq…"   6 minutes ago       Up 5 seconds (health: starting)   0.0.0.0:3306->3306/tcp, 33060/tcp   compose_mysql_1

문제점 #1

두개의 container 가 정상적으로 구동되긴 한데, node 에서 mysql 에 접속을 하지 못하는 현상이 발견됨.

Error: connect ECONNREFUSED 0.0.0.0:3306

접근방법 #1

node 에서 mysql 을 접근할때, localhost 로 접근을 하는데, node 의 3306 포트가 mysql 의 3306 포트로 연결이 되지 않았으므로, localhost 로 접근을 하지 말고, mysql 의 ip 로 접근을 해야 한다.

alice_k106 님의 블로그 를 참고하여 Host 와 Container 의 포트 연결에 대해 좀더 알아보자.

container 의 ip 를 알려면, docker inspect 명령을 사용하면 된다.

$ docker inspect <container_id>

Mysql 의 ip 로 접속하도록 Server.js 를 수정

'use strict';

const connection = mysql.createConnection({
  host: '172.19.0.2', // 획득한 IP 로 수정
  user: 'root',
  post: 3306,
  password: 'password',
  database: 'engineer'
});

문제점 #2

서버에서 에러를 리턴함.

Error: ER_HOST_NOT_PRIVILEGED: Host '172.19.0.3' is not allowed to connect to this MySQL server

접근방법 #1

Mysql 의 root 사용자가 로컬에서 접근을 허용하도록 설정되어있는 문제이므로, 신규 사용자를 추가하고, node 에서의 접근을 허용하도록 함.

$ docker exec -it <mysql_container_id> bash
$ mysql -u root -p
$ CREATE USER 'engineer'@'172.19.0.3' IDENTIFIED BY 'password';
$ GRANT ALL ON *.* TO 'engineer'@'172.19.0.3';

위와 같이 `engineer' 라는 사용자를 추가하고, 접근을 허용해준다. node 의 mysql 접근코드도 함께 변경한다.

'use strict';

const connection = mysql.createConnection({
  host: '172.19.0.2',
  user: 'engineer', // 사용자 변경
  post: 3306,
  password: 'password',
  database: 'engineer'
});

문제점 #3

서버에 로그인을 할 수 없는 문제가 발생.

Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client

접근방법 #1

Mysql 8 에서부터 사용자 인증방식이 변경되었다고 한다. docker-compose.yml 에서 버전을 지정해 주지 않아서, 최신버전인 8 을 사용하고 있었음. node 의 mysql 모듈이 아직 이를 지원하지 않으므로, mysql 버전을 5.7 로 변경하여 다시 시도함.

  mysql:
    image: "mysql/mysql-server:5.7"

정상적으로 동작확인

$ curl -i localhost:8080
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 16
ETag: W/"10-JhXyAELZ+v4AaWuE4SR9QoGav+4"
Date: Sat, 02 Mar 2019 08:42:49 GMT
Connection: keep-alive

Hello Engineers

일단 여기까지가 Docker 를 이용한 기본적인 사용방법을 익히는 따라하기가 될것 같습니다.
다음부터는 Docker 의 . Orchestration 을 한번 익혀볼까 합니다. (언제가 될지는 모르지만...쿨럭..)