[Docker] Docker Compose로 다중 컨테이너 배포 (1) - 도입 배경과 핵심 개념

1. 도입배경

  • Docker를 이용해 프로젝트 개발 중, 여러 컨테이너를 개별적으로 관리하는것이 비효율적이고 불편하다고 느꼈습니다.
  • Docker Compose는 이러한 문제를 해결해주는 도구로, 여러 컨테이너를 하나의 docker-compose.yml 파일로 정의하고, 이를 통해 일괄적으로 관리할 수 있는 도구입니다.
  • Docker Compose를 사용하면 한 번의 명령으로 여러 서비스를 동시에 실행하거나 중지할 수 있어, 개발 및 운영 환경에서의 복잡한 작업을 간소화할 수 있습니다.
  • 현재 프로젝트에서는 프론트엔드 서버(Nginx), 백엔드 서버(Spring Boot), 캐시 서버(Redis) 등 여러 컨테이너가 함께 운영되어야 합니다. 이처럼 다양한 서비스를 효율적으로 관리하기 위해 Docker Compose를 도입하였습니다.

2. Docker Compose

1) Docker와 무엇이 다른가?

Docker

  • 애플리케이션을 컨테이너라는 격리된 환경에서 실행할 수 있게 하는 도구입니다.
  • 이미지 기반의 컨테이너 실행, 배포 및 관리에 중점을 둡니다.
  • 리눅스 기반 도구입니다.
  • Docker CLI 명령어를 사용해 단일 컨테이너를 실행하거나 관리하는 데 유용합니다.

Docker Compose

  • 다중 컨테이너 를 빌드, 실행하기 위한 도구입니다.
  • WAS, RDBMS, Redis 등 다중 컨테이너로 구성된 애플리케이션에서 사용됩니다.
  • 단일 docker-compose.yml 파일을 통해 모든 컨테이너를 구성하고, 실행 순서나 의존성을 편리하게 정의할 수 있습니다.

2) Docker Compose 도입하는 이유

다중 컨테이너 관리

  • Docker Compose는 여러 개의 컨테이너를 단일 명령어로 실행하고 중지할 수 있어 복잡한 애플리케이션을 쉽게 관리할 수 있습니다. 예를 들어 docker-compose up이나 docker-compose down 명령어로 모든 컨테이너를 제어할 수 있습니다.
  • 현재 프로젝트에서 Nginx, BackEnd, Redis 등의 다양한 애플리케이션을 함께 운영해야 하므로, Docker Compose 로 손쉽게 다중컨테이너를 관리하도록 설계했습니다.

네트워크 설정

  • Docker Compose는 네트워크 구성을 단순화하여, 여러 컨테이너 간의 통신을 쉽게 할 수 있습니다.
  • 현재 프로젝트에선 Nginx (vue,js 파일 서빙, 리버스프록시), BackEnd Server, Redis 각 애플리케이션 통신을 Docker Compose 네트워크 내에서 원활히 연결할 수 있어 각 애플리케이션이 안정적으로 통신 하도록 설계하였습니다.

컨테이너 실행 순서 설정

  • 일부 애플리케이션은 특정 컨테이너가 먼저 실행된 후 다른 컨테이너가 구동되어야 합니다. 예를 들어, 데이터베이스가 구동된 후 백엔드 서버가 연결되도록 하는 것이 필요할 수 있습니다.
  • Docker Compose는 depends_on 옵션을 통해 이와 같은 실행 순서를 지정할 수 있습니다.
  • 현재 프로젝트에서는 이를 통해 BackEnd 서버가 Redis 서버(세션,캐시 서버)에 문제없이 접근할 수 있도록 Redis 서버를 우선 실행 시켰습니다.

환경변수 관리

  • Docker Compose는 환경변수 파일을 통해 손쉽게 변수를 전달할 수 있습니다. 이를 통해 개발과 운영 환경에 따라 설정을 분리하거나, 민감한 정보를 환경변수로 주입할 수 있습니다.
  • 현재 프로젝트에서 Naver OAuth2 제공자 정보, AWS 키 등 민감한 정보를 환경변수로 관리하여 코드에 포함시키지 않고 안전하게 정보 보호하였습니다.

포트 설정 간소화

  • 각 컨테이너의 포트를 외부에 노출할 때, docker-compose.yml 파일에 포트를 정의하면 Docker Compose가 자동으로 매핑해 주므로 포트 충돌을 방지하고 설정을 직관적으로 관리할 수 있습니다.

좀더 자세한 내용은 Docker Compose 공식문서 를 참고해해주세요

3) Docker- Compose 모식도

Docker Compose 설정파일 (docker-compose.yml)

  • docker-compose.yml 파일은 여러 개의 서비스(컨테이너) 구성을 정의하는 설정 파일입니다.
  • 이 파일을 통해 이미지, 환경 변수, 네트워크 설정, 볼륨 마운트 등을 정의할 수 있습니다.
  • Docker Compose는 이 설정 파일에 따라 여러 개의 컨테이너를 일괄적으로 하나의 파일에서 관리하고 실행합니다.
  • 현재 프로젝트의 docker-compose.yml은 다음과 같습니다.

version: '3.8'
services:

  frontend:
    build:
      context: ./net-novel-frontend
      dockerfile: Dockerfile
    container_name: frontend
    ports:
      - "80:80"  # 호스트의 80 포트를 컨테이너의 80 포트에 연결
    networks:
      - app-network

  backend:
    build:
      context: ./netnovel
      dockerfile: Dockerfile
    container_name: backend

    ports:
      - "8081:8081"                    # 애플리케이션 포트 설정
    environment:
      - SPRING_PROFILES_ACTIVE=prod  # 프로덕션 프로파일 활성화
      - DB_URL=jdbc:mysql://<IP>/netnovel
      - DB_USERNAME=
      - DB_PASSWORD=

       # 네이버 OAuth 클라이언트 정보 추가
      - NAVER_CLIENT_ID=
      - NAVER_CLIENT_SECRET=
      - REDIS_SESSION_HOST=redis-session
      - REDIS_CACHE_HOST=redis-cache
    networks:
      - app-network
    depends_on:
      redis-session:
        condition: service_started
      redis-cache:
        condition: service_started

  redis-session:
    image: redis:alpine                      # Redis 이미지
    container_name: redis-session
    ports:
      - "6379:6379"                          # Redis 포트 노출
    networks:
      - app-network

  redis-cache:
    image: redis:alpine                      # Redis 이미지
    container_name: redis-cache
    ports:
      - "6380:6379"                          # Redis 포트 노출
    networks:
      - app-network

networks:
  app-network:
    driver: bridge  

Dockerfile로 이미지 빌드(build)

  • Docker Compose는 docker-compose.yml 파일에서 각 서비스에 대해 정의된 Dockerfile 경로를 참조하여 이미지를 빌드합니다.
  • 각 Dockerfile은 개별 애플리케이션의 이미지 템플릿 역할을 하며, docker-compose build 컨테이너명 명령어를 통해 변경사항이 있을 때마다 이미지 빌드를 갱신할 수 있습니다. 예를 들어, 소스 코드 변경Dockerfile을 기반으로 새로운 이미지를 빌드해 컨테이너에서 최신 코드를 반영할 수 있습니다.
  • Docker Compose로 빌드된 이미지는 로컬 환경에 저장되며, 동일한 이미지를 바탕으로 여러 인스턴스를 생성하는 데 사용될 수 있습니다.(아래 실행 설명 참고)

컨테이너 실행(run)

  • 빌드된 이미지는 docker-compose up 명령어를 통해 실행할 수 있으며, 동일한 이미지로 여러 개의 컨테이너(인스턴스) 를 실행할 수도 있습니다.
  • 예를 들어 WAS 이미지를 기반으로 두 개의 인스턴스(Instance 1, Instance 2)를 생성하여 로드 밸런서를 통해 트래픽을 분산시킬 수 있습니다. 이는 애플리케이션의 확장성을 높이고, 특정 서비스의 가용성을 보장하는 데 유용합니다.

Docker Hub나 로컬 환경에서 이미지 사용

  • 이미 생성된 도커 이미지를 재활용하거나, Docker Hub에서 이미지 파일을 다운로드하여 사용할 수도 있습니다.
  • docker-compose.yml 파일에서 이미지의 소스를 Docker Hub에 있는 이미지로 지정하거나 로컬에 저장된 이미지를 참조하여 빠르게 컨테이너를 실행할 수 있습니다.
  • 예를 들어 image: nginx로 설정하여 Docker Hub의 최신 Nginx 이미지를 가져와 컨테이너로 사용할 수 있습니다.

3 결론

  • 이번 포스트에서는 프로젝트에 Docekr Compose를 도입한 배경과, 그이유에대해 알아보았습니다.
  • 다음 포스트에선 구체적인 구현 코드를 포스팅해보도록 하겠습니다.