기존에 하던 프로젝트에서 여러가지 문제점들을 겪게 되었습니다.
하던 프로젝트 스택을 간단히 말씀드리자면,
NodeJs로 백엔드
NextJs로 프론트를 구성하고
ec2 인스턴스 한 대를 빌려
Nginx 설정 및 mysql, https 인증 등등을 설정해주었습니다.
이 모든 문제를 해결해줄 수 있는 도구가 docker겠구나!
하며 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:
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이라는 이름으로 만들어줬습니다.
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:
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:
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가 어떻게 구성되어 있는 지 살펴보았습니다. 다음 편에선 제가 만들어 놓은 템플릿과 함께 어떻게 구현되는 지 적어보겠습니다.
😀