# CeleryExecutor와 Redis, PostgreSQL을 사용하여 기본적인 Airflow 클러스터 구성입니다.
# 이 구성은 환경 변수 또는 .env 파일을 사용한 기본 구성을 지원합니다.
# 다음 변수가 지원됩니다:
#
# AIRFLOW_IMAGE_NAME           - Airflow를 실행하는 데 사용되는 Docker 이미지 이름.
#                                기본값: apache/airflow:2.5.1
# AIRFLOW_UID                  - Airflow 컨테이너의 사용자 ID
#                                기본값: 50000
# AIRFLOW_PROJ_DIR             - 모든 파일이 볼륨을 설정할 기본 경로.
#                                기본값: .
# 이러한 구성은 대부분의 경우 독립적인 테스트/시험 모드에서 Airflow를 실행할 때 유용합니다.
#
# _AIRFLOW_WWW_USER_USERNAME   - 관리자 계정의 사용자 이름 (요청시).
#                                기본값: airflow
# _AIRFLOW_WWW_USER_PASSWORD   - 관리자 계정의 비밀번호 (요청시).
#                                기본값: airflow
# _PIP_ADDITIONAL_REQUIREMENTS - 모든 컨테이너를 시작할 때 추가할 추가 PIP 요구 사항.
#                                기본값: ''

---
version: '3'
x-airflow-common:
  &airflow-common

#requirements.txt 파일로 사용자 지정 종속성을 추가하거나 제공자 패키지를 업그레이드하려면

# Dockerfile을 추가해 확장 이미지를 사용할 수 있습니다.
# 'image: ${AIR~' 부분을  주석 처리 하고 docker-compose.yaml 파일이 있는 디렉토리에 Dockerfile을 생성
# 그런 다음 아래 "build" 라인의 주석 처리를 해제, 이후 이미지를 빌드하려면 `docker-compose build`를 실행

# 이미지를 설정하는 부분으로, AIRFLOW_IMAGE_NAME이 설정되어 있으면 해당 값을 사용하고, 
      # 설정되어 있지 않으면 기본값인 apache/airflow:2.5.1을 사용
  image: ${AIRFLOW_IMAGE_NAME:-apache/airflow:2.5.1}
    # build: .
  environment:
    &airflow-common-env
    #Airflow의 실행 모드(Executor)를 설정하는 부분입니다. CeleryExecutor는 Airflow이 작업을 분산하고
    #여러 워커에서 병렬로 실행하기 위해 Celery를 사용하는 실행 모드
    AIRFLOW__CORE__EXECUTOR: CeleryExecutor
        
    #Airflow이 데이터베이스에 연결하기 위한 SQLAlchemy 연결 문자열
    #PostgreSQL 데이터베이스를 사용하며, psycopg2라는 Python 드라이버를 통해 연결
    AIRFLOW__DATABASE__SQL_ALCHEMY_CONN: postgresql+psycopg2://airflow:airflow@postgres/airflow
                
    # Airflow 2.3 이전의 버전과의 하위 호환성을 위한 것으로, Airflow의 코어 모듈이 
    # 데이터베이스에 연결하는 데 사용하는 SQLAlchemy 연결 문자열
    AIRFLOW__CORE__SQL_ALCHEMY_CONN: postgresql+psycopg2://airflow:airflow@postgres/airflow
    
    # CeleryExecutor를 사용할 때 Celery 작업 결과를 저장하는 백엔드를 지정
    # CeleryExecutor를 사용하는 경우 작업의 실행 및 결과 추적
    AIRFLOW__CELERY__RESULT_BACKEND: db+postgresql://airflow:airflow@postgres/airflow
    
    # Redis 서버가 redis로 호스트되고 포트 6379를 사용하며, 브로커 데이터베이스는 0으로 설정
    AIRFLOW__CELERY__BROKER_URL: redis://:@redis:6379/0
    
    # Fernet은 암호화와 관련된 토큰 생성 및 검증을 담당하는 대칭 키 알고리즘
    AIRFLOW__CORE__FERNET_KEY: ''
    
    # DAG가 생성될 때 자동으로 일시 중지되는지 여부
    AIRFLOW__CORE__DAGS_ARE_PAUSED_AT_CREATION: 'true'
        
    # 예제 dag들을 실행할지 여부
    AIRFLOW__CORE__LOAD_EXAMPLES: 'false'
        
# Airflow API의 인증 백엔드를 지정합니다. 여기서는 기본적으로, basic_auth 및 session
# basic_auth : HTTP 기반의 사용자 이름 및 비밀번호를 사용한 인증/session: 세션을 사용하여 사용자를 인증
    AIRFLOW__API__AUTH_BACKENDS: 'airflow.api.auth.backend.basic_auth,airflow.api.auth.backend.session'
    
    # 추가적으로 설치해야 하는 Python 패키지의 목록
    _PIP_ADDITIONAL_REQUIREMENTS: ${_PIP_ADDITIONAL_REQUIREMENTS:-}
        
     # 볼륨으로 폴더들을 매핑  
  volumes:
    - ${AIRFLOW_PROJ_DIR:-.}/dags:/opt/airflow/dags
    - ${AIRFLOW_PROJ_DIR:-.}/logs:/opt/airflow/logs
    - ${AIRFLOW_PROJ_DIR:-.}/plugins:/opt/airflow/plugins
        
      # AIRFLOW_UID의 값을 사용하며, 해당 값이 설정되어 있지 않으면 기본값으로 50000을 사용  
  user: "${AIRFLOW_UID:-50000}:0"
    # redis,postgres가 healthy할때 컨테이너 시작
  depends_on:
    &airflow-common-depends-on
    redis:
      condition: service_healthy
    postgres:
      condition: service_healthy

services:
  postgres:
    image: postgres:13
    environment:
      POSTGRES_USER: airflow
      POSTGRES_PASSWORD: airflow
      POSTGRES_DB: airflow
    volumes:
      - postgres-db-volume:/var/lib/postgresql/data
    healthcheck:
        # PostgreSQL 서버가 준비 상태인지 확인합니다. -U airflow는 airflow 사용자로 접속하는 것을 의미
      test: ["CMD", "pg_isready", "-U", "airflow"]
        # 건강 상태를 확인하는 주기를 5초로 설정
      interval: 5s
        # 실패할 경우 최대 5번 재시도
      retries: 5
        # 서비스가 종료될 경우 자동으로 재시작하도록 설정
    restart: always
        # redis 서비스는 Redis 이미지를 사용하여 6379번 포트로 노출하며, 주기적으로 
        # redis-cli ping 명령을 사용하여 건강 상태를 확인하고, 문제가 발생할 경우 자동으로 재시작
  redis:
    image: redis:latest
    expose:
      - 6379
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 30s
      retries: 50
    restart: always

    # Airflow 웹 서버를 8080 포트로 노출하고 주기적으로 건강 상태를 확인하며, 
    #문제가 발생할 경우 자동으로 재시작합니다. 또한, airflow-webserver 서비스는 
    #airflow-init 서비스가 성공적으로 실행된 후에만 시작됨
  airflow-webserver:
    # 앵커에서 정의된 환경 변수를 가져옴
    <<: *airflow-common
    command: webserver
    ports:
      - 8080:8080
    healthcheck:
        # 서버가 오류 응답을 반환하면 curl 명령이 실패하도록 만듬
        # 건강 상태를 확인하기 위한 Airflow URL
      test: ["CMD", "curl", "--fail", "http://localhost:8080/health"]
      interval: 10s
      timeout: 10s
      retries: 5
    restart: always
    depends_on:
      <<: *airflow-common-depends-on
      airflow-init:
        condition: service_completed_successfully

  airflow-scheduler:
    <<: *airflow-common
    command: scheduler
    healthcheck:
        # 스케줄러 작업의 건강 상태를 확인하는 Airflow 명령입니다. $${HOSTNAME}는 환경 변수를 나타냅니다. 
        # 스케줄러 작업이 정상적으로 수행되고 있는지 확인하는 용도로 사용됨
      test: ["CMD-SHELL", 'airflow jobs check --job-type SchedulerJob --hostname "$${HOSTNAME}"']
      interval: 10s
      timeout: 10s
      retries: 5
    restart: always
    depends_on:
      <<: *airflow-common-depends-on
      airflow-init:
        condition: service_completed_successfully

  airflow-worker:
    <<: *airflow-common
    command: celery worker
    healthcheck:
      test:
        # 명령이 쉘에서 실행되어야 함
        - "CMD-SHELL"
        # Celery Worker가 실행 중이고 정상적으로 동작하는지 확인하는 Celery 명령입니다. 
        # Airflow의 작업들을 비동기적으로 처리하기 위해 Celery라는 분산 작업 큐 시스템을 이용
        # $${HOSTNAME}는 환경 변수를 나타냅니다. Celery Worker의 건강 상태를 확인하는데 사용됨
        - 'celery --app airflow.executors.celery_executor.app inspect ping -d "celery@$${HOSTNAME}"'
      interval: 10s
      timeout: 10s
      retries: 5
    environment:
      <<: *airflow-common-env
        # DUMB_INIT_SETSID를 0으로 설정하면, dumb-init이 프로세스를 세션 리더로 만들지 않습니다.
        # 세션 리더로 만들지 않는 것은 몇 가지 동작 관련 이슈를 방지하고자 하는이유는.
        # 안정성을 고려한 선택입니다. celery workers의 올바른 웜 셧다운을 처리하는데 도움됩니다.
      DUMB_INIT_SETSID: "0"
    restart: always
    depends_on:
      <<: *airflow-common-depends-on
      airflow-init:
        condition: service_completed_successfully

  airflow-triggerer:
    <<: *airflow-common
    command: triggerer
    healthcheck:
        #CMD-SHELL 테스트 명령어로, Airflow의 작업(triggerer job)이 정상적으로 동작하는지 확인
      test: ["CMD-SHELL", 'airflow jobs check --job-type TriggererJob --hostname "$${HOSTNAME}"']
      interval: 10s
      timeout: 10s
      retries: 5
    restart: always
    depends_on:
      <<: *airflow-common-depends-on
      airflow-init:
        condition: service_completed_successfully

  airflow-init:
    <<: *airflow-common
        # 컨테이너가 시작될 때 Bash 셸을 실행
    entrypoint: /bin/bash
    # yamllint disable rule:line-length
    command:
      - -c
      - |
        function ver() {
          printf "%04d%04d%04d%04d" $${1//./ }
        }
        # 현재 Airflow 버전 확인
        airflow_version=$$(AIRFLOW__LOGGING__LOGGING_LEVEL=INFO && gosu airflow airflow version)
        airflow_version_comparable=$$(ver $${airflow_version})
        
        # 최소 Airflow 버전 확인
        min_airflow_version=2.2.0
        min_airflow_version_comparable=$$(ver $${min_airflow_version})
        
        # 현재 버전이 최소 버전보다 낮으면 오류 출력
        if (( airflow_version_comparable < min_airflow_version_comparable )); then
          echo
          echo -e "\033[1;31mERROR!!!: Too old Airflow version $${airflow_version}!\e[0m"
          echo "The minimum Airflow version supported: $${min_airflow_version}. Only use this or higher!"
          echo
          exit 1
        fi
        
        # AIRFLOW_UID가 설정되지 않았을 때 경고 출력
        if [[ -z "${AIRFLOW_UID}" ]]; then
          echo
          echo -e "\033[1;33mWARNING!!!: AIRFLOW_UID not set!\e[0m"
          echo "If you are on Linux, you SHOULD follow the instructions below to set "
          echo "AIRFLOW_UID environment variable, otherwise files will be owned by root."
          echo "For other operating systems you can get rid of the warning with manually created .env file:"
          echo "    See: https://airflow.apache.org/docs/apache-airflow/stable/howto/docker-compose/index.html#setting-the-right-airflow-user"
          echo
        fi
        
        # 시스템 자원 확인 (메모리, CPU, 디스크)
        one_meg=1048576
        mem_available=$$(($$(getconf _PHYS_PAGES) * $$(getconf PAGE_SIZE) / one_meg))
        cpus_available=$$(grep -cE 'cpu[0-9]+' /proc/stat)
        disk_available=$$(df / | tail -1 | awk '{print $$4}')
        warning_resources="false"
        
        # 메모리 최소사양보다 부족할 경우 경고 출력
        if (( mem_available < 4000 )) ; then
          echo
          echo -e "\033[1;33mWARNING!!!: Not enough memory available for Docker.\e[0m"
          echo "At least 4GB of memory required. You have $$(numfmt --to iec $$((mem_available * one_meg)))"
          echo
          warning_resources="true"
        fi
        # CPU 최소사양보다 부족할 경우 경고 출력
        if (( cpus_available < 2 )); then
          echo
          echo -e "\033[1;33mWARNING!!!: Not enough CPUS available for Docker.\e[0m"
          echo "At least 2 CPUs recommended. You have $${cpus_available}"
          echo
          warning_resources="true"
        fi
        # 디스크 최소사양보다 부족할 경우 경고 출력
        if (( disk_available < one_meg * 10 )); then
          echo
          echo -e "\033[1;33mWARNING!!!: Not enough Disk space available for Docker.\e[0m"
          echo "At least 10 GBs recommended. You have $$(numfmt --to iec $$((disk_available * 1024 )))"
          echo
          warning_resources="true"
        fi
        
        # 시스템 자원 부족 시 경고 출력
        if [[ $${warning_resources} == "true" ]]; then
          echo
          echo -e "\033[1;33mWARNING!!!: You have not enough resources to run Airflow (see above)!\e[0m"
          echo "Please follow the instructions to increase amount of resources available:"
          echo "   https://airflow.apache.org/docs/apache-airflow/stable/howto/docker-compose/index.html#before-you-begin"
          echo
        fi
        
        # Airflow 폴더 및 파일 권한 설정
        mkdir -p /sources/logs /sources/dags /sources/plugins
        chown -R "${AIRFLOW_UID}:0" /sources/{logs,dags,plugins}
        
        #Docker 컨테이너 내에서 실행되는 Airflow의 버전을 확인
        exec /entrypoint airflow version
    # yamllint enable rule:line-length
    environment:
      <<: *airflow-common-env
        # db 업그레이드, 계정 생성후, id/pw 설정
      _AIRFLOW_DB_UPGRADE: 'true'
      _AIRFLOW_WWW_USER_CREATE: 'true'
      _AIRFLOW_WWW_USER_USERNAME: ${_AIRFLOW_WWW_USER_USERNAME:-airflow}
      _AIRFLOW_WWW_USER_PASSWORD: ${_AIRFLOW_WWW_USER_PASSWORD:-airflow}
      _PIP_ADDITIONAL_REQUIREMENTS: ''
    user: "0:0"
    volumes:
      - ${AIRFLOW_PROJ_DIR:-.}:/sources

 

  # airflow-cli은  Apache Airflow의 커맨드 라인 인터페이스(Command Line Interface, CLI)를 나타냅니다. Airflow CLI를
  # 사용하면 Airflow에서 제공하는 다양한 기능을 명령어를 통해 수행

  airflow-cli:
    <<: *airflow-common
    profiles:
      - debug
    environment:
      <<: *airflow-common-env
      CONNECTION_CHECK_MAX_COUNT: "0"
    # Workaround for entrypoint issue. See: https://github.com/apache/airflow/issues/16252
    # Bash 셸에서 문자열을 실행할 때 사용, Airflow CLI를 실행
    command:
      - bash
      - -c
      - airflow

  # You can enable flower by adding "--profile flower" option e.g. docker-compose --profile flower up
  # or by explicitly targeted on the command line e.g. docker-compose up flower.
  # See: https://docs.docker.com/compose/profiles/
    # flower는 Celery 작업 큐를 시각적으로 모니터링하고 관리하기 위한 도구
  flower:
    <<: *airflow-common
    command: celery flower
    profiles:
      - flower
    ports:
      - 5555:5555
    healthcheck:
      test: ["CMD", "curl", "--fail", "http://localhost:5555/"]
      interval: 10s
      timeout: 10s
      retries: 5
    restart: always
    depends_on:
      <<: *airflow-common-depends-on
      airflow-init:
        condition: service_completed_successfully
# Docker Compose 파일에서 볼륨을 설정하는 부분
volumes:
  postgres-db-volume:

FROM apache/airflow:2.5.1

 

USER root
RUN apt-get update \
  && apt-get install -y --no-install-recommends \
         vim \
  && apt-get autoremove -yqq --purge \
  && apt-get clean \
  && rm -rf /var/lib/apt/lists/*
Dockerfile 내에서 패키지를 설치하고 이미지를 최적화
1. `apt-get update`: 패키지 목록을 업데이트합니다.
2. `apt-get install -y --no-install-recommends vim`: vim 패키지를 설치하고 권장 패키지를 설치하지 않도록 합니다.
3. `apt-get autoremove -yqq --purge`: 불필요한 패키지를 자동으로 제거합니다.
4. `apt-get clean`: apt의 캐시를 지웁니다.
5. `rm -rf /var/lib/apt/lists/*`: 패키지 목록과 관련된 임시 파일을 제거합니다.

USER airflow

# app으로 requirements.txt 복사
COPY requirements.txt /app/requirements.txt
RUN pip3 install -r /app/requirements.txt


그냥하면 되는걸 왜 복사하고 설치할까?

Docker는 각 명령어를 캐싱하여 이미지 빌드 속도를 높이려고 합니다. 만약 COPY requirements.txt /app/requirements.txt 를 먼저 수행하고, 그 후에 소스 코드의 변경이 없는 경우 Docker는 이전 단계를 캐시하고 pip3 install을 다시 실행하지 않습니다. 이로써 이미지 빌드가 더 빨라집니다.

만약 소스 코드가 변경되지 않았고, requirements.txt 파일도 변경되지 않았다면, Docker는 이전에 설치된 패키지를 그대로 사용할 수 있습니다. 따라서 COPY ~ 를 따로 두는 것은 이미지 빌드 성능을 최적화하는 한 방법입니다.


# DAG 파일 복사
COPY dags/ /opt/airflow/dags/

 

쿠버네티스(k8s)

  • 컨테이너 기반 서비스의 배포,스케일,관리 자동화를 해주는 오픈소스 프레임워크
  • 가장 많이 사용되는 컨테이너 관리(orchestration) 시스템이다.
  • 모든 컨테이너가 가능하지만 컨테이너는 주로 docker가 쓰여서, docker container가 주 대상이다.
  • 물리서버나 가상서버 위에서 모두 동작한다.
  • 카카오, 네이버, 라인, 쿠팡 등 활발히 사용
  • 글로벌 클라우드 업체들이 지원 : EKS( Elastic 아마존),AKS ( Azure 마이크로소프트) ,GKE( Google 구글)
  • 그외 다양한 추가기능 머신러닝(kubeflow), CI/CD(Tekton), Service Mesh(lstio), serverless(kubeless)


k8s 기본구조와 구성요소

  • high availability : 시스템이나 서비스가 지속적으로 가용성을 유지하고 장애가 발생했을 때에도 빠르게 회복할 수 있는 능력. 다수의 서버를 구성하거나, 부하분산, 감시 및 자동화를 통해 장애를 최소화하는게 도움이 된다.

  • 노드들(서버들)은 물리 및 가상서버이다. master가 노드들의 상황을 파악하기 위해 kubelet을 이용한다. 
    virtual network : 노드들간의 연결, pod들간에 연결을 관리. 연결이 필요할땐, 연결해주고 보인이 필요할땐, 분리된 네트워크를 만들어 보안을 보장. 
    + Pod은 하나 이상의 컨테이너를 묶어서 공동으로 실행 하는 단위, 동일한 네트워크 네임스페이스를 공유하여 통신

  • api 서버 : container로 동작한다. 
    + 커맨드라인 cli(kubectl) 으로도 다룰수 있음
    예) kubectl run hello-minikube : 새로운 Pod를 시작 ,
    kubectl cluster-info : 작동 중인 Kubernetes 클러스터의 정보를 제공 ,
    kubectl get node : 클러스터 내의 노드들의 목록을 가져옴

  • scheduler : 노드들의 상황을 고려한 pods의 생성과 할당
  • controller manager : 전체 상황 모니터링 하고, 중단 없이 작동할 수 있게(fault tolerance) 한다.
  • etcd( distributed reliable key-value store ) : k8s 환경 설정 정보가 저장되는 key/value스토어(저장소)

 

pod란 무엇인가?

  1. pod : 사용자가 사용하는 가장 작은 블록(하나 혹은 그 이상의 컨테이너의 집합)
  2. 보통 쿠버네티스에서 컨테이너를 바로 다루지 않고 pod를 다룬다고 보면됨
  3. pod가 하나보다 많을땐, 경우에 따라 helper container가 같이 사용됨.
    +helper container : 주된 애플리케이션 컨테이너가 시작되기 전에 일회성 작업을 수행하는 데 사용.
    처음 설치때만 사용하고 비활성화 되는 init 같은것
  4. Pod 내의 컨테이너들이 서로 독립된 환경이 아니라, 동일한 네트워크 네임스페이스와 디스크 공간을 공유함
  5. fail-over를 방지하기 위해 다양한 방법으로 복제본을 유지한다.
  6. pod는 자체적인 네트워크 주소를 가진 독립된 서버, 내부에서는 컨테이너 간 통신과 데이터 공유가 쉽다.

 

 

환경설정 예

  • kind의 값으로 pod,service,replicaset,deployment가 가능하다.

  • Service: Kubernetes에서 서비스를 정의하여 클러스터 내의 여러 Pod에 접근 가능한 하나의 가상 IP 및 DNS 주소를 제공합니다. Pod의 논리적 그룹에 대한 로드 밸런싱, 서비스 디스커버리, 클러스터 내의 다른 서비스와 통신을 위한 추상화를 제공합니다.
  • ReplicaSet: ReplicaSet은 Pod을 여러 개 복제하고 관리하는 Kubernetes 오브젝트로, 지정된 수의 Pod 인스턴스를 유지하도록 합니다. 애플리케이션의 가용성을 보장하고 스케일링을 가능케 하며, Pod의 상태를 관리하여 원하는 상태를 유지합니다.
  • Deployment:Kubernetes에서 애플리케이션의 배포 및 업데이트를 관리하는 리소스로, ReplicaSet과 Pod을 관리하면서 롤링 업데이트 및 롤백과 같은 기능을 제공합니다. Deployment를 통해 애플리케이션의 버전 업데이트, 스케일 인/아웃 등을 쉽게 수행할 수 있습니다.

  • metadata : 오브젝트의 이름, 네임스페이스, 레이블 등의 정보를 포함하며, 오브젝트를 식별하고 구성하는 데 사용
  • spec : 오브젝트의 원하는 상태를 기술하며, Pod의 경우 컨테이너 이미지, 볼륨, 네트워크 설정 등이 여기에 속함

pod 생성예

  1. Kubernetes 클러스터에 Pod을 생성
    `kubectl create -f pod-definition.yml`:
       - `-f` 옵션 다음에는 Pod을 정의한 YAML 파일인 `pod-definition.yml`이 주어집니다.
       - YAML 파일에는 Pod의 메타데이터, 스펙 등이 정의되어 있어야 합니다.

  2. 현재 Kubernetes 클러스터에서 실행 중인 Pod 목록을 조회
    `kubectl get pods`:
       - 각 Pod의 이름, 상태, 시작 시간 등의 정보를 출력합니다.

  3. 이름이 "nginx"인 Pod에 대한 상세 정보를 출력
    `kubectl describe pod nginx`:
       - Pod의 메타데이터, 레이블, 이벤트, 컨테이너 상태 등을 자세히 보여줍니다.

  4. 새로운 Pod을 실행하도록 명령
    kubectl run nginx --image nginx`:
       - `nginx` 이미지를 사용하며, 이 명령어는 Deployment를 생성하여 Pod을 관리하는 형태로 동작합니다. (최근 버전의 kubectl에서는 Deprecated 되었을 수 있음)

 

쿠버네티스 사용 실제예

 

쏘카 데이터 그룹 - Airflow와 함께한 데이터 환경 구축기(feat. Airflow on Kubernetes)

지난 3년간 Airflow 구축 및 운영기록

tech.socarcorp.kr

 

버킷플레이스 Airflow 도입기 - 오늘의집 블로그

탁월한 데이터플랫폼을 위한 Airflow 도입기

www.bucketplace.com

 

쿠버네티스로 다음에 해볼만한 것들

  • docker image를 어떻게 배포할것인가? (블로그의 도커관련 글 참조)
  • docker-compose를 통해 multi-container 관리방법 (블로그의 도커관련 글 참조)
  • 쿠버네티스를 사용해 container 관리하고 배포하기
  • 네트워크 관련해 외부와 연결설정하기 (cluster ip,nodeport,load balancer, ingress, 서비스 타입)
  • 부하에 따라서 컨테이너 수를 늘리기(스케일 아웃)

Container Orchestration이란

  • 다수의 컨테이너를 잘 관리하는것
  • 필요기능 : 배포, 스케일링, 네트워크, 인사이트
    +자세한 설명은 아래에

  • 클러스터 내부의 관계 뿐 아니라 클러스터 간의 네트워크도 잘 조율해야함

  • 필요기능1 배포
    배포 (Deployment):새 버전 배포시, 이상이 감지되면 이전 안정 버전으로 롤백.

    +간단한거 같지만 컨테이너가 많을수록 서로 연결성이 복잡하기 때문에 고도의 기능(devops팀에게 중요한 기능)

  • 필요기능2 스케일링
    스케일링 (Scaling):** 시스템이나 서비스의 성능을 향상시키기 위해 컨테이너 수를 늘리고 줄여서, 리소스를 조절하는 프로세스. 수직 스케일링은 단일 서버의 성능을 증가시키는 반면, 수평 스케일링은 여러 서버 인스턴스를 추가하여 부하 분산과 성능 향상을 달성한다. 

  • 필요기능3 네트워크
    네트워크 (Network): 서비스가 다수의 컨테이너로 나눠지면서, 이들을 대표하는 load balancer를 만들어야함. 또한 서비스들간에 서로를 쉽게 찾을 수 있어야한다(서비스디스커버리). 
  • 필요기능3 인사이트
    인사이트 (Insights): 문제가 생긴 컨테이너(2번)를 발견시, 서버 3번에 프론트 이미지를 주고 실행시키고,
    서버2번은 로드밸런서에서 제거. 이를 자동으로 하는게 Container Orchestration의 network, service discovery 기능.
    남은 다양한 로그들을 분석을 할수 있고, 각 컴포넌트 간의 요청과 시간을 분석함으로서 문제가 있는 부분을 발견할수 있음.

  • Container Orchestration 툴들 : mesos, marathon, deis,rancher,nomad,docker swarm, k8s(쿠버네티스 이게 대세)
  • k8s 관련서비스 : EKS,AKS,GKE 

서버 관리시 발생하는 문제들

  1. 어느 서버가 문제가 있는지
  2. 어떤 서비스가 문제가 있는지
  3. 이런 문제들을 얼마나 빨리 파악하고, 해결할수 있는지
  4. 새로 들어온 주니어를 잘 교육시키려면?
  5. 문제는 밤낮, 연휴에도 발생

해결방안 1 :문서화

  • 위 문제들을 빠르고 정확하게 해결하기 위해 문서화.
  • 점점 관리 서버가 많아지고, 문서를 업데이트 하는것이 시간이 갈수록 불가능에 가까워짐

 

해결방안 2 : 코드로 관리(DevOps 가 하는일)

  • 설치과정 등을 코드로 작성(chef,puppet,ansible,terraform 등등 툴들)
  • 자동화된 스크립트 작성
  • 다수의 서버들이 명령을 대신 실행해줌
  • 단점 : 많은 툴들을 배워야 해서 진입장벽높음, 소프트웨어간 라이브러리간 충돌 문제에는 크게 도움이 안됨

해결방안3 : virtual Machine 도입

  • 가상 하드웨어를 사용. os 필요
  • os 필요해서 사용료 증가
  • 하드웨어를 VM에 일부 할당해야해서 리소스 소비가 크고 느림
  • VM 서비스에 종속됨

해결방안4: 끝판왕 docker 의 도입

  • docker image를 만들면 어디서든 동작(개발 테스트 운영이 일관화됨)
  • vm에 비해 리소스 낭비가 적고 실행도 빠름
  • 오픈소스라 특정업체에 종속 되지 않음
  • 단점 : 컨테이너 수가 늘어나면 관리가 힘듦
  • 현상황 : 현재 docker는 서비스 배포의 기본

 

docker를 사용하며 새롭게 발생한 문제들

목적 : airflow setup을 위해 제작된 docker-compose.yaml 파일의 내용을 살펴본다.

 

airflow 설치

  1. 깃허브에서 airflow-setup 파일 받음
    weare@DESKTOP-BE1I4GE:~$ git clone https://github.com/keeyong/airflow-setup.git
    Cloning into 'airflow-setup'...
    remote: Enumerating objects: 65, done.
    remote: Counting objects: 100% (65/65), done.
    remote: Compressing objects: 100% (63/63), done.
    remote: Total 65 (delta 27), reused 0 (delta 0), pack-reused 0
    Receiving objects: 100% (65/65), 1.32 MiB | 20.85 MiB/s, done.
    Resolving deltas: 100% (27/27), done.

  2. 해당 폴더로 이동
    weare@DESKTOP-BE1I4GE:~$ cd airflow-setup

  3. curl을 사용하여 URL에서 yaml 파일을 다운로드하고 -O 옵션을 사용하여 로컬에 파일을 저장
    weare@DESKTOP-BE1I4GE:~/airflow-setup$ curl -LfO "https://airflow.apache.org/docs/apache-airflow/2.5.1/docker-compose.yaml"
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100 10493  100 10493    0     0   134k      0 --:--:-- --:--:-- --:--:--  134k

  4. yaml 파일에 정의된 도커 이미지를 다운로드. 로컬에 없는, postres, redis 등은 docker hub 에서 가져옴.
    weare@DESKTOP-BE1I4GE:~/airflow-setup$ docker-compose -f docker-compose.yaml pull
    WARNING: The AIRFLOW_UID variable is not set. Defaulting to a blank string.
    Pulling postgres          ... done
    Pulling redis             ... done
    Pulling airflow-init      ... done
    Pulling airflow-triggerer ... done
    Pulling airflow-worker    ... done
    Pulling airflow-scheduler ... done
    Pulling airflow-webserver ... done
    + postres, redis 는 외부에서 가져와서 airflow-가 앞에 붙지 않았다.

  5. 서버 실행 (에러발생)
    weare@DESKTOP-BE1I4GE:~/airflow-setup$ docker-compose -f docker-compose.yaml up
    WARNING: The AIRFLOW_UID variable is not set. Defaulting to a blank string.
    Creating airflow-setup_redis_1    ... done
    Creating airflow-setup_postgres_1 ... done
    Creating airflow-setup_airflow-init_1 ... done
    Creating airflow-setup_airflow-scheduler_1 ... done
    Creating airflow-setup_airflow-webserver_1 ... done
    Creating airflow-setup_airflow-triggerer_1 ... done
    Creating airflow-setup_airflow-worker_1    ... done
    Attaching to airflow-setup_redis_1, airflow-setup_postgres_1, airflow-setup_airflow-init_1, airflow-setup_airflow-scheduler_1, airflow-setup_airflow-webserver_1, airflow-setup_airflow-triggerer_1, airflow-setup_airflow-worker_1
    airflow-init_1       |
    airflow-init_1       | WARNING!!!: AIRFLOW_UID not set!
    airflow-init_1       | If you are on Linux, you SHOULD follow the instructions below to set
    airflow-init_1       | AIRFLOW_UID environment variable, otherwise files will be owned by root.
    airflow-init_1       | For other operating systems you can get rid of the warning with manually created .env file:

    AIRFLOW_UID not set! : AIRFLOW_UID가 설정되지 않았다는 내용, 필요한 폴더들을 만들고 환경변수가 저장될 위치가 필요하다.
  6. 에러 해결을 위해 airflow 운용에 필요한 폴더( dags , logs, plugins )들을 만들고 환경변수가 저장될 위치가 필요하다.

    1) DAG 파일, 로그, 플러그인 등이 저장되는 경로를 설정
        `mkdir -p ./dags ./logs ./plugins`:
       - `mkdir`: 디렉토리를 생성
       - `-p`: 부모 디렉토리가 없으면 함께 생성합니다.
       - `./dags`: 현재 작업 디렉토리에 "dags"라는 디렉토리를 생성합니다. Airflow에서 DAG 파일을 저장하는 디렉토리
       - `./logs`: 현재 작업 디렉토리에 "logs"라는 디렉토리를 생성합니다. Airflow 로그 파일이 저장되는 디렉토리입니다.
       - `./plugins`: 현재 작업 디렉토리에 "plugins"라는 디렉토리를 생성합니다. Airflow 플러그인이 위치하는 디렉토리

    2) AIRFLOW_UID를 만들고 저장할 위치를 설정
    `echo -e "AIRFLOW_UID=$(id -u)\nAIRFLOW_GID=0" > .env`:
       - `echo`: 화면에 텍스트를 출력하는 명령어입니다.
       - `-e`: 이 옵션은 이스케이프 시퀀스 (예: `\n` 등)를 해석하도록 합니다.
       - `"AIRFLOW_UID=$(id -u)\nAIRFLOW_GID=0"`: 환경 변수 파일인 `.env`에 저장할 내용으로, 현재 사용자의 UID(사용자 ID)를 `AIRFLOW_UID`로 설정하고, `AIRFLOW_GID`를 0으로 설정합니다. `id -u`는 현재 사용자의 UID를 가져오는 명령어입니다.
       - `> .env`: 앞서 설정한 내용을 현재 디렉토리에 `.env` 파일로 저장합니다.

  7. 다시 서버실행 weare@DESKTOP-BE1I4GE:~/airflow-setup$ docker-compose -f docker-compose.yaml up
    airflow-webserver_1  | 127.0.0.1 - - [29/Dec/2023:13:06:38 +0000] "GET /health HTTP/1.1" 200 141 "-" "curl/7.74.0"
    airflow-webserver_1  | 127.0.0.1 - - [29/Dec/2023:13:06:48 +0000] "GET /health HTTP/1.1" 200 141 "-" "curl/7.74.0"
    airflow-webserver_1  | 127.0.0.1 - - [29/Dec/2023:13:06:58 +0000] "GET /health HTTP/1.1" 200 141 "-" "curl/7.74.0"
    airflow-webserver_1  | 127.0.0.1 - - [29/Dec/2023:13:07:08 +0000] "GET /health HTTP/1.1" 200 141 "-" "curl/7.74.0"
    airflow-webserver_1  | 127.0.0.1 - - [29/Dec/2023:13:07:18 +0000] "GET /health HTTP/1.1" 200 141 "-" "curl/7.74.0"
    airflow-webserver_1  | 127.0.0.1 - - [29/Dec/2023:13:07:28 +0000] "GET /health HTTP/1.1" 200 141 "-" "curl/7.74.0"
    정상동작 됨을 볼 수 있다.

  8. http://localhost:8080/ 접속 (포트 8080과 , id, pw :airflow 이고, 이는 전부 yaml파일에 설정돼있다.)

 

 

docker-compose.yaml 파일 내용분석

  • x-airflow-common

    `x-airflow-common`이라는 용어는 Apache Airflow의 DAG 정의에서 사용되는 확장(`x`) 속성 중 하나일 수 있습니다. DAG(Directed Acyclic Graph)는 Airflow에서 워크플로우를 정의하는 방식입니다.

    `x-airflow-common`은 일반적으로 Airflow DAG 정의에서 공통적으로 사용되는 설정이나 속성을 담기 위한 사용자 정의 확장 속성입니다. 이 속성을 사용하면 여러 DAG에서 공유되는 설정이나 로직을 중복해서 정의하지 않고 한 번에 관리할 수 있습니다.

    예를 들어, 여러 DAG에서 공통적으로 사용되는 설정이 있다면 이를 `x-airflow-common` 속성으로 정의하고, 각 DAG에서 이를 참조하여 사용할 수 있습니다.

    아래는 간단한 DAG 정의에서 `x-airflow-common`이 어떻게 사용될 수 있는지의 예시입니다:

    ```yaml
    # 예시 DAG 정의
    default_args:
      owner: 'airflow'
      start_date: days_ago(1)

    x-airflow-common:
      retries: 3
      retry_delay:
        minutes: 5

    tasks:
      - task_id: task1
        bash_command: 'echo "Hello, World!"'
    ```

    위의 예시에서 `x-airflow-common` 속성은 `retries` 및 `retry_delay`와 같은 일반적으로 여러 곳에서 사용되는 설정을 담고 있습니다. 이렇게 하면 `tasks` 내의 각 태스크에서 이 속성을 참조하여 사용할 수 있습니다.


  • airflow에서 x-airflow-common 의 실제예

     1) &airflow-common 아래 내용을 airflow-common으로 지정
     2) _PIP_ADDITIONAM_REQUIREMENTS : 설치해야할 파이썬 모듈 이름들 지정
     실행할때마다 모듈이 지워지는데 재설치할 수고가 적어짐, 모든 컨테이너에 모듈이 설치 돼서 모듈오류가 줄어듬
     3) {AIRFLOW_PROJ_DIR:-.} : airflow yaml 파일이 있는 폴더의 이름

모듈 추가방식

  • airflow-scheduler 서비스

     1) <<: *airflow-common : 아까 &airflow-common 로 지정했던것 사용
     2) airflow-init ~ : condition 충족하면 실행

networks

  • 프론티어와 백티어로 나눔
  • 왜냐하면 각각의 서비스가 다른 네트워크에 속함으로써 서비스 간의 통신을 조절하거나, 보안을 강화하거나, 다양한 다른 설정을 적용할 수 있다.

 

volume

  • 계속해서 데이터를 저장해야 하는곳에 쓰임
  • 아래의경우 postgresql를 docker volume으로 지정하려면
    volumes:
    # 지속적으로 내용이 유지됨
      db-data:

  • db-data:/var....
  • volume id: postgresql의 데이터저장위치


vote 서비스 개선

  • command ~ : 원래 동작(이미지 dockerfile의 cmd)을 덮어쓰고(오버라이드) 원하는 커맨드를 추가
    +entrypoint ~ : 이미지 dockerfile의 entrypoint를 덮어씀
  • depends_on ~: 이상적인 실행순서 지정
  • healthcheck ~: 서비스의 실행 컨디션이 좋은지 판단 (test로 주어진 명령을, 15초마다 실행,응답이 5초이상이면 실패고, 3번더 재시도 해보고, 실패판단, 10초후에 healthcheck 시작) 반환값이 0이면 성공, 1이면 실패
  • volumes ~:  보트쪽 폴더:도커컨테이너쪽 폴더 -> 두개 연결(매핑)

 

db 서비스 개선

+environment : environment  안에서 기술한 서비스가 컨테이너 안에서 실행될 때, 환경변수들을 지정
입력하는 방식의 차이

 

worker 서비스 개선

  • build에서 context 를 ./myapp -> ./worker로 덮어씀(오버라이드) 

 

목표 : postgres 로그인 정보를, docker-compose.yml 파일에 넣어 넘겨주는 실습을 진행 

 

 

실습진행

 

  1. 깃에서 실습파일 다운
    weare@DESKTOP-BE1I4GE:~$ git clone https://github.com/learndataeng/example-voting-app.git
    Cloning into 'example-voting-app'...
    remote: Enumerating objects: 1087, done.
    remote: Total 1087 (delta 0), reused 0 (delta 0), pack-reused 1087
    Receiving objects: 100% (1087/1087), 1.14 MiB | 21.26 MiB/s, done.
    Resolving deltas: 100% (407/407), done.
  2. 해당 파일로 이동
    weare@DESKTOP-BE1I4GE:~$ cd example-voting-app
  3. 파일 안에 yml 파일 빌드
    weare@DESKTOP-BE1I4GE:~/example-voting-app$ docker-compose -f docker-compose.mac.yml build
    중략
    +만약 worker가 빌드가 안되고, 그 이유가 Buildx 미설치로 인한 에러라면 
    https://allofdater.tistory.com/37 를 참조한다.

  4. 만들어진 이미지 확인
    weare@DESKTOP-BE1I4GE:~/example-voting-app$ docker images
    REPOSITORY                   TAG         IMAGE ID       CREATED             SIZE
    example-voting-app_worker    latest      79f4f5ff65ba   36 minutes ago      194MB
    example-voting-app_result    latest      21441b000470   37 minutes ago      220MB
    example-voting-app_vote      latest      68b2f101195b   37 minutes ago      145MB

  5. yml파일 빌드 수행
    weare@DESKTOP-BE1I4GE:~/example-voting-app$ docker-compose -f docker-compose.mac.yml build
    redis uses an image, skipping
    db uses an image, skipping
    Building vote
    [+] Building 7.1s (11/11) FINISHED

  6. 프로젝트에 정의된 모든 서비스의 이미지를 최신 버전으로 업데이트하고, 공식 이미지 postgres, redis를 받아옴
    weare@DESKTOP-BE1I4GE:~/example-voting-app$ docker-compose -f docker-compose.mac.yml pull

  7. 다시 이미지를 확인하면 postgres, redis 두개가 추가 돼있음
    weare@DESKTOP-BE1I4GE:~/example-voting-app$ docker images
    REPOSITORY                   TAG         IMAGE ID       CREATED          SIZE
    example-voting-app_worker    latest      79f4f5ff65ba   43 minutes ago   194MB
    example-voting-app_result    latest      21441b000470   44 minutes ago   220MB
    example-voting-app_vote      latest      68b2f101195b   44 minutes ago   145MB
    postgres                     15-alpine   c94362bdb5ee   2 weeks ago      240MB
    redis                        alpine      d2d4688fcebe   3 weeks ago      41MB

  8. 빌드하고, 컨테이너만들고, 컨테이너실행 3가지를 한번에 하는 명령어 docker-compose up
    weare@DESKTOP-BE1I4GE:~/example-voting-app$ docker-compose up
    (중략)
    vote_1    | 127.0.0.1 - - [29/Dec/2023 07:23:44] "GET / HTTP/1.1" 200 -
    vote_1    | 127.0.0.1 - - [29/Dec/2023 07:23:59] "GET / HTTP/1.1" 200 -

  9. 동작 확인
    윈도우 
    http://localhost:5000/
    http://localhost:5001/
    둘다 접속(맥은 5001,5002로 들어갈것)
  10. 실행중인 컨테이너 확인
    weare@DESKTOP-BE1I4GE:~/example-voting-app$ docker-compose ps
               Name                          Command                  State                         Ports
    ------------------------------------------------------------------------------------------------------------------------
    example-voting-app_db_1       docker-entrypoint.sh postgres    Up (healthy)   5432/tcp
    example-voting-app_redis_1    docker-entrypoint.sh redis ...   Up (healthy)   6379/tcp
    example-voting-app_result_1   nodemon server.js                Up             0.0.0.0:5858->5858/tcp,:::5858->5858/tcp,
                                                                                  0.0.0.0:5001->80/tcp,:::5001->80/tcp
    example-voting-app_vote_1     python app.py                    Up (healthy)   0.0.0.0:5000->80/tcp,:::5000->80/tcp
    example-voting-app_worker_1   dotnet Worker.dll                Up

  11. 사용자를 postgres로 지정하고, example-voting-app_db_1 의 shell을 연다.
    weare@DESKTOP-BE1I4GE:~/example-voting-app$ docker exec -it --user=postgres example-voting-app_db_1 sh

  12. whoami를 통해 postgres 계정에 들어와 있음을 확인
    / $ whoami
    postgres

  13.  psql 설치된것 확인
    / $ psql
    psql (15.5)
    Type "help" for help.

  14. 현재 연결된 db와 유저이름
    postgres=# \c
    You are now connected to database "postgres" as user "postgres".

  15. 현재 데이터베이스에 있는 테이블 목록을 나열
    postgres=# \dt
             List of relations
     Schema | Name  | Type  |  Owner
    --------+-------+-------+----------
     public | votes | table | postgres
    (1 row)

  16. votes 내용 확인
    postgres=# SELECT * FROM votes;
           id        | vote
    -----------------+------
     161e7795c8e92b7 | a
    (1 row)

  17. 종료
    postgres=# exit
    / $ exit


    p.s 
    +종료 후 yml 내려본다.
    weare@DESKTOP-BE1I4GE:~/example-voting-app$ docker-compose -f docker-compose.mac.yml down
    Stopping example-voting-app_worker_1 ... done
    Stopping example-voting-app_vote_1   ... done
    Stopping example-voting-app_result_1 ... done
    Stopping example-voting-app_redis_1  ... done
    Stopping example-voting-app_db_1     ... done
    Removing example-voting-app_worker_1 ... done
    Removing example-voting-app_vote_1   ... done
    Removing example-voting-app_result_1 ... done
    Removing example-voting-app_redis_1  ... done
    Removing example-voting-app_db_1     ... done
    Removing network example-voting-app_default
    WARNING: Network example-voting-app_default not found.

    + 컨테이너 지워 졌는지 확인
    weare@DESKTOP-BE1I4GE:~/example-voting-app$ docker ps
    CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

    + down은 컨테이너만 지우고 이미지는 지우지 않음을 알 수있음.
    weare@DESKTOP-BE1I4GE:~/example-voting-app$ docker images
    REPOSITORY                   TAG         IMAGE ID       CREATED         SIZE
    example-voting-app_worker    latest      79f4f5ff65ba   2 hours ago     194MB
    example-voting-app_result    latest      21441b000470   2 hours ago     220MB
    example-voting-app_vote      latest      68b2f101195b   2 hours ago     145MB
    <none>                       <none>      814c986a34da   2 hours ago     220MB
    <none>                       <none>      f220bc028f32   2 hours ago     145MB
    node                         18-slim     d3cce7487840   9 days ago      196MB
    postgres                     15-alpine   c94362bdb5ee   2 weeks ago     240MB
    redis                        alpine      d2d4688fcebe   3 weeks ago     41MB
    python                       3.9-slim    4fd8d6bf114c   2 months ago    126MB
    multiarch/qemu-user-static   latest      3539aaa87393   11 months ago   305MB

에러내용

Building worker failed to fetch metadata: fork/exec /usr/local/lib/docker/cli-plugins/docker-buildx: no such file or directory DEPRECATED: The legacy builder is deprecated and will be removed in a future release. Install the buildx component to build images with BuildKit: https://docs.docker.com/go/buildx/ Sending build context to Docker daemon 10.24kB Step 1/13 : FROM --platform=${BUILDPLATFORM} mcr.microsoft.com/dotnet/sdk:7.0 as build failed to parse platform : "" is an invalid component of "": platform specifier component must match "^[A-Za-z0-9_-]+$": invalid argument

 

배경 : 깃허브의 도커 이미지를 받아서, 빌드할때 Docker Buildx를 설치하라는 에러 발생.


원인 : 빌드하려는 도커 이미지에 Docker Buildx가 필요한 내용이 있었다.

해결과정

  1. sudo install Docker Buildx 명령이 먹히지 않았다.
  2. Buildx를 설치하기 위해서는 git에서 다운로드해야 했다.
  3. 우선 플러그인을 저장할 경로를 만들어준다.
    # 현재 사용자의 홈 디렉토리(~/) 내에 .docker/cli-plugins/ 디렉토리를 생성
    # -p   부모 디렉토리를 만들면서 중간에 필요한 디렉토리가 없으면 생성
    mkdir -p ~/.docker/cli-plugins/

  4. 깃에서 Buildx 다운로드
    # wget: 웹에서 파일을 다운, 다운로드한 파일을, 이름을 지정해(-O)  만든 경로에 저장wget https://github.com/docker/buildx/releases/download/v0.7.1/buildx-v0.7.1.linux-amd64 -O ~/.docker/cli-plugins/docker-buildx

    # chmod파일 권한을 변경, 모든 사용자(a+x)에게 실행 권한을 부여
    chmod a+x ~/.docker/cli-plugins/docker-buildx

  5. 이제 빌드가 실패한 이미지가 있다면 다시 실행해주면된다.

docker-compose란

  • 여러 도커 컨테이너를 정의하고 컨테이너들 간의 환경설정, 의존성, 포트매핑, 네트워크, 실행 등을 관리하는 도구
  • 이러한 설정 파일은 YAML 형식으로 작성되며, 컨테이너, 네트워크, 볼륨 등과 관련된 설정을 포함
    docker-compose.yml ,   docker-compose.yaml
  • 개별 컨테이너를 따로 관리하는거보다 효율적이다.
  • 개발 환경 (dev), 테스트 환경 (test), 운영 환경 (prod) 등 다양한 버전으로 만든다.

docker-compose 관련명령어

  • docker-compose up: 설정된 서비스들을 시작합니다. ( build->create->start 3단계 다있음)
  • docker-compose down: 실행 중인 서비스들을 중지하고 관련된 리소스를 삭제합니다. (stop +rm : 멈추고 삭제)
  • docker-compose ps: 현재 실행 중인 서비스들의 상태를 표시합니다.
  • docker-compose logs: 서비스들의 로그를 표시합니다.
  • docker-compose build : 정의된 서비스들의 이미지를 빌드
  • docker-compose pull : 정의된 서비스들에 대한 이미지를 Docker Hub 또는 지정된 레지스트리에서 가져옴
  • docker-compose start : 명령어는 정의된 서비스들을 시작
  • docker-compose stop : 실행 중인 서비스들을 중지
  • docker-compose rm : 정의된 서비스들과 관련된 컨테이너, 네트워크, 볼륨 등을 삭제합니다. -v 옵션을 추가하면 관련된 볼륨도 함께 삭제
  • docker-compose push : docker hub로 이미지들을 올림
  • docker compose = docker-compose
  • docker-compose.yaml = docker-compose.yml (둘다 존재하면 에러 발생하니 주의)

+ 만약 다른 이름의 파일 사용하고 싶으면 docker-compose -f docker-compose.mac.yml up (-f 사용)
보통 이렇게 쓰임
docker-compose.prod.yml (프로덕션용) , docker-compose.dev.yml (개발용) , docker-compose.test.yml (테스트용)
프로덕션 : 실제운영환경/ 개발 :개발하고 디버깅 / 테스트 : 버그 찾아내고 테스트

 

docker-compose 설치

  • docker desktop의 일부로 자동 설치됨
  • docker engine 실행하고 터미널에서 버전 확인
  • docker-compose --version

docker-compose.yml 파일구성

  1. **`services`:**
       - `services` 섹션은 여러 개의 컨테이너 서비스를 정의합니다. 각 서비스는 독립적으로 실행되는 컨테이너를 나타냅니다. 각 서비스에는 사용할 도커 이미지, 포트 매핑, 환경 변수 등을 설정할 수 있습니다.

       services:
         web:
           image: nginx:latest
           ports:
             - "8080:80"
         database:
           image: postgres:latest
           environment:
             POSTGRES_PASSWORD: example

  2.  **`volumes`:**
       - `volumes` 섹션은 볼륨을 정의합니다. 볼륨은 컨테이너 간 데이터를 공유하거나 데이터를 영속적으로 저장하는 데 사용됩니다. 여러 서비스 간에 데이터를 공유하거나 컨테이너 내부의 데이터를 호스트와 분리하는 데 활용됨

       volumes:
         data-volume:

       볼륨은 `services` 섹션에서 각 서비스의 `volumes` 옵션을 통해 연결할 수 있습니다.

  3.  **`networks`:**
       - `networks` 섹션은 네트워크를 정의합니다. 여러 컨테이너 간의 통신을 위한 네트워크를 설정할 수 있습니다. 기본적으로 `docker-compose`는 기본 네트워크를 생성하며, 추가적으로 정의된 네트워크를 사용할 수 있습니다.

       networks:
         frontend:
         backend:

       네트워크는 `services` 섹션에서 각 서비스의 `networks` 옵션을 통해 연결할 수 있습니다. 이를 통해 서비스 간에 특정 네트워크를 통한 통신이 가능해집니다.

    이러한 섹션들을 조합하여 `docker-compose.yml` 파일을 작성하면 여러 개의 컨테이너로 구성된 멀티-컨테이너 애플리케이션을 쉽게 정의하고 실행할 수 있습니다.

+여기다 서버를 각각 따로 구성하려면 networks도 추가

 

docker 관련 명령 동작 예시

  • docker images : 이미지들을 출력.
    'docker-compose build' 시 폴더 이름(example/voting/app) 이 앞에 첨자로 붙어 출력된다.
    +다른방법으로 빌드 됐거나, 도커 허브에서 온경우 첨자가 붙지 않는다.
  • docker-compose images : 컨테이너들을 출력
  • docker-compose push : docker hub로 이미지들을 올림(허브에서 온애들 안올림)

  • docker-compose ls (그룹별로 보여줌)
  • docker-compose ps(그룹내 각각 보여줌)

 

  • docker network ls (bridge, host, none)

+Bridge 모드는 Docker의 기본 네트워크 모드이며, 컨테이너를 위한 가상 브리지를 생성합니다. 이 가상 브리지는 호스트 시스템과 컨테이너 간의 통신을 도와줍니다.
   - **특징:**
     - 컨테이너 간 통신을 지원합니다.
     - 각 컨테이너는 가상 브리지에 연결되어 호스트와 격리됩니다.
   docker run --network=bridge my-container

Host 모드는 호스트의 네트워크 네임스페이스를 공유하는 방식으로 동작합니다. 컨테이너는 호스트의 네트워크 인터페이스를 직접 사용하게 됩니다.
   - **특징:**
     - 호스트와 동일한 네트워크 네임스페이스를 공유하므로 호스트와 동일한 IP 주소를 사용합니다.
     - 호스트와 완전히 통합되어 있는데, 이는 네트워크 격리를 해제하는 효과가 있습니다.
   docker run --network=host my-container

None 모드는 네트워크를 사용하지 않는 방식으로, 컨테이너는 네트워크를 가지지 않습니다. 따라서 외부와의 통신이 차단
   - **특징:**
     - 외부와 통신이 필요하지 않은 경우에 사용됩니다.
     - 컨테이너는 외부 네트워크와 격리되며, 내부에서만 동작합니다.
   docker run --network=none my-container

 

+ Recent posts