Docker) Docker Compose에 대해서 간단하게 알아보기

2023. 3. 8. 20:16개발/Docker

Docker Compose란 

 

Docker Compose란 여러 컨테이너를 가지는 애플리케이션을 통합적으로 만들고, 각각의 컨테이너를 시작 및 중지하는 작업을 더 쉽게 수행할 수 있도록 도와주는 도구입니다.

위의 그림으로 직관적으로 이해한다고 보면 여러 컨테이너를 한 번에 시작 및 실행을 해주는 도구라고 볼 수 있습니다.

 

그렇다면 이런 게 왜 필요할까?

 

3 계층 구조(3 Tier- Architecture) 란?

어떠한 플랫폼을 3 계층으로 나누어 별도의 논리적/물리적인 장치에 구축 및 운영하는 형태

보통 서버 한대에 여러 기능을 구축하는 것이 아니라 계층으로 나눠서 관리하게 된다고 합니다.

여기서는 데이터 계층, 로직 계층, 클라이 언 계층으로 나누고, 각각의 기능으로 별도의 논리적/물리적인 장치로 운영하는 방식을 사용한다고 합니다.

 

이러한 구조가 2층도 있고 4층도 있고 다층 구조라고 부릅니다.(Multi-tier Architecture)

이런 것을 각각 docker container를 개별로 띄울 수 있지만, 이러면 서로 연결관계를 다 고려해 줘서 해줘야 하지만,

docker-compose를 구성하면 하나의 network에서 쉽게 관리할 수 있게 합니다.

 

 

Docker Compose를 구성하기 위해서는 YAML 파일을 사용하여 구성할 수 있습니다.

 

 

 

 

 

YAML

Docker Compose 파일은 다음과 같은 구성 요소로 이루어져 있습니다.

 

  • Services: Services는 Docker Compose에서 실행할 컨테이너를 정의합니다. 각각의 서비스는 이미지 이름, 컨테이너 이름, 사용할 포트, 환경 변수 등의 정보를 포함합니다.
  • Networks: Networks는 각 서비스 간의 네트워크 연결을 정의합니다. 각각의 네트워크는 이름과 드라이버 등의 정보를 포함합니다.
  • Volumes: Volumes는 애플리케이션에서 사용하는 데이터 볼륨을 정의합니다. 각각의 볼륨은 이름, 드라이버, 옵션 등의 정보를 포함합니다.
  • Environments: Environments는 서비스에서 사용할 환경 변수를 정의합니다.
  • Configuration : Configurations는 서비스에서 사용할 환경 설정 파일을 정의합니다.
  • Deployments : Deployments는 서비스를 배포하는 데 사용할 설정을 정의합니다.

Docker Compose를 사용하면 Docker CLI 명령어를 사용하여 애플리케이션을 실행하는 대신, docker-compose 명령어를 사용하여 애플리케이션을 실행할 수 있습니다. Docker Compose는 YAML 파일을 읽어 애플리케이션을 실행하며, 컨테이너의 로그를 모니터링하고 상태를 관리할 수 있습니다.

 

Services

services에는 자기가 원하는 여러 도커 컨테이너의 서비스들을 작성하는 곳입니다.

여기서 사용하고자 하는 컨테이너들의 정의를 하시면 됩니다.

  • image
    • image는 해당 서비스에서 사용할 도커 이미지 이름을 정의합니다. 이 이미지는 Docker Hub, Private Registry 또는 로컬에 저장되어 있을 수 있습니다.
    • image를 사용하면 해당 서비스는 이미지를 이미 가지고 있으므로 Dockerfile을 사용하여 이미지를 빌드할 필요가 없습니다. 이미지가 로컬 또는 리모트 레지스트리에서 가져올 수 있습니다.
  • continer_name
    • container_name은 컨테이너의 이름을 정의합니다. 이름을 지정하지 않으면 Docker Compose는 자동으로 이름을 생성합니다.
  • ports
    • ports는 컨테이너가 사용할 포트와 호스트에서 사용할 포트를 지정합니다.
  • environment
    • environment는 서비스에서 사용할 환경 변수를 정의합니다.
  • volumes
    • volumes는 컨테이너와 호스트 간의 데이터 공유를 위한 볼륨을 정의합니다.
  • depends_on
    • depends_on은 다른 서비스에 의존하는 서비스를 정의합니다.
  • build
    • build는 Dockerfile을 사용하여 이미지를 빌드합니다.
    • Dockerfile을 사용하여 새로운 이미지를 빌드합니다. build는 image와 다르게 이미지를 이미 가지고 있지 않습니다. 따라서 이미지를 빌드하기 위해 Dockerfile을 사용하며, 이미지를 로컬 또는 리모트 레지스트리에 저장할 수 있습니다.

web이라는 서비스를 만들 때의 예시는 다음과 같습니다.

 

services:
  web:
    image: nginx:latest
    # build: . (image 또는 build 하나만 사용)
    container_name: my-nginx-container
    ports:
      - "8080:80"
  	environment:
      - ENV_VAR=value
    volumes:
      - "/path/to/local/folder:/path/to/container/folder"
    depends_on:
      - db

 

Networks

Docker Compose YAML 파일에서 networks는 애플리케이션의 컨테이너들이 속할 네트워크를 정의합니다. 컨테이너는 동일한 네트워크에서 연결된 다른 컨테이너와 통신할 수 있습니다.

아무런 설정을 하지 않을 경우 자동으로 생성됩니다.

하지만 다른 컨테이너 잘 통신하는 것이 필요한 경우 Network를 설정해 줘야 합니다.

 

  • driver
    • driver는 네트워크 드라이버를 지정합니다. 네트워크 드라이버는 Docker Engine에서 제공하는 기능으로, 컨테이너를 연결하기 위한 다양한 네트워크 타입을 지원합니다.
  • driver_opts
    • driver_opts는 네트워크 드라이버에 대한 옵션을 정의합니다.
  • ipam
    • IP 주소 관리 방법을 정의합니다. IPAM(IP Address Management)은 IP 주소 할당과 관리를 자동화하기 위한 도구입니다.
  • attachable
    • attachable은 다른 서비스에서 해당 네트워크를 사용할 수 있는지 여부를 지정합니다.

아직 이쪽 분야에 모르는 게 많아서 하나씩 단어를 찾아보면 다음과 같다.

  • IPAM
    IPAM은 IP 주소를 할당하고 관리하며, IP 주소 충돌을 방지하고, IP 주소를 효율적으로 사용할 수 있도록 지원합니다. IPAM은 DHCP(Dynamic Host Configuration Protocol) 서버를 통해 IP 주소를 동적으로 할당할 수 있습니다.
    IPAM은 대규모 네트워크에서 특히 유용합니다. 대규모 네트워크에서는 많은 수의 IP 주소를 관리해야 하며, 이를 수동으로 할당하고 관리하면 매우 복잡하고 시간이 많이 소요됩니다. IPAM을 사용하면 이러한 작업을 자동화하고, IP 주소 관리를 간소화할 수 있습니다.

 

위의 예시에서는 overlay 네트워크 드라이버가 사용되고, attachable 옵션이 true로 설정되어 다른 서비스에서 my-network 네트워크를 사용할 수 있습니다.

networks는 여러 개의 네트워크를 정의할 수 있습니다. 각각의 서비스는 networks 구성 요소를 사용하여 하나 이상의 네트워크에 참여할 수 있습니다.

 

networks:
  my-network:
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: my-bridge
    labels:
      environment: development
  internal-network:
    internal: true
    ipam:
      driver: default
      config:
        - subnet: 10.1.1.0/24

 

Volumes

도커 컨테이너를 사용하여 서비스를 배포하다 보면 데이터를 저장해야 할 필요성이 있습니다. 이때 도커에서 제공하는 Volume을 사용하면 호스트 파일시스템과 컨테이너의 파일시스템을 마운트 하여 데이터를 관리합니다.

이때 각각의 컨테이너에 Volume을 일일이 생성하고 관리하는 것은 번거로울 수 있습니다.

docker-compose의 volume을 사용하면, 여러 개의 컨테이너에 같은 볼륨을 사용할 수 있게 됩니다.

 

  • driver 
    • 볼륨 드라이버 지정하는 데 사용
    • 도커 Volume을 생성할 때 기본적으로 사용되는 드라이버는 local입니다. 이 local 드라이버 이외에도 다른 드라이버를 사용할 수 있으며, driver 옵션을 사용하여 지정할 수 있습니다
    • local을 기본적으로 사용하고, 호스트 머신의 파일 시스템에 디렉터를 생성하고, 이를 컨테이너와 공유하여 데이터를 저장하는 방식
  • name
    • 기본적으로 도커는 무작위로 이름을 생성하지만, name 옵션을 사용하여 이름을 지정할 수 있습니다.
  • external
    • external 옵션을 사용하면 이미 생성된 Volume을 참조할 수 있습니다. 이 옵션을 사용하면 docker-compose up 명령을 실행할 때 Volume을 새로 생성하지 않고 기존 Volume을 사용합니다.

 

version: '3.9'
services:
  web:
    image: nginx
    volumes:
      - type: volume
        source: mydata
        target: /usr/share/nginx/html
  db:
    image: mysql
    volumes:
      - type: volume
        source: mydata
        target: /var/lib/mysql
volumes:
  mydata:

 

위의 코드와 같이 web과 db 서비스에 공유하는 Volume을 만들 수 있습니다.

 

Environments

 컨테이너에 전달할 환경 변수를 설정하는 데 사용됩니다

환경 변수는 컨테이너 내부에서 실행되는 애플리케이션에서 사용할 수 있는 변수로, 컨테이너의 동작을 조정하는 데 중요한 역할

 

version: '3'
services:
  web:
    image: nginx
    ports:
      - "80:80"
    environment:
      - DB_HOST=db
      - DB_USER=user
      - DB_PASSWORD=password
  db:
    image: mysql
    environment:
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_DATABASE=myapp
      - MYSQL_USER=user
      - MYSQL_PASSWORD=password

 

Configuration

 "configuration" 옵션은 Docker 스웜을 사용할 때 스웜 서비스에 대한 구성을 지정하는 데 사용됩니다.

"configuration" 옵션을 사용하면 Docker Compose 파일 내에서 서비스와 관련된 설정을 중앙 집중적으로 관리할 수 있습니다.

 

음 많이 쓰는 것은 나는 아직까지는 못 봤다.

 

Deployments 

애플리케이션 모델의 배포를 지원하는 Compose 구현에는 Compose 애플리케이션 모델이 서비스당 실제 인프라 요구 사항 또는 수명 주기 제약 조건을 반영하기에는 너무 추상적이기 때문에 일부 추가 메타데이터가 필요할 수 있습니다(MAY).

Compose 사양 배포를 통해 사용자는 서비스에 대한 추가 메타데이터를 선언할 수 있으므로 Compose 구현은 관련 데이터를 가져와 플랫폼에 적절한 리소스를 할당하고 사용자의 요구에 맞게 구성할 수 있습니다.

 

  • replicas: 서비스 인스턴스의 수를 지정합니다.
  • placement: 서비스 인스턴스를 배치할 노드를 선택하는 규칙을 지정합니다.
  • update_config: 서비스 업데이트를 제어하는 옵션을 지정합니다.
  • resources: 서비스 인스턴스가 사용할 CPU 및 메모리 등의 자원을 지정합니다.
  • networks: 서비스가 연결할 네트워크를 지정합니다.
version: '3.7'

services:
  web:
    image: nginx:latest
    deploy:
      replicas: 3
      placement:
        constraints:
          - node.role == manager
      update_config:
        parallelism: 2
        delay: 10s
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
      networks:
        - frontend
        - backend

networks:
  frontend:
  backend:

위의 예시는 다음과 같다고 한다.

위의 예시에서는 "web" 서비스를 배포할 때, "deploy" 옵션을 사용하여 다양한 설정을 지정하고 있습니다. 

예를 들어, "replicas" 옵션을 사용하여 3개의 서비스 인스턴스를 생성하고, "placement" 옵션을 사용하여 매니저 노드에서만 서비스 인스턴스를 배치하도록 지정하고 있습니다. 

또한 "update_config" 옵션을 사용하여 서비스 업데이트를 제어하고, "resources" 옵션을 사용하여 서비스 인스턴스가 사용할 자원을 제한하고 있습니다. 마지막으로 "networks" 옵션을 사용하여 서비스가 연결할 네트워크를 지정하고 있습니다.

 

 

예시(대략적인 예시)

3-Tier 아키텍처는 Presentation Layer, Application Layer 및 Data Layer로 구성된다. 

Presentation Layer는 사용자와 상호 작용하며, Application Layer는 비즈니스 로직을 처리하고 Data Layer는 데이터를 저장하고 관리한다.

version: '3.9'
services:
  web:
    build: ./presentation
    ports:
      - "8080:80"
    depends_on:
      - app
  app:
    build: ./application
    ports:
      - "5000:5000"
    environment:
      - DB_HOST=db
      - DB_PORT=3306
      - DB_USER=user
      - DB_PASSWORD=password
      - DB_NAME=myapp
    depends_on:
      - db
  db:
    image: mysql:5.7
    restart: always
    environment:
      - MYSQL_DATABASE=myapp
      - MYSQL_USER=user
      - MYSQL_PASSWORD=password
      - MYSQL_ROOT_PASSWORD=root_password
    volumes:
      - db_data:/var/lib/mysql
volumes:
  db_data:

위의 구성 파일은 3개의 서비스를 정의합니다.

web: Nginx를 사용하여 Presentation Layer를 구성하는 서비스입니다../presentation 디렉터리에서 Dockerfile을 빌드하며, 호스트의 8080 포트를 컨테이너의 80 포트로 매핑합니다.
app: Flask를 사용하여 Application Layer를 구성하는 서비스입니다. ./application 디렉터리에서 Dockerfile을 빌드하며, 호스트의 5000 포트를 컨테이너의 5000 포트로 매핑합니다. db 서비스에 대한 의존성을 가지며, MySQL 데이터베이스 연결 정보를 환경 변수로 설정합니다.
db: MySQL을 사용하여 Data Layer를 구성하는 서비스입니다. mysql:5.7 이미지를 사용하며, 호스트의 3306 포트를 컨테이너의 3306 포트로 매핑합니다. MySQL 데이터베이스 및 사용자 정보를 환경 변수로 설정하며, 데이터베이스 파일을 볼륨으로 저장합니다.


이렇게 Docker Compose를 사용하여 3-Tier 아키텍처를 구성하면, 각각의 레이어를 독립적으로 구성할 수 있으며, 서로 다른 서버에서 실행될 때 발생할 수 있는 호환성 문제를 최소화할 수 있습니다. 또한, Docker Compose를 사용하여 레이어 간의 의존성 및 관계를 쉽게 관리할 수 있으며, 스케일링과 관리도 용이합니다.

 

 

 

참고

https://docs.docker.com/compose/compose-file/

 

Compose file specification

 

docs.docker.com

https://docs.docker.com/compose/compose-file/deploy/

 

Compose file deploy reference

 

docs.docker.com

https://www.youtube.com/watch?v=HG6yIjZapSA&ab_channel=ProgrammingwithMosh 

https://mundanecode.com/posts/three-tier-architecture-in-docker/

 

Three Tier Architecture in Docker - mundaneCode

In this article I am going to talk about how to do a classic 3-tier architecture using docker containers. The 3-tiers will be: Frontend tier: This will host the web application. Middle tier: This will host the api, in our case the REST api. Database tier:

mundanecode.com

https://www.javacodegeeks.com/2015/02/multi-tier-architecture-tutorial-using-docker.html

 

Multi-Tier Architecture Tutorial using Docker - Java Code Geeks - 2023

Background While there are many very good Docker tutorials currently available, I found that many are either too simplistic in the scenarios offered, or

www.javacodegeeks.com

 

728x90