멀티 컨테이너 앱(DB 컨테이너 및 네트워크 연결)

정민교·2024년 5월 10일
0

Docker

목록 보기
4/10
post-thumbnail

📒목표

앱을 여러 컨테이너에서 실행할 수 있도록 공부해보자.

📒개요

지금까지 단일 컨테이너 애플리케이션을 사용해왔습니다. 이제는 애플리케이션 스택에 MySQL을 추가해봅시다.

그럼 MySQL도 별도의 컨테이너에서 실행해야 할까요? 일반적으로는 그렇게 하는 것이 좋습니다.

그 이유는 여러 이유가 있는데요.

1. 확장성 고려

프론트엔드, 백엔드, DB 등등 애플리케이션을 위한 각 구성 요소들은 모두 다 같이 확장되기보다는 각각 다른 시점에서 확장될 확률이 높습니다. 따라서 각각 독립적으로 확장할 수 있도록 별도의 컨테이너에서 실행하는 것이 좋습니다.

2. 업데이트와 버전관리의 독립성

별도의 컨테이너들에 앱을 실행하면 독립적으로 버전을 업데이트하고 관리할 수 있습니다.

따라서 각각을 개별적으로 업그레이드 하거나 롤백할 수 있는 유연성을 가질 수 있습니다.

3. 운영 환경의 유연성

개발 환경에서는 로컬 컨테이너로 데이터베이스를 운영할 수 있지만, 실제 운영 환경에서는 더 안정적인 데이터베이스 서비스(AWS RDS, GCP SQL 등)를 사용할 수 있습니다.

로컬, 개발 환경에서는 컨테이너를 사용하다가 운영 환경에서는 관리형 서비스로 쉽게 전환할 수 있는 유연성을 가질 수 있습니다.

4. 복잡성 관리

여러 프로세스를 실행해야 할 경우, 프로세스 관리자가 필요하게 됩니다(컨테이너는 기본적으로 하나의 프로세스만 시작합니다).

이는 컨테이너의 시작과 종료를 복잡하게 만들 수 있습니다.

정리

결국, 여러 컨테이너를 사용하는 것은 각각의 컴포넌트를 독립적으로 운영하고 최적화할 수 있게 해주며, 전체 시스템을 더 안정적으로 만들어 줍니다. 이는 개발과 운영 모두에서 많은 이점을 제공합니다.

📒컨테이너 네트워킹

컨테이너 간의 네트워킹은 컨테이너들이 서로 통신할 수 있게 하는 중요한 기능입니다.

기본적으로 각 컨테이너는 독립적으로 실행되며, 다른 프로세스나 컨테이너들과는 별개로 작동합니다.

컨테이너가 서로 통신하려면 같은 네트워크에 있어야 합니다.

✔️컨테이너 네트워크에 연결하기

컨테이너를 네트워크에 연결하는 두 가지 방법이 있습니다.

1. 컨테이너 시작 시 네트워크 지정하기.

2. 이미 실행 중인 컨테이너를 네트워크에 연결하기.

여기서는 네트워크를 먼저 생성한 후에, MySQL 컨테이너를 시작할 때 해당 네트워크에 연결하도록 하겠습니다.

📌네트워크 생성하기

docker network create todo-app

📌MySQL 컨테이너 시작

MySQL 컨테이너를 생성하는데 사용될 몇 가지 환경 변수를 정의하면서, MySQL 컨테이너를 네트워크에 연결합니다.
MySQL 환경변수 참조

MySQL 시작하기

docker run -d \
   --network todo-app --network-alias mysql \
   -v todo-mysql-data:/var/lib/mysql \
   -e MYSQL_ROOT_PASSWORD=secret \
   -e MYSQL_DATABASE=todos \
   --name mysql \
   mysql:8.0
  • --network-alias
  • -v: /var/lib/mysql에 마운트된 todo-mysql-data라는 볼륨을 사용했습니다.(MySQL이 데이터를 저장하는 위치)

별도로 docker volume create 명령을 실행하지 않았지만 Docker는 명시된 이름의 볼륨을 자동으로 생성합니다.

DB 연결 확인

docker exec -it mysql mysql -u root -p
  • -i (또는 --interactive): 이 옵션은 컨테이너와 상호 작용(interactive)을 가능하게 합니다.
    즉, 표준 입력(STDIN)을 열어두어 사용자가 컨테이너의 쉘에 입력할 수 있도록 합니다. 이 옵션 없이 명령을 실행하면 사용자 입력이 무시될 수 있습니다.
  • -t (또는 --tty): 이 옵션은 명령어 실행에 터미널 할당(tty)을 추가합니다. -t 옵션은 컨테이너 내부에서 명령어를 실행할 때 텍스트 기반의 인터페이스를 제공하며, 명령어 실행 결과를 보기 좋게 표시하도록 도와줍니다. 특히, 쉘 접속이나 인터랙티브 콘솔 프로그램을 사용할 때 유용합니다.

결합하여 사용할 때, -it 플래그는 컨테이너 내에서 명령어를 마치 로컬 터미널에서 실행하는 것처럼 입력을 받고 결과를 출력할 수 있도록 해줍니다.

연결까지 확인을 마쳤습니다.

📌 네트워크 연결

MySQL은 이제 준비가 완료되었습니다. 이제 다른 컨테이너에서 MySQL 서버와 연결할 수 있어야 합니다.

같은 네트워크 상에 있는 다른 컨테이너가 MySQL 컨테이너를 어떻게 찾을 수 있을까요?

각 컨테이너는 고유의 IP 주소를 가지고 있는데 Docker 네트워크에서는 이름을 통해서 서로를 찾을 수 있습니다.

네트워킹을 확인하기 위해 nicolaka/netshoot 이미지를 사용하는 컨테이너를 사용하겠습니다.

nicolaka/netshoot 컨테이너 실행 및 ip 확인

docker run -it --network todo-app nicolaka/netshoot

dig mysql

ANSWER SECTION을 보면 mysql의 ip 주소가 172.23.0.2 A 레코드로 해석된 것을 볼 수 있습니다.

이 주소는 --network-alias 옵션으로 지정한 네트워크 별칭을 가진 컨테이너의 IP 주소입니다.

MySQL을 연결하기 위해서는 mysql이라는 호스트 이름을 사용해서 연결하면 됩니다. 이렇게 하면 애플리케이션이 MySQL 서버와 통신할 수 있게 됩니다.

📌애플리케이션과 MySQL 연결하여 실행하기

docker run -dp 127.0.0.1:3000:3000 \
 -w /app -v "$(pwd):/app" \
 --network todo-app \
 -e MYSQL_HOST=mysql \
 -e MYSQL_USER=root \
 -e MYSQL_PASSWORD=secret \
 -e MYSQL_DB=todos \
 node:18-alpine \
 sh -c "yarn install && yarn run dev"

앱과 MySQL을 연결하기 위해 환경 변수를 지정하여 주었습니다. 개발환경에서는 일반적으로 이렇게 사용하기는 하지만, 운영 환경에서는 이 방법을 추천하지 않습니다.

docker history 명령어 등으로 확인이 가능하기 때문에 보안적인 측면에서 좋지 않습니다.
(secret을 위해 환경 변수를 사용하지 말아야 하는 이유)

앱 잘 실행되었는지 확인

앱이 잘 실행되었는지 확인하고, 위와 같이 투두 리스트들을 추가해줬습니다.

MySQL 클라이언트로 MySQL 접속하여 데이터 잘 저장되었는지 확인

docker exec -it mysql mysql -p todos

한글로 입력한 건 깨진거 보니 table 설정이 utf-8이 아닌 듯 하지만 제대로 저장된 것 같으니 일단 넘어갑시다.

📒정리

하나의 컨테이너에서 여러 프로세스를 실행하는 것보다, 각각의 컨테이너에서 각 서비스를 실행하는 것이 좋은 선택입니다.

컨테이너들을 같은 네트워크에 묶어서 실행하면 ip 주소 대신 Host name(--network-alias로 지정한 이름)으로 참조할 수 있습니다.

https://docs.docker.com/network/
https://docs.docker.com/reference/cli/docker/

profile
백엔드 개발자

0개의 댓글