Docker compose의 네트워크부터 실습까지

hyeongjun Jo·2023년 5월 4일
2

DevOps

목록 보기
6/11
post-thumbnail

목표

  • docker compose의 use case
  • docker network의 복습
  • docker compose가 사용하는 docker network를 알아보고
  • 실제 여러 컨테이너가 통신할 수 있는 환경을 구축해본다.

Docker compose

이번 포스트는 docker compose입니다. docker compose는 무엇이고 어떨 때 쓰일까요?
Docker Compose 는 다중 컨테이너 애플리케이션을 정의 공유할 수 있도록 개발된 도구로 단일 명령을 사용하여 모두 실행 또는 종료할 수 있도록 개발된 도구입니다.
도커 컴포즈는 이럴 때 쓰입니다.

개발 환경의 표준화

팀 구성원이 규칙대로 개발 환경을 수동으로 정비하면 시간이 걸릴뿐만 아니라 수작업 실수를 유발할 가능성이 있습니다. Docker Compose를 사용하여 설정 파일을 전달하면, 개발 환경의 세부 사항을 걱정하지 않고 하나의 명령으로 환경을 정비 할 수 있습니다. 이로 개발 환경 정비 작업을 간소화 할 수 있습니다.

테스트 환경의 자동화

CI(Continuous Integration)와 CD(Continuous Deployment)를 할 경우, end to end 테스트(모든 구성 요소를 결합하여 테스트)를 자동화하려면 이상적으로는 테스트마다 독립적인 테스트 환경을 제공 해야 합니다. Docker Compose를 사용하면 필요한 테스트 환경을 명령어 1개로 시작할 수 있으며, 검사가 완료되면 쉽게 파기할 수도 있습니다.

단일 호스트 배포

운영 환경이 단일 서버의 경우 Docker Compose를 사용하여 배포 할 수 있습니다.
그러나 응용 프로그램을 확장하기 위해 다중 노드에 배포하려면 일반적으로 Docker Engine의 Swarm mode 라는 기능 또는 K8S, AWS ECS 와 Google Container Engine과 같은 클라우드 클러스터 매니저가 더 적합합니다.

Docker network 복습

이전 포스트에 docker의 네트워크를 공부해보았습니다. 기억이 안나시는 분은 여기를 참고해주시기 바랍니다.
짧게 복습하자면 Default 네트워크인 Bridge 네트워크를 사용하게 되면 그림과 같이 네트워크가 구성되게 됩니다.

그림은 두 개의 컨테이너가 네트워크에 소속되어 있는 모습이고 임의로 컨테이너를 네트워크에 연결하기 위해서는
docker network connect NETWORK CONTAINER 명령을 사용할 수 있습니다.
그러면 해당 네트워크가 가진 private한 IP 대역의 IP중 하나를 container가 할당받습니다.

컨테이너 간 통신

이번에는 같은 도커 네트워크에 속한 컨테이너들의 통신을 살펴보겠습니다.

busybox 이미지로 A 컨테이너와 B 컨테이너를 생성합니다.

busybox는 Linux 환경에서 경량화된 유틸리티 도구 모음인 BusyBox 프로젝트에서 파생된 이미지로, 최소한의 도구만을 갖추고 있습니다. busybox 이미지는 디버깅이나 테스트, 간단한 기능의 실행을 위해 사용될 수 있습니다. busybox는 다른 이미지의 기반이 되는 미니멀한 운영체제 이미지를 만들 때도 자주 사용됩니다.

기본적으로 default network를 사용하므로 connect 명령어를 사용할 필요는 없습니다.
docker network ls로 네트워크 이름을 확인하고
docker network inspect bridge로 상세정보를 확인가능합니다.

같은 네트워크에서는 컨테이너간 통신에서 ip로 접근이 가능합니다.

Docker compose의 network

docker compose의 link기능은 version 2부터 deprecated 되었습니다.

default 네트워크

docker compose는 기본적으로 default 네트워크를 생성하고 모든 컨테이너를 연결하는데 그 이름은 docker-compose.yaml이 존재하는 폴더명 + _default입니다.

이외에도 사용자지정 네트워크를 지정할 수 있습니다

docker-compose.yaml

version: '3'
services:
  web:
    image: nginx:latest
    ports:
      - "8000:80"
    networks:
      - default
      - our_net

  db:
    image: postgres
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres

networks: # 네트워크 지정
  our_net:
   # driver: bridge                   

docker compose up

docker network들을 생성합니다

db 컨테이너는 default 네트워크에만 자동으로 연결되지만 web 컨테이너는 default와 our_net 네트워크 둘 다 연결됩니다.

default network
172.22.0.0/16 대역

our-net
172.23.0.0/16 대역

default 네트워크를 docker-compose 외부에서 설정한 네트워크로 설정할 수도 있습니다.

version: '3'
services:
  web:
    image: nginx:latest
    ports:
      - "8000:80"

  db:
    image: postgres
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres

networks:
  default:
    external:
      out_net # 외부 네트워크 설정

이렇게 진행하면 docker compose down 시에도 외부 네트워크는 삭제되지 않습니다.

Docker compose 실습

이번에는 docker compose로 여러 컨테이너들을 띄우고 네트워크를 이용해 서로 통신을 하는 실습을 진행하겠습니다.

여러 컨테이너로 실습하기 위해 voting app을 선택하였습니다.

해당 깃허브 레포지토리에 자세히 나와있지만 그림과 함께 간략히 설명하자면

  • voting-app
    • 사용자에게 투표를 촉구하는 Web 페이지를 표시하는 응용 프로그램.
    • 데이터는 redis에 저장한다.
    • Python과 Flask에 따르는 Web 응용 프로그램
  • redis
    • 투표 결과를 임시로 저장 캐시.
    • Redis
  • worker
    • 투표 결과를 가져오고 Postgres 데이터베이스에 저장하는 작업자.
    • .NET
  • db
    • 투표 결과를 저장하는 데이터베이스. 데이터는 Docker volume 보관한다.
    • Postgres
  • result-app
    • 실시간 투표 결과를 표시하는 Web 응용 프로그램.
    • Node.js

docker-compose.yml

version: "3"

services:
  vote:
    build: ./vote
    command: python app.py
    volumes:
     - ./vote:/app
    ports:
      - "5000:80"
    networks:
      - front-tier
      - back-tier

  result:
    build: ./result
    command: nodemon --debug server.js
    volumes:
      - ./result:/app
    ports:
      - "5001:80"
      - "5858:5858"
    networks:
      - front-tier
      - back-tier

  worker:
    build:
      context: ./worker
    networks:
      - back-tier

  redis:
    image: redis:alpine
    container_name: redis
    ports: ["6379"]
    networks:
      - back-tier

  db:
    image: postgres:9.4
    container_name: db
    volumes:
      - "db-data:/var/lib/postgresql/data"
    networks:
      - back-tier

volumes:
  db-data:

networks:
  front-tier:
  back-tier:
  

해당 docker-compose.yaml은 front-tier와 back-tier 두 개의 네트워크를 사용합니다.

열려있는 포트번호 확인
sudo lsof -PiTCP -sTCP:LISTEN

docker compse up으로 docker-compose.yaml에 작성된 이미지들을 띄워 봅시다.

애플리케이션이 잘 작동하는 것을 확인할 수 있습니다.

docker compose down을 이용해 하나의 명령어로 모든 컨테이너를 중지시킬 수 있습니다.

Plus

Docker Compose의 Health check

docker의 기능 중에는 Health check 기능도 있는데 이는 Docker compose에도 또한 지원됩니다.

docker-compose의 version 2부터는 depends on과 health check 기능이 추가되었는데 그 내용을 간략히 살펴보겠습니다.

healthcheck: 
      test: ["CMD", "curl", "-f", "http://localhost"]
      interval: 15s
      timeout: 5s
      retries: 3
      start_period: 10s

test - 컨테이너를 테스트하는 데 사용됩니다. 이를 위해 curl 명령을 사용하여 호스트로부터 응답이나 신호를 받았습니다.

curl 명령의 -f 옵션이 궁금해서 찾아보았습니다. man curl
(HTTP) 서버 오류가 전혀 출력되지 않고 빠르게 실패합니다. 이것은 스크립트와 사용자가 실패한 시도를 더 잘 처리할 수 있도록 하는 데 유용합니다. HTTP 서버가 문서 전달에 실패하는 일반적인 경우에는 이를 알리는 HTML 문서를 반환합니다(종종 이유 등을 설명하기도 함). 이 플래그는 컬이 출력하는 것을 방지하고 오류 22를 반환합니다. 이 방법은 절대 안전하지 않으며 특히 인증이 관련된 경우(응답 코드 401 및 407) 성공하지 못한 응답 코드가 빠져나가는 경우가 있습니다.

interval - healthcheck 프로세스가 실행되는 기간 또는 간격을 지정합니다.
timeout - 상태 확인을 기다리는 시간을 정의합니다. 오류 또는 비정상적인 조건의 경우 지정된 시간이 지나면 종료 코드를 반환합니다.
retries - 실패 후 상태 확인을 구현하기 위한 시도 횟수를 정의하는 데 사용됩니다.
start_period - 시작 기간은 부트스트랩 시간이 필요한 컨테이너의 초기화 시간을 제공합니다. 해당 기간 동안의 프로브 실패는 최대 재시도 횟수에 포함되지 않습니다. 그러나 시작 기간 동안 상태 확인이 성공하면 컨테이너가 시작된 것으로 간주되며 모든 연속 실패는 최대 재시도 횟수에 포함됩니다.

health check를 설정했다면 depends_on:condition: service_healthy를 작성가능 합니다.

이는 종속된 service를 시작하고 health check를 마친 후 의존된 서비스를 실행한다는 얘기입니다.

예시

services:
  web:
    build: .
    depends_on:
      db:
        condition: service_healthy
        restart: true
      redis:
        condition: service_started
  redis:
    image: redis
  db:
    image: postgres

참고

profile
DevOps Engineer

1개의 댓글

comment-user-thumbnail
2023년 11월 8일

깃허브에서 그대로 클론하셨나요? 저는 깃허브에서 그대로 클론했는데 container is unhealthy 오류가 발생했습니다...

답글 달기