테스트 앱을 구축해가며 Docker Compose를 이해하고 활용해보기 (feat. Node.js, Redis, Dockerfile)

Bakumando·2022년 5월 14일
0

Docker

목록 보기
7/7
post-thumbnail

0. 블로깅 목적

  • Docker Compose를 정의하고, 테스트 앱 구축에 필요한 것을 파악한다.
  • 테스트 앱 구축을 위해 필요한 파일들을 작성하고 내부를 이해한다.
  • 테스트 앱을 실행하는 과정에서, Docker Compose의 필요성을 이해한다.
  • Docker Compose 실행 명령어로 멀티 컨테이너 통신을 구축하는 방법을 이해한다.
  • Docker Compose 중단 명령어 및 Docker Compose 명령어 옵션을 이해한다.

1. Docker Compose를 정의하고, 앱 구축을 위한 사전 준비를 진행해보자.

  • Docker compose란 다중 컨테이너 도커 애플리케이션을 정의하고 실행하기 위한 도구이다.
  • 정의만 봐서는 이해가 쉽지 않으므로 테스트 애플리케이션을 구축해가면서 파악해 갈 예정이다.
  • 테스트 앱은 node와 redis를 활용해 만들어볼 예정이다.
  • index.js에서 express를 활용하여 node.js 환경을 구축할 것이다.
  • node.js 환경에서 redis를 적용하기 위한 순서가 있다.
    1) docker를 이용해 redis 서버를 띄운다.
    2) 띄운 서버로부터 redis 모듈을 다운받는다.
    3) redis 클라이언트를 생성하기 위해 createClient() 메서드를 이용한다. 여기에서 redis 호스트와 포트를 세팅해 준다.
    4) node.js 앱에 만든 redis 클라이언트의 포트와, docker로 띄운 redis 서버의 포트를 매핑해준다.

  • 참고 1: redis란 무엇일까?
    • Redis(Remote Dictionary Server)는 메모리 기반의 키-값 구조 데이터 관리 시스템이며 딕셔너리 형식을 가지고 있다. 모든 데이터를 메모리에 캐싱하고 빠르게 조회할 수 있는 NoSql의 일종이다.
  • 참고 2: redis를 쓰는 이유는?
    • 메모리에 저장하기 때문에 Mysql 같은 RDBMS의 DB에 데이터를 저장하거나 혹은 조회할 때 훨씬 빠르게 처리할 수가 있으며, 비록 메모리에 저장하지만 영속적으로도 보관이 가능하다. 서버를 재부팅해도 데이터를 유지할 수 있다.
  • 참고 3: redis 호스트 설정은 어떻게 해야할까?
    • 보통 createClient() 시에, redis 서버의 기본 포트는 6379, 호스트는 https://redis-server.com 이기 때문에 이와 같이 세팅해주면 된다.
    • 허나 만약에 docker compose 및 이를 실행하기 위한 설정 값이 담긴 compose.yml파일을 사용할거라면, yml 파일에 설정한 redis 컨테이너 이름을 redis 클라이언트의 host명으로 적용해주면 된다. (포트는 6379로 동일하게 주면 됨)

2. node.js 테스트 앱 구축을 위한 파일들을 작성하고 분석해보자.

  • package.json 파일이다.
    • npm init을 활용하여 최대한 기본값으로 세팅해 보았다.
    • scripts에 start를 추가해주었다. (추후 Dockerfile에서 활용)

  • index.js 파일이다.
    • express, app 세팅을 하고 redis를 적용하였다. 그리고 get("/")요청 발생 시에 redis 및 view 업데이트를 위한 안배를 해두었다. 이에 대해선 추후 다시 살펴보겠다.

  • Dockerfile 이다.
    • 도커 이미지 생성하기 2편에서 봤던 Dockerfile과 동일하다. 각 키워드에 대한 자세한 설명은 해당 편을 참고하면 된다.

  • Docker-compose.yml 이다.
    • docker compose 명령어 사용시에 활용될 각종 설정 값이 세팅되어 있다.
    • docker compose는 depth 1에 version과 services를 기본이자 필수로 가져야 한다.
    • version의 설정값은 자유롭게 적용할 수 있다.
    • services는 멀티 컨테이너를 감쌀 수 있는 상위 박스라고 생각하면 된다. services 하위에 서로 통신이 가능하게 하고 싶은 컨테이너들을 명시해주면 되는 것이다.
      • redis-server 컨테이너의 하위엔 image가 있는데, image는 컨테이너에서 사용하는 베이스 이미지를 뜻한다.
      • node-app 컨테이너의 하위엔 우선 build가 있는데, 여기엔 Dockerfile이 어디에 있는지 그 경로를 나타내면 된다. 만약 현재 디렉토리에 있다면 ./ 으로 표현해주면 된다. 그 다음 ports가 있는데, 이는 포트 맵핑을 위한 것이다. {로컬 포트}:{컨테이너 포트} 순으로 지정하여 표현해주면 된다.

  • 참고 1: yml은 무엇일까?
    • yml(yaml)은 ain't markup language의 약자이다.
    • 일반적으로 구성 파일 및 데이터가 저장되거나 전송되는 응용 프로그램에서 사용되고, 원래는 XML이나 json 포맷으로 많이 쓰였지만 좀 더 사람이 읽기 쉬운 포맷으로 탄생한 게 yaml이라 할 수 있다.
    • 그리고 yml파일은 외부에서 import를 해서 활용할 수도 있는데, 각 depth는 .(dot)체이닝으로 이어져있어서 js객체를 접근하듯 사용할 수 있다.

3. node.js 테스트 앱 실행을 실패하는 과정에서, Docker compose의 필요성을 이해해보자.

$ docker run redis
$ docker build -t bakumando/docker-compose-app ./
$ docker run -p 4000:8080 bakumando/docker-compose-app
  • node.js 앱을 실행하기 위해서 우선 띄워줘야 하는 서버가 있는데, redis 서버이다. docker를 통해 실행하면 된다.
  • 터미널에서 docker run redis를 입력하였다.
    • redis 서버 컨테이너가 가동되었다.

  • docker build -t bakumando/docker-compose-app ./ 를 입력하였다.
    • Dockekfile을 토대로 최초의 빌드가 이루어진 것이다. 이는 곧 사전에 준비해 둔 node.js 앱 관련 파일들을 토대로, 새로운 이미지를 생성하는 것을 의미한다.

  • docker run -p 4000:8080 bakumando/docker-compose-app 를 입력하였다.
    • redis server 접근에 실패했다는 에러가 발생했다.
    • 현재 node 앱의 index.js에는 redis 서버 연결을 위한 로직이 존재하고 있는데, 여기에서 에러가 터졌음을 알 수 있다.
    • 왜 에러가 일어났을까?
      • node.js 서버와 redis 서버가 서로 다른 docker 컨테이너로 이루어져 있기 때문이다.
      • 즉, 아무런 설정 없이 서로 다른 컨테이너는 각각에 접근할 수 없다는 것이다.
    • 어떻게 서로 다른 컨테이너 사이에 통신을 가능하게 할 수 있을까?
      • 바로 Docker Compose가 그 해답이 된다.
      • Docker Compose는 멀티 컨테이너 상황에서 쉽게 네트워크를 연결시켜주는 역할을 해준다!

4. Docker Compose 기본 명령어로 멀티 컨테이너 통신을 구축하는 방법을 이해한다.

$ docker-compose up
  • 앞서 살펴보았듯, 도커 컨테이너는 기본적으로 독립적인 영역을 가지기 때문에 각각 띄우면 서로 간의 통신이 불가능하다.
  • docker-compose는 멀티 컨테이너를 하나의 박스로 감싸 같은 유니버스(?)를 공유할 수 있게 해주기 때문에, 컨테이너 간의 통신이 가능해진다.
  • 이미 위에서 docker-compose.yml 파일에 node.js 앱과 redis 서버를 하나의 유니버스로 감싸주었다는 것을 확인하였다.

곧장 실습을 통해 확인해보자.

  • 명령어는 간단하다.
  • docker-compose up만 입력하면 된다.
    • Creating... 부분에서 각 컨테이너가 성공적으로 생성되었음을 알 수 있다.
    • redis-server_1의 Redis is starting 부분에서 redis 서버가 실행되고 그 아래로 각종 세팅이 완료되었다.
    • node-app_1의 서버 가동 부분에서 node.js 앱 실행이 완료되었다.
    • 그리고 간혹 캡쳐에 명령어 실행경로를 포함시키지 않았던 것도 있어서 노파심에 언급하자면, 당연히 docker-compose 및 Dockerfile을 활용한 이미지 생성 및 컨테이너 생성, 실행 등의 명령어는 관련 파일이 존재하는 경로에서 이루어져야 한다.

  • 실제로 앱이 잘 실행되는지 로컬 4000으로 접속해보자.
    • 문제 없이 접속이 이루어진다.

  • 새로고침을 4차례 진행해보자.
    • 이를 통해 redis 서버도 정상 동작함을 알 수 있다.

5. Docker Compose 중단 명령어 및 Docker Compose 명령어 옵션을 이해한다.

$ docker-compose down
$ docker-compose up -d
$ docker-compose up --build
  • Docker Compose 중단 명령어을 사용해보자.
  • docker-compose down으로 중단이 가능하다.
    • 컨테이너 중단 및 삭제를 모두 진행해준다.

바로 실습을 통해 확인해보자.

  • 터미널 두개를 준비한다.
    • 1번 터미널: docker-compose up을 실행한다.
      • redis, node.js가 컨테이너 둘다 create 및 start 되었다.

    • 2번 터미널: docker-compose down을 실행한다.
      • redis, node.js 컨테이너가 둘다 stop 및 remove되었다.

    • docker-compose down을 진행하면 1번 터미널 상태도 변화한다.
      • redis 컨테이너가 먼저 종료되면서 node 컨테이너에 에러가 발생하고, 그다음 node 컨테이너도 종료된다.
  • 솔직히 근데 터미널을 두개 켜야한다는 점은 불편한 부분일 수 있다.
  • -d 옵션 (detach 옵션)으로 백그라운드에서 컨테이너 실행을 시키고 터미널로 빠져나오면 하나의 터미널에서 up down을 모두 수행할 수 있다.
  • docker-compose up -d 형식으로 사용하면 된다.

역시 실습을 통해 확인하자.

  • 하나의 터미널에서 docker-compose up -d을 입력하였다.
    • 서버 실행만 하고 바로 빠져나왔다는 걸 확인할 수 있다.

  • 확인 사살을 위해 docker ps도 입력해보았다.
    • 아주 잘 실행 중이다.
  • docker-compose up은 이미지가 없을때만 이미지를 빌드하고 컨테이너를 시작한다.
  • docker-compose up --build는 이미지가 있든 없든 다시 이미지를 빌드하고 컨테이너를 시작한다.
  • 즉, 만약 따로 앱에 변동이 없는 상태라면 docker-compose up이 적합하겠으나, 앱에 주요한 변동이 있어 이미지를 다시 빌드해야 하는 상태라면 docker-compose up --build를 사용해야 변동사항이 반영될 수 있다.

직접 확인을 통해 비교해보자.

  • docker-compose up
    • 이미지가 있기 때문에 따로 빌드 과정이 없다.

  • docker-compose up --build
    • 이미지가 있든 없든 무조건 빌드 과정이 있다.
    • 여기에도 -d 옵션을 주면 컨테이너 띄우고 바로 터미널로 빠져나올 수 있다. 아래처럼 입력하면 된다.
    • docker-compose up --build -d (예시는 생략한다.)

  • 참고 1: docker-compose.yml 파일에 docker volume 옵션을 넣을 수 있을까?
    • 물론 가능하다. 그럼 앱의 소스 코드 변경이 있더라도 --build를 활용한 재빌드도 필요 없을 수 있다.
    • 허나 모든 상황에서 적용되는 것은 아니다. 가령 앱의 중요한 환경 설정의 변동으로 npm install을 다시 수행해야 한다던가, docker-compose.yml 파일 자체를 잘못 작성했다던가 하는 문제가 있다면, volume 옵션 만으로는 해결이 불가능하기 때문에 docker-compose up --build를 수행해야 한다.
profile
그렇게 바쿠만도는 개발에 퐁당 빠지고 말았답니다.

0개의 댓글