본문 바로가기
DevOps

Dockerfile & docker-compose 작성

by WhoamixZerOne 2022. 7. 31.

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' 카테고리의 다른 글

[Docker] Redis 설치  (0) 2023.06.28
Docker 설치 및 명령어 정리  (0) 2022.07.24

댓글