컨테이너 간 네트워크 설정
1. 이슈 내용
Node.js의 express로 구현한 API 서버를 클라우드 서버에 docker-compose
로 배포하고자 하였습니다. 이 API 서버의 데이터베이스는 MongoDB
이며, API 서버의 컨테이너는 MongoDB
와 node.js
로 구성하였습니다.
version: '3.7'
services:
mongo:
image: mongo:latest
volumes:
- ./mongodb:/data/db
ports:
- 27017:27017
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: password
app:
build: ./server/
restart: always
ports:
- 80:5000
로컬 환경에서 개발할 때, Node.js 서버와 MongoDB의 포트를 각각 5000번, 5001번으로 설정하였기 때문에 Node.js 서버에서 MongoDB로 접속하기 위한 URI는 mongodb://localhost:5001
로 설정하였습니다. 다른 [issue]
글과 마찬가지로 이번에도 CI/CD 파이프라인을 구축하지 않았기 때문에 클라우드 인스턴스에서 git pull
을 하여 모든 소스 코드를 다운로드 받고, .env
파일은 따로 전달해준 후 docker-compose.yml
파일을 실행하였습니다.
$ sudo docker compose up --build -d
그리고 해당 인스턴스의 공용 IP에 5000번 포트로 접속하여 정상적으로 서버에 접속한 것을 확인하였으나, 서버와 데이터베이스 연결은 실패하였다는 로그를 확인하였습니다.
2. 해결 내용
약 5시간이라는 꽤 오랜 시간동안 삽질한 끝에 컨테이너 간 네트워크를 구성하는데 있어서 스스로 놓치고 있는 부분이 있었다는 사실을 알게 되었고, 이를 해결한 내용에 대해서 기록하였습니다. 먼저, 문제를 해결하기 전에 접근한 방식을 그림으로 나타내면 다음과 같습니다.
클라이언트가 클라우드 인스턴스에 80번 포트로 요청을 보내면, 인스턴스의 로컬 호스트에서 Node.js 서버가 실행 중인 컨테이너(이하, node
로 칭함)로 포워딩해줍니다. 여기까지는 정확히 동작하였으나, node
에서 MongoDB 서버가 실행 중인 컨테이너(이하, mongo
)로 접근하는 방법이 잘못되었다는 것을 뒤늦게 알게 되었습니다. 따라서, 전체적인 구성을 다음 그림과 같이 수정하였고, 이를 토대로 하여 문제를 해결하고자 하였습니다.
기본적으로 Docker Compose로 여러 개의 컨테이너를 실행시키면, 해당 docker-compose.yml
파일이 속해있는 폴더명에 _default
가 붙은 네트워크로 연결됩니다. 예를 들어, 해당 docker-compose.yml
파일이 포함된 폴더명이 test일때, 이를 실행시키면 test_default
라는 네트워크가 생성됩니다.
$ sudo docker network ls
NETWORK ID NAME DRIVER SCOPE
cc3ffc8789c4 bridge bridge local
10310d6d8d79 test_default bridge local
0ad1b9feb858 host host local
8a96f95bed66 none null local
즉, node
와 mongo
는 test_default라는 네트워크를 통해 통신해야 하며, node
에서 mongo
로 접속하기 위해서는 mongo
에 접속하는 URI를 현재 mongo
가 실행 중인 IP와 내부 포트인 27017번으로 변경해야 합니다. 이를 위해 현재 실행 중인 컨테이너를 확인한 후 mongo
컨테이너에 직접 접속하여 IP 주소를 확인하였습니다.
$ sudo docker ps
CONTAINER ID IMAGE PORTS NAMES
5d25694504fe node-1_app 0.0.0.0:80->5000/tcp, :::80->5000/tcp node
2a88827f218a mongo:latest 0.0.0.0:27017->27017/tcp, :::27017->27017/tcp mongo
$ sudo docker exec -it 5d25694504fe /bin/bash
root@2a88827f218a:/# hostname -I
172.23.0.3
그리고 Node.js 서버에서 MongoDB로 연결하는 URI를 mongodb://172.23.0.3:27017
으로 변경한 후 docker-compose.yml
파일을 다음과 같이 수정해 주었습니다.
version: '3.7'
services:
mongo:
image: mongo:latest
volumes:
- ./mongodb:/data/db
ports:
- 27017:27017
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: password
networks:
- default
app:
build: ./server/
restart: always
ports:
- 80:5000
networks:
- default
networks:
test_default:
driver: bridge
이어서 인스턴스에서 다시 Docker Compose를 실행시킨 후 웹 브라우저에서 인스턴스의 공용 IP로 http 요청을 보냈고, node
와 mongo
의 연결이 성공했다는 로그를 확인할 수 있었습니다.