docker compose로 nginx, mysql, nodejs 설정하기

황재원·2024년 1월 7일

사지방

목록 보기
4/4
post-thumbnail

왜 docker-compose를 쓰게 됐나?

기존에 하던 프로젝트에서 여러가지 문제점들을 겪게 되었습니다.
하던 프로젝트 스택을 간단히 말씀드리자면,

NodeJs로 백엔드
NextJs로 프론트를 구성하고
ec2 인스턴스 한 대를 빌려
Nginx 설정 및 mysql, https 인증 등등을 설정해주었습니다.

  1. 모든 걸 하나의 인스턴스에 올리다 보니 용량 문제도 발생했고
  2. npm 버전 이슈도 계속 발생하고
  3. 인스턴스를 추가할 때마다 이 모든 과정을 동일하게 반복한다는 게 너무 비효율적이었습니다.

이 모든 문제를 해결해줄 수 있는 도구가 docker겠구나!
하며 docker-compose로 문제 해결을 시도해보았습니다.

그래서 docker-compose 어케 쓰는데?

검색해보니 ec2에 직접 nginx를 설치 및 설정하고
docker로는 프론트나 백엔드를 구동하는 용도로만 사용하는 글들이 많이 보였습니다.

하지만 전 docker image를 불러와 빌드하면 모든 환경이 갖추어지는!
All In One 툴을 만들고 싶었습니다.

그래서 docker-compose를 좀 더 공부해야겠다는 생각을 했죠.

version: '3.8'

services:
  nginx:
    image: nginx:latest
    volumes:
      - ./conf/nginx.conf:/etc/nginx/nginx.conf
    restart: always
    ports:
      - 80:80
    depends_on:
      - back
      - front
    networks:
      - backbone


  mysqldb:
    image: mysql:5.7
    restart: unless-stopped
    env_file: ./.env
    environment:
      - MYSQL_ROOT_PASSWORD=$MYSQLDB_ROOT_PASSWORD
      - MYSQL_DATABASE=$MYSQLDB_DATABASE
    ports:
      - $MYSQLDB_LOCAL_PORT:$MYSQLDB_DOCKER_PORT
    volumes:
      - db:/var/lib/mysql
    networks:
      - backbone

  back:
    depends_on:
      - mysqldb
    build: ./back
    restart: unless-stopped
    env_file: ./.env
    ports:
      - $NODE_LOCAL_PORT:$NODE_DOCKER_PORT
    environment:
      - DB_HOST=mysqldb
      - DB_USER=$MYSQLDB_USER
      - DB_PASSWORD=$MYSQLDB_ROOT_PASSWORD
      - DB_NAME=$MYSQLDB_DATABASE
      - DB_PORT=$MYSQLDB_DOCKER_PORT
      - CLIENT_ORIGIN=$CLIENT_ORIGIN
    networks:
      - backbone
    container_name: myBack
  front:
    depends_on:
      - back
    build:
      context: ./front
      args:
        - REACT_APP_API_BASE_URL=$CLIENT_API_BASE_URL
    ports:
      - $REACT_LOCAL_PORT:$REACT_DOCKER_PORT
    networks:
      - backbone 
    container_name: myFront 

volumes: 
  db:

networks:
  backbone:
    driver: bridge

먼저 위와 같이 docker-compose.yml 파일을 만들어줍니다.

하나 하나씩 뜯어보겠습니다.

nginx

nginx:
    image: nginx:latest
    volumes:
      - ./conf/nginx.conf:/etc/nginx/nginx.conf
    restart: always
    ports:
      - 80:80
    depends_on:
      - back
      - front
    networks:
      - backbone

volumes는 docker container 안의 디렉토리와 이 로컬 환경에서의 디렉토리를 연결해주는 장치입니다. 여기선 nginx.conf라는 configuration 파일을 넣으려고 사용했습니다.

restart: always
해당 컨테이너가 죽어도 자동으로 nginx 컨테이너를 재시작하는 명령어입니다.

ports는 이 로컬의 포트가 앞에, 컨테이너 안에서 사용할 포트가 뒤에 오게끔 작성하면 됩니다.

depends_on 은 컨테이너가 시작되고 중지되는 순서를 알려주는 명령어입니다.
따라서 back,front 컨테이너가 준비되기 전까지 nginx 컨테이너는 준비되지 않아요.

networks
중요하지 않아보여도 아주아주 중요한데요, (전 여기서 너무 헤매서요...)
network를 지정해주지 않으면 기본 로컬에 직접 접속할 수 있게 돼서 보안상 이슈가 있습니다. 그리고 각 컨테이너가 같은 통신망에서 소통하려면 같은 network를 적어줘야 돼요. 전 backbone이라는 이름으로 만들어줬습니다.

mysql

mysqldb:
    image: mysql:5.7
    restart: unless-stopped
    env_file: ./.env
    environment:
      - MYSQL_ROOT_PASSWORD=$MYSQLDB_ROOT_PASSWORD
      - MYSQL_DATABASE=$MYSQLDB_DATABASE
    ports:
      - $MYSQLDB_LOCAL_PORT:$MYSQLDB_DOCKER_PORT
    volumes:
      - db:/var/lib/mysql
    networks:
      - backbone

image와 restart 부분은 아실 거라 믿습니다.

.env 파일에 MYSQL_ROOT_PASSWORD, MYSQLDB_DATABASE, MYSQLDB_DOCKER_PORT 등등의 민감한 정보들이 들어 있습니다. 프로덕션과 개발용을 구분하기 위해 사용한 것도 있고, 민감한 정보들이 코드와 분리되어 있지 않다면 보안 문제가 생길까봐 분리해두었습니다.

나머지 밑은 위와 동일합니다.

back

back:
    depends_on:
      - mysqldb
    build: ./back
    restart: unless-stopped
    env_file: ./.env
    ports:
      - $NODE_LOCAL_PORT:$NODE_DOCKER_PORT
    environment:
      - DB_HOST=mysqldb
      - DB_USER=$MYSQLDB_USER
      - DB_PASSWORD=$MYSQLDB_ROOT_PASSWORD
      - DB_NAME=$MYSQLDB_DATABASE
      - DB_PORT=$MYSQLDB_DOCKER_PORT
      - CLIENT_ORIGIN=$CLIENT_ORIGIN
    networks:
      - backbone
    container_name: myBack

나머지는 모두 동일하게 해석하면 되는데, container_name을 추가했습니다.
중요하진 않지만 log를 용이하게 확인하기 위해 추가했습니다.

front

front:
    depends_on:
      - back
    build:
      context: ./front
      args:
        - REACT_APP_API_BASE_URL=$CLIENT_API_BASE_URL
    ports:
      - $REACT_LOCAL_PORT:$REACT_DOCKER_PORT
    networks:
      - backbone 
    container_name: myFront 

위와 동일합니다.


정리

docker compose가 어떻게 구성되어 있는 지 살펴보았습니다. 다음 편에선 제가 만들어 놓은 템플릿과 함께 어떻게 구현되는 지 적어보겠습니다.

😀

profile
낭만 개발자, 황재원

0개의 댓글