새소식

🍪 Study/Docker 도커

docker-compose (node.js, MySQL) 실행 순서 동기화

  • -
728x90

docker-compose를 사용해 node.js 서버와 mysql db 서버 컨테이너를 만들고 node.js 서버에서 mysql db 서버에 연결을 시도하면, closed 오류가 발생한다. 이는 node.js 서버가 mysql db에 연결을 시도할 때, 아직 mysql db 서버가 완전히 실행되지 않았기 때문에 발생하는 문제이다.

이를 해결하기 위해 node.js 서버가 mysql db 서버 구동 완료 후에 실행될 수 있게 해야 한다.

이는 node.js와 mysql 외의 다른 서버와 DB에 모두 적용가능한 방법이다.

 

 

디렉토리 구조

📦
 ┣ 📂 db
 ┃ ┣ 📂 conf.d  # MySQL configuraiton (선택)
 ┃ ┃ ┗ 📜 my.cnf
 ┃ ┣ 📂 initdb.d  # MySQL 초기 DB 설정 (선택)
 ┃ ┃ ┣ 📜c reate_table.sql	# 초기 테이블 생성 (선택)
 ┃ ┃ ┗ 📜 insert_data.sql	# 초기 데이터 삽입 (선택)
 ┣ 📂 server
 ┃ ┣ 📂 node_modules
 ┃ ┣ 📜. dockerignore
 ┃ ┣ 📜 docker-entrypoint.sh
 ┃ ┣ 📜 Dockerfile
 ┃ ┣ 📜 index.js
 ┃ ┣ 📜 package-lock.json
 ┃ ┗ 📜 package.json
 ┗ 📜 docker-compose.yml

이 중 필수적으로 봐야할 파일들은 다음과 같다.

  • docker-compse.yml
  •  server
    • Dockerfile
    • docker-entrypoint.sh

 

docker-compose.yml

사실 docker-compose에는 컨테이너 생성 순서와 관련해 depends_on 이 존재한다. 하지만, 기억해야할 것은 depends_on은 컨테이너의 생성 자체에만 관여하기 때문에, 컨테이너 내부에서 서버가 완전히 실행된 상태를 고려해주지는 않는다는 점이다.

# docker-compose.yml

version: "3.8"

services:
  server:
    container_name: server_app
    build:
      context: ./server
      dockerfile: Dockerfile
    ports:
      - 5000:5000
    volumes:
      - ./server:/app
    depends_on:
      - mysql_db
    stdin_open: true
    tty: true
    networks:
      - app-tier
    environment:
      - DB_HOST=mysql_db  # ip or localhost가 들어갈 수 있는데, 연결할 DB 컨테이너를 작성한다.
      - DB_PORT=3306
      - DB_USER={user 이름}
      - DB_PASSWORD={user의 password}
      - DB_DATABASE={데이터베이스 이름}

  mysql_db:
    image: mysql
    volumes:
      - db/data:/var/lib/mysql
      - ./db/conf.d:/etc/mysql/conf.d
      - ./db/initdb.d:/docker-entrypoint-initdb.d
    ports:
      - 3306:3306
    environment:
      - MYSQL_DATABASE={데이터베이스 이름}
      - MYSQL_USER={user 이름}
      - MYSQL_PASSWORD={user의 password}
      - MYSQL_ROOT_HOST=%     # 전체 ip (host)에 대해
      - MYSQL_ROOT_PASSWORD={root 계정 비밀번호}
      - TZ=Asia/Seoul
    restart: unless-stopped
    networks:
      - app-tier

networks:
  app-tier:
    driver: bridge
volumes:
  db:

중괄호로 표시된 것들은 본인 프로젝트 설정에 따라 작성하면 된다.

예를 들어, "user0" 계정을 사용하고 싶다면, DB_USER=user0으로 작성하면 된다.

 

.dockerignore

.gitignore
/node_modules

 

server (node.js)

Dockerfile

dockerize 모듈은 docker-compose에서 docker 컨테이너 간의 실행 순서를 동기화해주는 역할을 수행한다.

dockerize 모듈을 설치한 후, docker-entrypoint.sh 파일을 컨테이너에서 실행시켜 실행 순서를 동기화한다.

FROM node:latest

ENV DOCKERIZE_VERSION v0.2.0
RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
    && tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz

WORKDIR /app

COPY ./package*.json ./
RUN npm install --silent

COPY docker-entrypoint.sh ./

# RUN chmod +x docker-entrypoint.sh
ENTRYPOINT ./docker-entrypoint.sh

EXPOSE 3000

 

docker-entrypoint.sh

#!/bin/bash

echo "wait mysql_db server"
dockerize -wait tcp://mysql_db:3306 -timeout 20s

echo "start node server"
node index.js

 

실행 결과

[오류] docker-entrypoint.sh: Permission denied

서버 컨테이너에서 아래와 같은 권한 오류가 발생할 수 있는데, 이는 .sh 파일 실행에 대한 권한 오류이다.

아래 코드로 해결이 되어야 하지만, 나는 여전히 오류가 발생했다.

RUN chmod +x docker-entrypoint.sh

 

[해결]

Stackoverflow에 이 오류에 관한 글이 있었고, 여기서도 chmod를 하라는 얘기들이 있었다.

그 중, 답변의 이 부분에서 해결법을 찾았다.

Alternately, you can ensure that the local copy referenced by the Dockerfile is executable, and then use 
COPY (which is explicitly documented to retain metadata).

 

(도커 말고) 그냥 터미널에서 ./docker-entrypoint.sh를 실행했을 때, 똑같이 권한 오류가 발생했다. 따라서, 복사하려던 원본 파일 자체의 권한을 먼저 바꿔주었다.

# ./server
chmod +x docker-entrypoint.sh

 

다시 docker compose up을 실행했을 때, 정상적으로 컨테이커가 실행됨을 확인했다.

 

이제 문제없이 잘 작동된다!!

 

 

 

 


참고

https://millo-l.github.io/docker-compose-nodejs-mysql-%EC%8B%A4%ED%96%89-%EC%88%9C%EC%84%9C-%EB%8F%99%EA%B8%B0%ED%99%94/

 

[Docker] docker-compose (node.js, mysql) 실행 순서 동기화 | millo's tech blog

docker-compose에서 dockerize를 사용하여 node.js와 mysql의 실행 순서를 동기화해보자.

millo-l.github.io

 

728x90
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.