터칭 데이터

Docker-Compose로 다수의 Container 프로그램 실행하기 (실습 개요) 본문

Docker & K8S

Docker-Compose로 다수의 Container 프로그램 실행하기 (실습 개요)

터칭 데이터 2023. 12. 21. 16:01

 

 

앞서 매뉴얼하게 실행해본 voting application를 docker-compose를 통해 실행해보자

 

1. Docker 명령 정리와 2장 퀴즈


2. Docker Volume이란?


3. 다수의 Container로 구성된 소프트웨어 실행


4. Docker-Compose로 다수 Container로 실행해보기


5. Airflow Docker docker-compose.yml 리뷰

 

지난 시간 voting application을 메뉴얼하게 구성하는 실습으로 1~3번을 진행했습니다.

 

이번에는 같은 프로그램을 docker-compose 방식으로 실습하며 4번 과정을 진행하겠습니다.

 

바로 이전 게시물에서 Docker-compose 개념을 익혔으니 이제 실습을 해보려 합니다. 그전에 실습의 개요를 설명드리겠습니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

Voting application을 docker-compose 실행 실습 개요

 

 

 

 

 

 

앞서 5개의 Container를 일일히 실행했을 때의 문제점

 

Postgres를 실행하는 부분이 제대로 동작하지 않았음

docker run -d --name=db -e POSTGRES_PASSWORD=password --network mynetwork postgres

 

 

 

메뉴얼 실습을 끝내고 Dogs나 Cats에 투표를 해도 결과창에서는 계속 50:50으로 조회되었습니다.

 

 

 

 

그 이유는 Worker가 redis에 기록된 투표 결과를 postgres에 적어줘야 하는데

 

 

 

worker/Program.cs (cs는 C#의 확장자) 파일을 살펴보면

var pgsql = OpenDbConnection("Server=db;Username=postgres;Password=postgres;");
var redisConn = OpenRedisConnection("redis");

 

아래 명령어로 postgres 이미지 db를 빌드할 때 호스트 이름은 db로 제대로 주었지만 

docker run -d --name=db -e POSTGRES_PASSWORD=password --network mynetwork postgres

 

패스워드를 password로 주었기 때문에 posgres와 일치하지도 않고 Username도 주지 않았기 때문입니다.

당연히 OpenDBConnection이 제대로 작동하지 않았을테고 결과가 제대로 반영되지 않았을 겁니다.

 

 

 

이를 해결하려면 Container를 실행할 때 아래 2개의 환경변수를 넘겨주어야 함

POSTGRES_USER: "postgres"
POSTGRES_PASSWORD: "postgres" (passwor라는 패스워드 대신)
이걸 docker-compose 환경 설정 파일을 통해 넘기면서 해결해볼 예정

 

 

 

 

 

 

 

 

 

 

 

 

docker-compose.yml로 포팅: 뼈대

 

지난 시간 메뉴얼하게 voting application을 실습할 때 아래 5개의 명령어를 사용했었습니다.

 

docker run -d --name=redis --network mynetwork redis

 

docker run -d --name=db -e POSTGRES_PASSWORD=password --network mynetwork postgres

앞서 컨테이너를 하나씩 실행할 때 이 부분은 제대로 동작하지 않았습니다.

 

docker run -d --name=vote -p 5001:80 --network mynetwork vote

 

docker run -d --name=result -p 5002:80 --network mynetwork result

 

docker run -d --name=worker --network mynetwork worker

 

 

 

 

 

 

위의 명령어들을 docker-compose.ymldocker-compose up을 사용하여

 

 

위의 이미지와 같이 보완할 겁니다.

 

일단 networks와 volumes를 처음에는 쓰지 않을겁니다. volumes를 쓰지 않으니 Data persistency는 보장되지 않고 networks는 docker-compose에서 기본으로 주어지는 default 네트워크를 쓰게될겁니다.

 

이렇게 처음 실습한 후 조금씩 난이도를 높여가며 yaml파일의 섹션들을 더 자세히 살펴보고 기능 구현을 해보겠습니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

docker-compose.yml로 포팅: services 키 보기

yml 파일의 services 섹션을 살펴보겠습니다.

 

수정할 yml 파일의 services 섹션

redis:
  image: redis:alpine
db:
  image: postgres:15-alpine
vote:
  image: vote
  ports:
    - 5001:80
result:
  image: result
  ports:
    - 5002:80
worker:
  image: worker

 

 

 

수정이 된 docker-compose.mac.yml 의 services 섹션

redis:
  image: redis:alpine
db:
  image: postgres:15-alpine
vote:
  build: ./vote
  ports:
    - 5001:80
result:
  build: ./result
  ports:
    - 5002:80
worker:
  build: ./worker

 

image는 로컬에 이미 빌드된 Docker Image가 존재하지 않으면 Docker Hub에서 이미 빌드된 이미지를 pull로 다운 받고 빌드하겠다는 뜻입니다.

 

우리가 지난 voting application에서 살펴보았을 때 vote, result, worker 디렉토리의 아래에 Dockerfile이 존재했던 것을 기억하실겁니다. 그리고 Dockerfile로 이미지를 생성(빌드)했었죠? 그래서 image:를 build:로 고쳐 ./vote(result or worker) 아래의 Dockerfile을 읽도록 수정합니다.

 

Image와 build의 차이점을 상기시키기 위해 별도의 장으로 구성해 설명드렸습니다. 꼭 기억해주세요.

 

 

 

이미지로 표현

좌측이 수정전, 우측이 수정된 docker-compose.mac.yml입니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

최종 docker-compose.mac.yml의 내용


https://github.com/learndataeng/example-voting-app/blob/main/docker-compose.mac.yml

 

# v2 and v3 are now combined!
# docker-compose v1.27+ required
# % docker-compose version
# Docker Compose version v2.15.1
services:
  vote:
    build: ./vote
    # use python rather than gunicorn for local dev
    command: python app.py
    ports:
      - "5001:80"

  result:
    build: ./result
    # use nodemon rather than node for local dev
    entrypoint: nodemon server.js
    ports:
      - "5002:80"

  worker:
    build: ./worker

  redis:
    image: redis:alpine

  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: "postgres"
      POSTGRES_PASSWORD: "postgres"

 

build와 ports는 똑같은데 command가 있네요? 뒤에서 설명 드리겠지만

 

vote 디렉토리에 존재하는 Dockerfile에 적힌 

 

(생략..)
FROM base AS dev
RUN pip install watchdog
ENV FLASK_ENV=development
CMD ["python", "app.py"]
(생략..)

 

CMD의 내용을 docker-compose를 이용해 오버라이드(override)할 때 사용합니다.

즉 Dockerfile 내부에 있는 'CMD' 명령보다 docker-compose.yml 파일에 있는 'command:' 명령이 더 우선시 됩니다.

 

result에 적힌 entrypoint도 똑같은 맥락으로 override로 이해하시면 됩니다.

 

db에서 image:만 지정하지 않고 postgres_user와 postgres_password를 세팅했습니다.

그래야 위의 흐름도대로 Worker가 아래의 파일에서 코드대로 db와 연결되어 

 

worker/Program.cs (cs는 C#의 확장자)

var pgsql = OpenDbConnection("Server=db;Username=postgres;Password=postgres;");
var redisConn = OpenRedisConnection("redis");

 

PostgreSQL와 잘 연결 및 작동되기 때문입니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

데모(실습)

 

git clone https://github.com/learndataeng/example-voting-app.git

주의) https://github.com/dockersamples/example-voting-app 와는 다른 repo입니다.

위는 example-voting-app의 원본이고 우리가 데모를 진행할 repo는 원본을 fork한 멘토님의 repo입니다.

 

cd example-voting-app

 

먼저 청소 한번 하기

docker container rm -f $(docker container ls -aq)
docker image rm -f $(docker image ls -q)

 

확인해보기

docker ps -a
docker images

 

그리고나서 앞의 docker-compose.mac.yml의 내용을 바탕으로 실행해보기