Operations/Docker

Docker로 MariaDB 연결, 웹에서 DB 내용 띄우기

혬수 2024. 8. 19. 21:58

 

https://github.com/ShimHyesu/KakaoTech_Bootcamp/tree/main/0728_Docker_DB

 

📌 목표

Docker로 MariaDB 연결하여 테이블 생성하고 내용 삽입한다.

테이블 데이터를 Docker로 띄운 웹에서 확인한다.

 

📌 파일 구조

  • app
    • app.js → 앱 진입
    • connection.js → 데이터베이스와의 연결을 설정
    • userRouter.js → 사용자 정의 라우터 모듈
    • Dockerfile
  • db
    • Dockerfile
    • initdb.sql → 데이터베이스 초기화
  • docker-compose.yaml
  • .env

 

📌 Docker Compose

version: '3.9'

services:
  app:
    build: 
      context: ./app
      dockerfile: Dockerfile
    restart: on-failure
    ports:
      - "4000:4000"
    depends_on:
      - db 
    volumes:
      - ./app:/app
    env_file: # 환경변수 파일 설정
      - .env
    networks:
      - app-network

  db:
    build:
      context: ./db
      dockerfile: Dockerfile
    restart: on-failure
    environment: # 환경변수 설정 - .env 파일에 정의
      MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MARIADB_DATABASE: ${DB_DATABASE}
    ports: 
      - "3307:3306"
    volumes: # db-data 볼륨에 저장되어 컨테이너가 재시작되거나 삭제되더라도 데이터가 유지
      - db-data:/var/lib/mysql
    networks:
      - app-network

volumes:
  db-data:

networks:
  app-network:
  • 환경변수
    • docker compose 파일과 동일한 위치면 env_file로 지정하지 않아도 바로 반영 docker compose convert → 이 명령어로 환경변수 주입된 값 확인 가능
    • docker compose --env-file <파일 위치> → 이렇게 여러개의 파일로 구성 가능 개발 환경(production, develop)에 따라 다르게 환경 변수 값을 조정 가능
    • env_file 항목을 함께 포함하면 서비스마다 다른 환경변수 파일을 적용
    • https://seongjin.me/environment-variables-in-docker-compose/

 

📌 DB

# Dockerfile
FROM mariadb:latest

# /docker-entrypoint-initdb.d/ : 컨테이너가 처음 시작될 때 실행되는 SQL 파일을 저장하는 디렉토리
# 데이터베이스 초기화 작업 진행
COPY initdb.sql /docker-entrypoint-initdb.d
-- initdb.sql

-- 데이터베이스 생성 및 테이블 생성
CREATE DATABASE IF NOT EXISTS mydatabase;
use mydatabase;
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email varchar(100) NOT NULL
);
insert into users (name, email) values ('hyesu', 'hesushim@gmail.com');

-- 사용자 생성 및 권한 부여
CREATE USER '<user>'@'%' IDENTIFIED BY '<user-password>';
GRANT ALL PRIVILEGES ON mydatabase.* TO '<user>'@'%';
FLUSH PRIVILEGES;
  • sql 권한
    • ALTER USER ‘<user>’@'~' IDENTIFIED BY ‘<user-password>’;
    • ‘<user>’@’localhost’ : 내부 접근
    • ‘<user>’@’%’ : 외부 접근
    • ‘<user>’@’<특정 ip>’
    • ‘<user>’@’192.168.%’ : 특정 대역 허용
    • https://jay-so.tistory.com/67

 

📌 App

// 
// app.js
// 서버를 설정하고, 기본 라우트와 사용자 라우트를 설정하고, 서버를 시작
//

const express = require('express');

const userRouter = require('./userRouter');

const app = express();

const PORT = 4000;

app.get('/', (req, res) => {
  res.send('Hello World!');
});

app.use('/users', userRouter); // 사용자 라우트를 설정

app.listen(PORT, () => {  
  console.log(`Server is running on port ${PORT}`);
});
//
// 데이터베이스와의 연결을 설정하는 파일
//

const mariadb = require('mariadb');
require('dotenv').config({path: '../.env'});

const db = process.env.DB_DATABASE
const dbUser = process.env.DB_USER
const dbPassword = process.env.DB_PASSWORD

// 연결 풀을 생성
// 여러 개의 연결을 미리 열어 두고 요청이 있을 때마다 재사용
const pool = mariadb.createPool({ 
    host: 'db', // Docker Compose 설정에서 'db' 서비스
    user: dbUser,
    password: dbPassword,
    database: db,
    connectionLimit: 10, // 최대 연결 수
})

async function fetchConn(){
    let conn = await pool.getConnection();
    return conn;
}

module.exports = fetchConn;
  • .env 파일 상위에 있을때
    • Docker-compose.yaml에 env_file 지정
    • config에 path 지정
  • pool
//
// userRouter.js
// 데이터베이스와 상호작용하여 사용자 데이터를 조회하는 기능을 제공
//

const express = require('express');
const fetchConn = require('./connection');

const userRouter = express.Router();

userRouter.get('/', (req, res) => {
    res.send('User Router');
})

userRouter.get('/getUsers', async (req, res) => {
    let conn;
    try {
        conn = await fetchConn();

        const [results] = await conn.query('SELECT * FROM users');
        res.json(results);
    } catch (err) {
        console.error('Error fetching users:', err);
        res.status(500).send('Error fetching users');
    }finally {
        if(conn) conn.end();
    }
});

module.exports = userRouter;
  • localhost:4000/users/ → ‘User Router’ 확인 가능

  • localhost:4000/users/getUsers → users 테이블의 데이터 확인 가능
    • promise 기반의 반환된 pull → async/await
    • 연결한 풀에 쿼리 날려서 데이터 가져옴 → json으로 바꿔 웹에 출력