1. 시작하며
Docker Compose는 컨테이너화된 애플리케이션을 효율적으로 관리하기 위한 필수 도구입니다. 하지만 서비스가 복잡해질수록 반복되는 설정과 환경변수의 증가로 인해 Compose 파일이 비대해지고 관리가 어려워질 수 있습니다.
이 문제를 해결하기 위해 Docker Compose는 x-접두사와 YAML 앵커(anchor)를 활용한 사용자 정의 확장 기능을 제공합니다. 이를 통해 공통 설정을 모듈화하고 반복되는 내용을 간결하게 관리할 수 있습니다. 이번 글에서는 Docker Compose에서 x-접두사와 YAML 앵커를 활용해 공통 설정과 명령어를 재사용하는 방법을 Kafka 및 Hadoop + Spark 클러스터 구성 사례를 통해 살펴보겠습니다.
2. Docker Compose의 x-접두사란?
2.1 x-접두사의 정의
x-접두사는 Docker Compose 파일에서 사용자 정의 확장 필드를 정의하기 위한 방식입니다. 이 필드는 Docker Compose에서 무시되며, 주로 공통 설정과 명령어를 모듈화하여 재사용하고 유지보수를 간소화하기 위해 사용됩니다.
1) 주요 특징
- 공통 설정의 모듈화
- 반복되는 환경변수와 명령어를 재사용 가능하게 정의하여 효율적이고 일관된 설정을 유지할 수 있습니다.
- 가독성 향상
- Compose 파일이 간결해지고, 서비스 간 차이를 명확하게 파악할 수 있습니다.
- 유지보수성 향상
- 공통 설정만 수정하면 모든 관련 서비스에 자동으로 반영되므로, 오류 발생 가능성을 줄이고 관리가 쉬워집니다.
2.2 YAML 앵커 (anchor)란?
YAML 앵커(anchor)는 YAML 파일에서 특정 값을 참조하거나 병합하는 기능을 제공합니다. Docker Compose의 x-접두사
와 함께 사용하면 공통 설정과 명령어를 효율적으로 재사용할 수 있습니다.
1) YAML 앵커와 별칭
- 앵커(anchor):
&
기호를 사용하여 값을 정의합니다. - 별칭(alias):
*
기호를 사용하여 정의된 앵커를 참조합니다.
2) YAML 병합
YAML은 앵커를 병합(<<
)하여 기존 값에 새로운 값을 추가하거나 재정의할 수 있습니다.
2.3 Docker Compose 버전 요구 사항
Docker Compose에서 x-접두사를 사용하려면 Docker Compose CLI 1.27.0 이상(Compose V2)이 필요합니다.
1) Compose 파일 버전과 사양
- Docker Compose CLI 1.27.0 이상에서 Compose Specification이 구현되었습니다. 이는 기존 Compose 파일 사양(2.x 및 3.x)의 모든 기능을 통합하며, x-접두사와 같은 사용자 정의 확장 기능을 지원합니다.
- Docker Compose에서 사용되는 모든 주요 기능은 최신 Compose Specification에서 제공되며, 공통 설정과 확장 필드의 재사용이 가능해집니다.
3. 활용 사례 1: Kafka 환경변수 공통 관리
Kafka와 같은 분산 시스템은 여러 브로커가 동일한 설정을 필요로 합니다. 이때 x-접두사와 YAML 앵커(anchor)를 활용하면 공통 설정을 효율적으로 관리하고 유지보수를 간소화할 수 있습니다.
3.1 Kafka 공통 환경변수 정의
Kafka의 공통 설정을 x-kafka-environment
로 정의합니다. 앵커(&)는 설정의 기준점을 정의하는 데 사용됩니다.
x-kafka-environment: &kafka_environment
KAFKA_ZOOKEEPER_CONNECT: zookeeper:${ZOOKEEPER_CLIENT_PORT}
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
KAFKA_DEFAULT_REPLICATION_FACTOR: ${KAFKA_DEFAULT_REPLICATION_FACTOR}
KAFKA_NUM_PARTITIONS: ${KAFKA_NUM_PARTITIONS}
KAFKA_LOG_RETENTION_HOURS: ${KAFKA_LOG_RETENTION_HOURS}
KAFKA_COMPRESSION_TYPE: ${KAFKA_COMPRESSION_TYPE}
KAFKA_SEGMENT_BYTES: ${KAFKA_SEGMENT_BYTES}
KAFKA_HEAP_OPTS: ${KAFKA_HEAP_OPTS}
TZ: ${TZ}
x-kafka-environment
: Kafka 브로커 간 공통 환경변수를 정의한 확장 필드입니다.&kafka_environment
: 공통 설정의 기준점을 정의합니다.
3.2 Kafka 브로커에서 공통 설정 적용
각 Kafka 브로커는 <<: *kafka_environment
를 사용하여 공통 설정을 참조하고, 추가적으로 필요한 개별 설정만 정의합니다.
services:
kafka-1:
image: confluentinc/cp-kafka:latest
container_name: kafka-1
restart: always
depends_on:
- zookeeper
ports:
- "${KAFKA_1_PORT}:${KAFKA_1_PORT}"
environment:
<<: *kafka_environment
KAFKA_BROKER_ID: ${KAFKA_BROKER_ID_1}
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka-1:${KAFKA_INTERNAL_PORT_1},EXTERNAL://localhost:${KAFKA_1_PORT}
kafka-2:
image: confluentinc/cp-kafka:latest
container_name: kafka-2
restart: always
depends_on:
- zookeeper
ports:
- "${KAFKA_2_PORT}:${KAFKA_2_PORT}"
environment:
<<: *kafka_environment
KAFKA_BROKER_ID: ${KAFKA_BROKER_ID_2}
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka-2:${KAFKA_INTERNAL_PORT_2},EXTERNAL://localhost:${KAFKA_2_PORT}
kafka-2:
image: confluentinc/cp-kafka:latest
container_name: kafka-3
restart: always
depends_on:
- zookeeper
ports:
- "${KAFKA_3_PORT}:${KAFKA_3_PORT}"
environment:
<<: *kafka_environment
KAFKA_BROKER_ID: ${KAFKA_BROKER_ID_3}
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka-3:${KAFKA_INTERNAL_PORT_3},EXTERNAL://localhost:${KAFKA_3_PORT}
<<: *kafka_environment
:x-kafka-environment
에서 정의한 공통 설정을 가져옵니다.- 개별 설정 추가: 각 브로커는 고유한
KAFKA_BROKER_ID
와KAFKA_ADVERTISED_LISTENERS
만 정의합니다.
4. 활용 사례 2: Hadoop + Spark 클러스터에서 공통 명령어 관리
Hadoop + Spark 클러스터를 구성할 때, 마스터와 워커 노드의 초기화 및 실행 명령어가 유사한 경우가 많습니다. x-접두사와 YAML 앵커를 활용하면 이를 간결하고 효율적으로 관리할 수 있습니다.
4.1 공통 명령어 정의
공통 명령어를 x-commands
필드에 정의합니다. 앵커(&)를 사용해 초기화 스크립트를 모듈화합니다.
x-commands:
master_command: &master_command >
/bin/bash -c "
if [ ! -f /setup_completed ]; then
echo 'Performing initial setup...';
/usr/local/bin/setup-hadoop.sh &&
/usr/local/bin/update-hosts.sh &&
/usr/local/bin/init-ssh-keys.sh &&
/usr/local/bin/collect-ssh-keys.sh 3 &&
/usr/local/bin/master/setup-master-hadoop-env.sh &&
/usr/local/bin/create-hdfs-log-dir.sh &&
touch /setup_completed;
else
echo 'Skipping initial setup, already completed.';
fi;
/usr/local/bin/start-master.sh &&
/usr/local/bin/start-history-server.sh"
worker_command: &worker_command >
/bin/bash -c "
if [ ! -f /setup_completed ]; then
echo 'Performing initial setup...';
/usr/local/bin/setup-hadoop.sh &&
/usr/local/bin/update-hosts.sh &&
/usr/local/bin/init-ssh-keys.sh &&
/usr/local/bin/collect-ssh-keys.sh 7 &&
/usr/local/bin/worker/setup-worker-hadoop-env.sh &&
touch /setup_completed;
else
echo 'Skipping initial setup, already completed.';
fi;
/usr/local/bin/start-slave.sh"
&master_command
: 마스터 노드 초기화와 실행 명령어입니다.&worker_command
: 워커 노드 초기화와 실행 명령어입니다.
4.2 마스터 및 워커 노드에서 공통 명령어 참조
각 서비스에서 공통 명령어를 참조하여 클러스터 노드를 간단히 정의합니다.
services:
master1:
build:
context: . # Dockerfile 경로
dockerfile: hd-spark-base.Dockerfile
container_name: master1
hostname: master1
ports:
- '${HADOOP_NAME_NODE_WEB_UI_PORT}:${HADOOP_NAME_NODE_WEB_UI_PORT}'
- '${HADOOP_RESOURCE_MANAGER_WEB_UI_PORT}:${HADOOP_RESOURCE_MANAGER_WEB_UI_PORT}'
- '${HADOOP_MAP_REDUCE_JOB_HISTORY_SERVER_WEB_UI_PORT}:${HADOOP_MAP_REDUCE_JOB_HISTORY_SERVER_WEB_UI_PORT}'
- '${SPARK_MASTER_PORT}:${SPARK_MASTER_PORT}'
- '${SPARK_MASTER_WEB_UI_PORT}:${SPARK_MASTER_WEB_UI_PORT}'
- '${SPARK_HISTORY_SERVER_PORT}:${SPARK_HISTORY_SERVER_PORT}'
volumes:
- shared_keys:/shared_keys
networks:
- nowdoboss-net
command: *master_command
worker1:
build:
context: .
dockerfile: hd-spark-base.Dockerfile
container_name: worker1
hostname: worker1
volumes:
- shared_keys:/shared_keys
networks:
- nowdoboss-net
command: *worker_command
- 공통 명령어 사용
command: *master_command
: 마스터 노드 초기화 및 실행 명령어 참조합니다.command: *worker_command
: 워커 노드 초기화 및 실행 명령어 참조합니다.
- 동일한 초기화 로직
- 모든 노드가 동일한 초기화 스크립트를 실행하여 환경 일관성을 유지합니다.
- 유지보수 용이
- 초기화 스크립트를 수정하면 모든 노드에 자동으로 반영합니다.
5. Docker Compose 공식 문서에서의 언급된 x-접두사 사용법
Docker Compose 공식 문서에 따르면, x-접두사는 다양한 상황에서 활용할 수 있습니다. 몇 가지 추가 사례는 다음과 같습니다.
5.1 환경변수 병합
환경변수를 여러 소스에서 병합하여 사용할 수 있습니다.
x-env: &env
environment:
- CONFIG_KEY
- EXAMPLE_KEY
services:
app1:
<<: *env
image: my-image:latest
app2:
<<: *env
image: another-image:latest
5.2 사용자 정의 태그 및 종속성 관리
공통적인 태그와 종속성을 관리할 때도 x-접두사를 활용할 수 있습니다.
x-function: &function
labels:
type: function
depends_on:
- gateway
services:
service1:
<<: *function
image: service1:latest
service2:
<<: *function
image: service2:latest
6. 결론
Docker Compose의 x-접두사는 공통 설정을 관리하고 YAML 파일의 가독성과 유지보수성을 높이는 데 매우 유용한 도구입니다. Kafka와 Hadoop + Spark 환경에서 이를 활용하는 방법을 살펴보았으며, Docker Compose 공식 문서에서 제공하는 다양한 사례를 통해 이 기능의 잠재력을 확인할 수 있었습니다.
앞으로도 Docker Compose의 다양한 기능을 활용하여 DevOps 환경에서 효율적인 관리와 확장을 지속적으로 구현해 나가겠습니다.