[NodeJS] docker-compose를 활용해 nodejs 서버와 MySQL 연동 / docker volume

Onam Kwon·2022년 9월 19일
0

Docker

목록 보기
2/2
post-thumbnail

docker-compose를 활용한 NodeJS 서버와 MySQL 연동

  • docker-compose up

  • 실행 후 MySQL컨테이너에 들어가 로그인

  • 실제 DB

  • 클라이언트에서 보이는 값과 일치

프로젝트 파일 구조

~/Desktop/Desktop/CS/Practical/AWS/Project ❯ pwd                                                                                                         16:29:22
/Users/scott/Desktop/Desktop/CS/Practical/AWS/Project
~/Desktop/Desktop/CS/Practical/AWS/Project ❯ ls                                                                                                          16:29:23
Downloads           docker-compose.yml
~/Desktop/Desktop/CS/Practical/AWS/Project ❯ tree . -L 2                                                                                                 16:29:24
.
├── Downloads
│   ├── Dockerfile
│   ├── README.md
│   ├── controllers
│   │   ├── 2048
│   │   ├── authMiddleware.js
│   │   ├── board
│   │   ├── chat
│   │   ├── encryptPassword.js
│   │   ├── home
│   │   ├── issueToken.js
│   │   ├── loginCheck.js
│   │   ├── user
│   │   └── userValidateCheck.js
│   ├── models
│   │   ├── boardCommentDB.js
│   │   ├── boardDBController.js
│   │   ├── comparePassword.js
│   │   ├── connectMongoDB.js
│   │   ├── connectMySQL.js
│   │   ├── findUser.js
│   │   └── user.js
│   ├── mysql
│   ├── node_modules
│   ├── package-lock.json
│   ├── package.json
│   ├── public
│   ├── pythonScript
│   ├── routes
│   ├── server.js
│   └── views
└── docker-compose.yml

10 directories, 8 files
  • 프로젝트의 구조는 위와 같다 (레벨2까지 검색후 불필요한 파일은 지우고 필요한 파일은 따로 추가로 보이게 수정했습니다).
  • 원래는 Downloads디렉토리를 루트 디렉토리로 사용했지만 docker-compose를 사용하기 위해 상위에 폴더를 하나 더 만든 후 docker-comopse.yml파일을 추가했다.

docker-compose.yml

docker-compose.yml

version: '3.8'
services:
  server:
    depends_on:
      - mysqlDB
    ports:
      - 80:80
    build: ./Downloads
    restart: unless-stopped
    
    # combine below two together makes `-it` option when you use `docker exec -it`
    stdin_open: true # `-i`
    tty: true # `-t`

    networks:
      - mysql_db
  mysqlDB:
    image: mysql
    restart: unless-stopped
    env_file:
      - Downloads/.env
    container_name: mysql_db
    ports:
      - 3306:3306
    #environment:
      #- MYSQL_USER=${MYSQL_USER}
      #- MYSQL_DATABASE=${MYSQL_DATABASE}
      #- MYSQL_CONTAINER_NAME=${MYSQL_CONTAINER_NAME}
      #- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
      #- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
      #- MYSQL_PASSWORD=${MYSQL_PASSWORD}
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
    volumes:
      - db:/var/lib/mysql  # -v option
    networks:
      - mysql_db
volumes:
    db:
networks:
    mysql_db:
  • version: 도커 컴포즈의 버전을 의미함.
  • services: 해당 도커 컴포즈가 실행할 서비스 나열. 컨테이너의 집합체를 서비스라고 표현함.
    • 여기선 server mysqlDB 두가지 사용할 예정. 임의로 이름 만들면 됨.
    • depends_on: 다른 서비스에 대한 의존관계 정의.
    • ports: 포트 설정.
    • build: Dockerfile위치 지정.
    • networks: 네트워크 설정.
    • restart: 재시작 여부 설정.
    • env_file: .env파일 위치 지정.
    • volumes: MySQL컨테이너가 종료되어도 DB데이터를 유지하기 위해 도커에서 관리하는 볼륨이라는걸 사용함, 데이터를 이곳에 저장한다 (아래 설명).

docker volume

  • 도커 볼륨은 컨테이너와 관련된 특별한 유형의 디렉토리다.
  • 볼륨은 모든 데이터 유형을 저장할 수 있으며 코드가 될 수도 있고 로그파일 일 수도 있다. 볼륨을 사용하면 컨테이너간 데이터 공유도 된다.
  • 이미지가 업데이트 될 때 데이터 볼륨에 영향을 미치지 않는다. 따라서 컨테이너가 컴퓨터에서 삭제된 경우에도 데이터 볼륨은 남아서 여전히 제어가 가능하게 할 수 있다.
  • 도커 공식문서에서 권장하는 방식, 도커 엔진에 의해 관리됨.
  • 아래는 도커 볼륨 관련 커맨드.
~/Desktop/Desktop/CS/Practical/AWS/Project ❯ docker volume ls                                                                                            21:06:49
DRIVER    VOLUME NAME
local     db
local     prac2_db
local     prac_db
local     project_db
~/Desktop/Desktop/CS/Practical/AWS/Project ❯ docker volume create practice                                                                               21:06:53
practice
~/Desktop/Desktop/CS/Practical/AWS/Project ❯ docker volume ls                                                                                            21:07:06
DRIVER    VOLUME NAME
local     db
local     prac2_db
local     prac_db
local     practice
local     project_db
~/Desktop/Desktop/CS/Practical/AWS/Project ❯ docker volume rm practice                                                                                   21:07:10
practice
~/Desktop/Desktop/CS/Practical/AWS/Project ❯ docker volume ls                                                                                            21:07:18
DRIVER    VOLUME NAME
local     db
local     prac2_db
local     prac_db
local     project_db
~/Desktop/Desktop/CS/Practical/AWS/Project ❯ docker volume inspect db                                                                                    14:46:16
[
    {
        "CreatedAt": "2022-09-15T00:55:27Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/db/_data",
        "Name": "db",
        "Options": {},
        "Scope": "local"
    }
]
  • docker volume ls명령어를 통해 도커 볼륨의 목록을 확인할 수 있다.
  • docker volume create ${volume_name} 명령어를 통해 원하는 이름으로 볼륨을 생성할 수 있다.
    • 해당 커맨드 실행시 기본적으로 /var/lib/docker/volumes/${volume_name}/_data/ 생성됨.
      • 위 경로는 도커 Host의 내부에 있음(볼륨은 도커 엔진에 의해 관리된다).
  • docker volume rm ${volume_name} 명령어를 통해 원하는 볼륨을 삭제할 수 있다.
  • 추가로docker volume prune 커맨드로 사용하지 않는 볼륨을 삭제할 수 있다.
  • 위의 docker-compose.yml파일의 volumes에서 db:/var/lib/mysql 이 있는데 :를 기준으로 왼쪽이 사용할 볼륨 이름, 오른쪽이 도커 컨테이너에서 마운트할 경로다.

맥OS docker volume 접근

~ ❯ cd /var/lib/docker                                                                                                                                   16:05:07
cd: no such file or directory: /var/lib/docker
  • 맥OS는 도커와 기본적으로 호환되지 않기 때문에 Hyperkit를 사용한다.
    • Hyperkit은 도커에 내장되어 있는 프로그램으로 가상머신을 돌리거나 관리할떄 사용되며 경량화된 가상머신과 컨테이너 배포에 최적화 되어있다.
  • 따라서 맥OS를 사용하는 경우 맥은 VM을 뛰우고 그 위에 도커를 실행하기 때문에 /var/lib/docker경로가 존재하지 않는다.

References

docker run -it --rm --privileged --pid=host justincormack/nsenter1
  • 해당 커맨드를 입력하면 도커 호스트로 접속하게 된다.

/ # pwd
/
/ # ls
bin          containers   etc          home         lib          mnt          proc         run          srv          tmp          var
boot         dev          grpcfuse.ko  init         media        opt          root         sbin         sys          usr
/ # cd var/lib/docker/volumes/db
/var/lib/docker/volumes/db # ls
_data
/var/lib/docker/volumes/db # ls _data/board_db
BOARD.ibd    comment.ibd
  • MySQLboard_db 데이터베이스 폴더 내부 BOARD comment 테이블 확인.
~/Desktop/Desktop/CS/Practical/AWS/Project ❯ docker ps                                                                                                   17:08:06
CONTAINER ID   IMAGE            COMMAND                  CREATED       STATUS       PORTS                               NAMES
49621d83a5d4   project_server   "docker-entrypoint.s…"   3 hours ago   Up 3 hours   0.0.0.0:80->80/tcp, 8080/tcp        project_server_1
5b982b28115e   mysql            "docker-entrypoint.s…"   3 hours ago   Up 3 hours   0.0.0.0:3306->3306/tcp, 33060/tcp   mysql_db
~/Desktop/Desktop/CS/Practical/AWS/Project ❯ docker exec -it mysql_db bash                                                                               17:08:08
bash-4.4# mysql -u${user_id} -p${user_password}
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.30 MySQL Community Server - GPL

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| board_db           |
| dbPrac             |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
6 rows in set (0.02 sec)

mysql> use board_db;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+--------------------+
| Tables_in_board_db |
+--------------------+
| BOARD              |
| comment            |
+--------------------+
2 rows in set (0.00 sec)
  • hostdb볼륨에 있는 내용과 MySQL 데이터베이스 파일, 테이블 내용이 같다.
  • 아래 커맨드로 custo_mysql 컨테이너 내부에 들어갈 수 있다.
docker exec -it custom_mysql bash

MySQL 유저 생성 및 권한 부여

  • MySQL컨테이너로 docker exec -it ${MySQL_container_name} bash 커맨드를 이용해 들어간 후 mysql -u${root} -p${root_password}형식, 일반적으로 첫 로그인은 mysql -uroot -ppassword(docker-compose.yml.env에서 설정).
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.30 MySQL Community Server - GPL

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
  • 컨테이너에 접속 후 MySQL에 로그인 하면 위의 화면이 나온다.

MySQL Creating a new user

CREATE USER ‘user_id’@‘host’ IDENTIFIED BY ‘user_password’; 
  • root계정으로 접속한 후 새로운 계정을 만들려면 위 커맨드를 사용하면 된다.
  • 참고로 Node서버 컨테이너에서 MySQL컨테이너로 통신을 해야하므로 host부분에는 local이 아닌 %가 들어가야한다.

MySQL Droping a new user

  • DROP USER 'user_id'@'host';

MySQL Modifying a password plugin

  • ALTER USER 'user_id'@'host' IDENTIFIED WITH mysql_native_password BY 'user_password';

MySQL 사용자 권한 부여

GRANT ALL PRIVILEGES ON *.* TO ‘user_id@‘%’; 
GRANT GRANT OPTION ON *.* TO ‘user_id’@‘%’; 
FLUSH PRIVILEGES;
  • 아래와 같은 방법으로 계정의 호스트, 플러그인을 확인할 수 있다.
    • plugincaching_sha2_password에서 mysql_native_password로 바꾸지 않으면 로그인할때 에러가 생기는 경우도 있다 (위의 방법 참조).
mysql> use mysql;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select host, user, plugin, authentication_string from user;
+-----------+------------------+-----------------------+------------------------------------------------------------------------+
| host      | user             | plugin                | authentication_string                                                  |
+-----------+------------------+-----------------------+------------------------------------------------------------------------+
| %         | root             | caching_sha2_password | $A$005$v~
                                                                  ~Oh371q_,ZBa_68xVpZ2S51EyttiuSLUM2vGITpMuwLKnUMGza6qXSXLRC |
| localhost | mysql.infoschema | caching_sha2_password | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED |
| %         | kon6443          | mysql_native_password | *DBE7772F64BD31FDA89F9ABF216B174BA62481BB                              |
| localhost | mysql.session    | caching_sha2_password | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED |
| localhost | mysql.sys        | caching_sha2_password | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED |
S.P]f5o4GeZKavigIB3Y9/Anaa6QX3ZaIDeKsjX6cx9lBNVA8 |ord | $A$005$MBJ075Hu3
+-----------+------------------+-----------------------+------------------------------------------------------------------------+
6 rows in set (0.00 sec)

.env

.env

# For user account DB in mongodb
MONGO_URI = mongodb+srv://${YourID}:${YourPW}@cluster0.cefr7.mongodb.net/${YourDB}?retryWrites=true&w=majority

# For jsonwebtoken secret key
SECRET_KEY = 'YourjwtSecret'

# For MySQL board DB
SQL_USER = 'YourID'
SQL_PASSWORD = 'YourPW'
MYSQL_DATABASE="board_db"
MYSQL_ROOT_PASSWORD="password"
  • .env파일은 docker-compose.yml파일의 env_file 옵션부분에서 위치 지정을 해준 후 위와같은 방법으로 민감한 정보를 저장할 수 있다.

Dockerfile

Dockerfile

FROM node:16

# Creating an app directory.
WORKDIR /app

# Installing app dependencies.
COPY package*.json ./

RUN npm install

# Copying rest of the applications to app directory.
COPY . /app

# Exposing the port and starting the application.
Expose 8080

CMD ["npm", "start"]
  • WORKDIR: 컨테이너가 실행되면 CLI환경에서 app이란 이름의 디렉토리 생성
  • COPY: 의존파일 목록 복사
  • RUN: 설치
  • COPY: 나머지 파일들 복사

MySQL create connection

connectMySQL.js

// connecting MySQL

const path = require('path');
var mysql = require('mysql');

require('dotenv').config({ path: path.resolve(__dirname, '../.env') }); 

const conn = mysql.createConnection({
    host: "mysql_db",
    user: process.env.SQL_USER,
    password: process.env.SQL_PASSWORD,
    database: 'board_db'
});

module.exports = conn;
  • 위와 같이 모든 준비를 마친 후 docker-compose.yml파일이 있는 경로에서
docker-compose up
  • 위 커맨드를 날려주면 docker-compose를 사용한 서버가 돌아간다!



References

profile
권오남 / Onam Kwon

0개의 댓글