[DevOps] MS 공식문서로 이해하는 Docker - 6 다중 컨테이너 앱

Song-YunMin·2021년 6월 3일
1

DevOps

목록 보기
8/9

본 내용은 Microsoft에서 제공하는 Docker 자습서 내용을 정리한 글입니다.
원문과 내용이 비슷하지만, Docker를 접하기에 아주 유용한 문서로 개인 학습 및 정보공유 차원에서 작성합니다.

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

“MySQL은 어디서 실행되나요? 같은 컨테이너에 설치하나요, 아니면 별도로 실행하나요?”라는 질문을 받는 경우가 많습니다.

일반적으로 각 컨테이너에서 한 가지 작업을 잘 수행하는 것이 좋습니다. 다음과 같은 몇 가지 이유가 있습니다.

  • API와 프런트 엔드의 크기를 데이터베이스와 다르게 스케일링해야 할 가능성이 있습니다.
  • 개별 컨테이너를 사용하면 격리된 상태로 버전을 관리하고 업데이트할 수 있습니다.
  • 로컬에서는 데이터베이스에 컨테이너를 사용할 수 있지만, 프로덕션 환경에서는 데이터베이스에 관리형 서비스를 사용하는 것이 좋습니다. 그러면 앱과 함께 데이터베이스 엔진을 제공하지 않아도 됩니다.
  • 여러 프로세스를 실행하는 경우 프로세스 관리자가 필요하며(컨테이너는 하나의 프로세스만 시작함), 컨테이너 시작/종료가 복잡해집니다.

그 밖에 다른 이유도 있습니다. 따라서 애플리케이션을 다음과 같이 업데이트 하겠습니다.

Container Networking

  • 기본적으로 컨테이너는 격리된 상태로 실행됨 (다른 프로세스, 컨테이너에 대해 모름)
  • 컨테이너 간 통신을 하려면 네트워킹을 해야 함
  • 두 컨테이너가 같은 네트워크에 있으면 서로 통신할 수 있음

MySQL 시작

  • 네트워크에 컨테이너를 배치하는 방법에는 두 가지가 있음
  • 시작할 떄 할당하거나, 기존 컨테이너를 연결하는 것
  • 지금은 먼저 네트워크를 만든 다음, 시작 시 MySQL 컨테이너를 연결 함
  1. 네트워크 생성

    $ docker network create todo-app
  2. MySQL 컨테이너를 시작하고 네트워크에 연결함, 또한 DB를 초기화 하는데 사용할 몇 개의 환경 변수를 정의함

    $ 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 \
        mysql:5.7

    --network-ailas 플래그도 지정 함, 잠시후에 설명 함

    여기서는 todo-mysql-data 라는 볼륨 이름을 사용하고, MySQL에서 데이터를 저장하는 위치인 /var/lib/mysql 에 볼륨을 탑재합니다. 그러나 docker volume create 명령을 실행한 적은 없습니다. Docker에서 명명된 볼륨을 사용하려는 의도를 인식하고 자동으로 볼륨을 만듭니다.

  3. 데이터베이스가 시작되어 실행되고 있는지 확인하려면 데이터베이스에 연결하여 연결 상태를 확인함

$ docker exec -it <mysql-container-id> mysql -p

암호 프롬프트가 표시되면 secret을 입력합니다. MySQL 셀에서 데이터베이스 목록을 표시하고 todos 데이터베이스가 표시되는지 확인합니다.

MySQL에 연결

  • 같은 네트워크에서 다른 컨테이너를 실행하는 경우 컨테이너를 찾는 방법을 파악하기 위해 '많은' 도구가 포함된 nicolaka/netshoot 컨테이너를 사용함.
  1. nicolaka/netshoot 이미지를 사용하여 새 컨테이너를 시작, 같은 네트워크에 컨테이너를 연결해야 함

    $ docker run -it --network todo-app nicolaka/netshoot
  2. 컨테이너 내에서 유용한 DNS 도구인 dig 명령을 사용함, Host이름 mysql 의 IP 주소를 조회

    $ dig mysql

    아래와 같은 출력이 표시 됨

    ; <<>> DiG 9.14.1 <<>> mysql
    ;; global options: +cmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32162
    ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
    
    ;; QUESTION SECTION:
    ;mysql.             IN  A
    
    ;; ANSWER SECTION:
    mysql.          600 IN  A   172.23.0.2
    
    ;; Query time: 0 msec
    ;; SERVER: 127.0.0.11#53(127.0.0.11)
    ;; WHEN: Tue Oct 01 23:47:24 UTC 2019
    ;; MSG SIZE  rcvd: 44

    “ANSWER SECTION”에서 mysql에 대해 A 레코드가 표시되며, 172.23.0.2로 확인됩니다(사용자 IP 주소는 다른 값일 가능성이 높음). mysql는 일반적으로 유효한 호스트 이름이 아니지만, Docker에서 해당 네트워크 별칭을 가진 컨테이너의 IP 주소로 확인할 수 있었습니다(앞에서 사용한 --network-alias 플래그 참조).

    따라서 앱이 mysql이라는 호스트에 연결하기만 하면 데이터베이스와 통신할 수 있습니다. 매우 간단합니다.

MySQL을 사용하여 앱 실행

todo 앱에서 몇 개의 환경 변수를 설정하여 MySQL 연결 설정을 지정할 수 있습니다. 관련 토폴로지는 아래와 같습니다.

  • MYSQL_HOST - 실행 중인 MySQL 서버의 호스트 이름
  • MYSQL_USER - 연결에 사용할 사용자 이름
  • MYSQL_PASSWORD - 연결에 사용할 암호
  • MYSQL_DB - 연결된 후 사용할 데이터베이스

이제 개발 환경용 컨테이너를 시작합니다.

  1. 위에서 언급한 각 환경 변수를 지정하고 컨테이너를 앱 네트워크에 연결

    $ docker run -dp 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:12-alpine \
      sh -c "yarn install && yarn run dev"
  2. 컨테이너에 대한 로그(docker logs <container-id>) 를 살펴보면 MySQL 데이터 베이스를 사용하고 있음을 나타내는 메시지를 볼 수 있습니다.

    # Previous log messages omitted
    $ nodemon src/index.js
    [nodemon] 1.19.2
    [nodemon] to restart at any time, enter `rs`
    [nodemon] watching dir(s): *.*
    [nodemon] starting `node src/index.js`
    Connected to mysql db at host mysql
    Listening on port 3000
  3. 브라우저에서 앱을 열고 todo 목록에 몇 개의 항목을 추가합니다.

  4. MySQL 데이터베이스에 연결하여 데이터베이스에 항목이 기록되고 있음을 증명합니다. 암호는 secret 입니다.

    $ docker exec -ti <mysql-container-id> mysql -p todos

    MySQL 셸에서 다음을 실행합니다.

    mysql> select * from todo_items;
    +--------------------------------------+--------------------+-----------+
    | id                                   | name               | completed |
    +--------------------------------------+--------------------+-----------+
    | c906ff08-60e6-44e6-8f49-ed56a0853e85 | Do amazing things! |         0 |
    | 2912a79e-8486-4bc3-a4c5-460793a575ab | Be awesome!        |         0 |
    +--------------------------------------+--------------------+-----------+

    사용자 테이블은 해당 항목을 포함하므로 다르게 표시될 것입니다. 그러나 항목이 테이블에 저장된 것은 확인할 수 있습니다.

IDE 에서 제공하는 Docker 확장을 살펴보면 앱 컨테이너 두개가 같이 실행되는 것을 확인할 수 있습니다.

profile
고독한 서버 개발 3년차

0개의 댓글