NodeJS, Express, MySQL, Sequelize로 구현한 프로젝트를 Docker를 이용하여 배포하기 위한 내용
처음 Docker를 사용 배포를 하면서 생긴 오류들과 과정을 기억하기 위해 남깁니다.
과정은 다음과 같습니다.
- docker-compose.yml 파일에 Redis서버와 MySQL 서버, Express app 서버 3개를 한 번에 구동시키기 위해 작성
- docker-compose up -d --build로 이미지가 만들어지고 컨테이너가 실행
- app에서 MySQL 연결 및 Redis 연결이 이뤄지고 실행
하지만 컨테이너가 실행은 됐지만 app 컨테이너의 로그를 봤더니 "connect ECONNREFUSED 127.0.0.1:3306"으로 에러가 발생 원인들의 이유부터 말하자면, 일단 첫 번째로 MySQL 컨테이너의 host를 제대로 못 찾아서 연결이 안 되고, 두 번째는 컨테이너가 구동되면서 Express app이 구동되면서 MySQL 연결하는데 MySQL 컨테이너가 다 실행이 안 된 상태인데 Express app에서 MySQL 연결을 시도해서 나는 문제였습니다!!
해결방법은 다음과 같습니다.
- host의 경우는 docker-compose.yml에 작성한 services의 DB 서비스명을 MySQL의 host 환경변수에 지정
- DOCKERIZE 라이브러리로 구동하는데 시간을 지정해줘서 MySQL 컨테이너가 구동 끝나길 기다린다
Dockerfile을 이용한 이미지 생성
Dockerfile은 Docker 이미지를 만들 때 사용하는 설정 파일
Dockerfile에 설정된 내용대로 이미지를 생성
FROM node:16
# "DOCKERIZE" 라이브러리 사용
ENV DOCKERIZE_VERSION v0.6.1
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 \
&& rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz
# 이미지 내에서 명령어를 실행할(현 위치로 잡을) 디렉터리 설정
WORKDIR /home/node/app
# 이미지 생성 과정에서 실행할 명령어
RUN npm install
# npm ci와 install의 차이점은 install은 package.json으로 모듈을 설치하지만,
# ci는 package-lock.json의 고정된 버전을 설치한다.
# RUN npm ci
# 도커환경에서 컨테이너 생성시 스크립트를 실행하는 폴더로
# 미리 작성된 스크립트들을 이동(DB .sql 파일 같은)
COPY ./scripts/ /docker-entrypoint-initdb.d/
# 호스트와 공유할 디렉터리 목록
VOLUME ["/data", "/home/data", "/root/data"]
# 컨테이너 실행시 실행할 명령어
CMD ["node", "index.js"]
# 호스트와 연결할 포트 번호
EXPOSE 80
EXPOSE 443
# 이미지 빌드 명령어 (현 파일과 같은 디렉터리에서)
# docker build -t {이미지명}
# 실행 명령어(터미널에서 로그 찍히는 것 보기)
# docker run -it --name {컨테이너명} -p 3306:3306 {이미지명}
# 실행 명령어(데몬으로 실행)
# docker run -d --name {컨테이너명} -p 3306:3306 {이미지명}
docker-compose.yml 을 이용한 이미지 생성 및 컨테이너 구동
docker-compose.yml는 여러 개의 컨테이너를 실행시킬 수 있도록 도커 애플리케이션을 정의하는 파일이다.
- 각 컨테이너의 Dockerfile 작성(기존에 있는 이미지를 사용하는 경우는 불필요)
- docker-compose.yml 작성 / 독립된 컨테이너의 실행 정의
- docker-compose up -d --build 커맨드를 실행하여 컨테이너를 구동
version: '3'
services:
db:
# Dockerfile이 있는 위치
# build: ./src/database
image: mysql:5.7
container_name: mysql-con # 컨테이너 명칭
environment: # 환경변수 값 지정
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
- TZ=Asia/Seoul
# 연결할 외부 디렉토리 : 컨테이너 내 디렉토리
volumes:
- ./src/database/scripts:/docker-entrypoint-initdb.d
# 내부에서 개방할 포트 : 외부에서 접근할 포트
ports:
- '3306:3306'
redis:
image: redis:6
container_name: redis-con
command: redis-server --port 6379
ports:
- '6379:6379'
app:
build: .
image: testxxboy/my-test
container_name: app-con
# 연결할 외부 디렉토리 : 컨테이너 내 디렉토리
volumes:
- ./:/home/web-app
# 환경변수 설정
environment:
- MYSQL_HOST=db # 서비스의 명으로 host 지정
- REDIS_HOST=redis # 서비스의 명으로 host 지정
ports:
- '3000:3000'
depends_on:
- db
'devOps' 카테고리의 다른 글
AWS EC2 Ubuntu Nginx 설치 (0) | 2025.03.01 |
---|---|
Spring 프로젝트 AWS EC2 Docker 배포 (0) | 2025.02.05 |
Spring Boot 프로젝트 AWS EC2 배포하기 (1) | 2025.02.02 |
[Docker] Redis 설치 (0) | 2023.06.28 |
Docker 설치 및 명령어 정리 (0) | 2022.07.24 |