[Docker] Docker Compose : Multiple Environment

2023. 7. 28. 19:38·DevOps/Docker & Kubernetes
목차
  1. 1. Deploy Multiple Applications
  2. 2. Override file
  3. 3. Environment variation & Secret value
  4. 4. Extended Field
  5. 5. Setting workflow
  6. 6. Practice
📕 목차

1. Deploy Multiple Applications
2. Override file
3. Environment variation & Secret value
4. Extended Field
5. Setting workflow
6. Practice

1. Deploy Multiple Applications

 

📌 As-is

같은 Application을 다시 실행해도 Application이 두 개가 실행되지는 않는다.

  • Docker가 운영 환경에 상관 없이 Application을 실행할 수는 있지만, 운영 환경마다 다르게 Application을 동작시키는 것은 다른 문제다.
  • Application을 개발 환경과 테스트 환경, 운영 환경 다르게 구동해야 하는 경우가 있다.
    • 운영 환경은 1.5 버전
    • 핫픽스 테스트 환경은 1.5.1 버전
    • 사용자 테스트 환경은 1.6 버전
    • 시스템 테스트 환경은 1.7 버전

참고로 Scaling 기능이 필요 없고, 운영 환경만큼의 성능을 요구하지 않는 비운영 환경이야 말로 Docker compose가 활약할 수 있는 환경이다.

 

📌 Docker resource가 종속된 Application 구분
💡 Docker compose는 Lable 명명 규칙에 따라 Application에 속한 Docker resource를 구분한다.
(project_name)_(service_name)_(number)
  • 프로젝트(Project) : Docker resource가 어떤 Application의 일부인지 아닌지를 판단하기 위해 Docker compose가 사용하는 개념
    • project name : 기본값으로 Docker compose 파일이 들어있던 디렉토리명
    • service name : Compose 파일에 정의된 service 이름으로 DNS 상의 domain 이름으로도 쓰인다.
    • number : Container의 경우 번호를 부여

예를 들어, Docker compose가 Docker resource를 만들 때 다음과 같은 과정을 거치게 된다.

  1. project name을 resource 이름의 접두사로 붙인다.
    • directory가 app1이고, compose에 정의된 service가 web, volume이 disk인 경우
      • app1_web
      • app1_disk
  2. Container인 경우 번호를 접미사로 붙여 scaling에 대응할 수 있다.
    • app1_web_1, 다음에 추가되는 Container는 app1_web_2가 된다.

 

🟡 프로젝트 이름 바꾸어 실행하기

docker-compose -f .\todo-list\docker-compose.yml -p todo-test up -d

docker container ls

# Container가 공개된 port 번호 확인
docker container port todo-test-todo-web-1 80

  • -p : Docker compose에서 project name을 명시해주는 옵션
  • 하나의 Compose 파일로 project name만 바꾸면 여러 개의 Application을 실행할 수 있다.
    • docker container port 부명령으로 임의로 공개된 port 번호를 알아낼 수 있다.
    • 무작위로 정해진 공개 port를 일일이 찾아내야 해서 번거롭다.

 


2. Override file

 

📌 Override

# docker-compose.yml
services:
  todo-web:
    image: diamol/ch06-todo-list:v2
PS C:\Users\qud12\docker\080258\ch10\exercises> cat .\todo-list\docker-compose.yml
version: "3.7"

services:
  todo-web:
    image: diamol/ch06-todo-list
    ports:
      - 80
    environment:
      - Database:Provider=Sqlite
    networks:
      - app-net
# Override file
services:
  todo-web:
    image: diamol/ch06-todo-list:v2
  • 각 설정 또는 환경마다 Compose 파일을 두는 방법은 유지보수 측면에서 바람직하지 않다.
  • 모든 환경에서 공통으로 쓰이는 속성이 정의된 docker-compose.yml을 Overriding 하는 방식을 사용할 수 있다.
  • Docker compose는 여러 파일을 합쳐서 Compose 파일을 구성하여, 나중에 지정된 파일 내용을 기존 파일에 덮어쓴다.

 

📌 Compose 파일 병합
docker-compose -f .\todo-list\docker-compose.yml -f .\todo-list\docker-compose-v2.yml config

  • Override할 Compose 파일에는 해당 환경에서 변경할 항목만 기술하면 된다.
    • 기존 Compose 파일 구조를 유지해야 Dockcer compose가 두 정의를 연결지을 수 있다.
  • Docker compose는 하나 이상의 파일이 인자로 지정되면 두 파일을 병합한다.
    • 인자로 받은 순서대로 병합한다.
  • config : 입력 파일 내용이 유효한 경우에만 최종 출력을 보여준다. (실행하지는 않는다.)

 

📌 실전 응용 사례
services:
  numbers-api:
    image: diamol/ch08-numbers-api:v3
    networks:
      - app-net

  numbers-web:
    image: diamol/ch08-numbers-web:v3
    environment:
      - RngApi__Url=http://numbers-api/rng
    networks:
      - app-net

networks:
  app-net:
  •  docker-compose.yml
    • 기본이 되는  Compose 파일
    • 웹 및 API 정의가 되어있으나 port나 Docker network 정의는 없다.
services:
  numbers-api:
    ports:
      - "8087:80"
    healthcheck:
      disable: true

  numbers-web:
    entrypoint:
      - dotnet
      - Numbers.Web.dll
    ports:
      - "8088:80"

networks:
  app-net:
    name: numbers-dev
  • docker-compose-dev.yml
    • 개발 환경 대상 설정
    • Dokcer network와 Service 공개 port를 정의
    • health & dependency check 비활성화
    • 개발자들이 빠르게 Application을 실행하는 것을 목적으로 한다.
services:
  numbers-api:
    healthcheck:
      interval: 20s
      start_period: 15s
      retries: 4

  numbers-web:
    ports:
      - "8080:80"
    restart: on-failure
    healthcheck:
      test: ["CMD", "dotnet", "Utilities.HttpCheck.dll", "-t", "250"]
      interval: 20s
      timeout: 10s
      retries: 4
      start_period: 10s

networks:
  app-net:
      name: numbers-test
  • docker-compose-test.yml 
    • 테스트 환경 대상 설정
    • Docker network를 정의
    • health check를 설정하고, Web service 공개 port를 정의
    • API service port는 공개하지 않는다.
version: "3.7"

services:
  numbers-api:
    healthcheck:
      interval: 10s
      retries: 2
    restart: always
    ports:
      - "8090:80"

  numbers-web:
    restart: always
    ports:
      - "80:80"
    healthcheck:
      interval: 10s
      retries: 2

networks:
  app-net:
    name: numbers-uat
  • docker-compose-uat.yml
    • 사용자 인수 테스트 환경 대상 설정
    • Docker network, Web service 80 port 설정
    • Service 에러 시, 항상 재시작하도록 설정
    • health check를 더 꼼꼼하게 하도록 설정

 

🟡 실행해보기

환경마다 다른 port 번호를 사용하므로 여러 개의 Application을 단일 Docker Host에서 실행할 수 있다.

docker-compose -f .\numbers\docker-compose.yml -f .\numbers\docker-compose-dev.yml -p numbers-dev up -d

docker-compose -f .\numbers\docker-compose.yml -f .\numbers\docker-compose-test.yml -p numbers-test up -d

docker-compose -f .\numbers\docker-compose.yml -f .\numbers\docker-compose-uat.yml -p numbers-uat up -d

  • 개발 팀에서는 이들 모두를 한 Server에서 실행할 수 있다.
  • port를 다르게 하여 자신의 업무와 관련된 환경에 접근해서 작업하면 된다.
  • 자신의 Network에 속한 API Container와만 통신 가능하므로 세 환경의 Application은 서로 독립적이다.
    • 같은 Docker network에 속해있지 않으면 Domain name으로 식별할 수 없다.

 

🟡 Container 제거

# 실패
docker-compose down

# 실패
docker-compose -f .\numbers\docker-compose.yml -f .\numbers\docker-compose-test.yml down

# 성공
docker-compose -f .\numbers\docker-compose.yml -f .\numbers\docker-compose-test.yml -p numbers-test down
  1. project가 기본값으로 지정한 resource 식별값에 매칭되는 값을 찾지 못하므로 실패한다.
  2. 'numbers-numbers-web-1'과 'numbers-numbers-api-1'이라는 Container가 없으므로 제거 되었다고 판단하여 명시적으로 이름이 지정된 Network를 제거하려 시도하지만, 아직 Container가 연결되어 있으므로 실패한다.
  3. 'number-test-numbers-web-1' Container와 API Container 또한 정상적으로 제거하고 Network를 제거한다.

  • 테스트 환경의 Application을 종료하기 위해서는 해당 환경의 Container와 Network를 제거해야 한다.
  • Project name을 명시적으로 변경했으므로 모든 파일과 project 정보를 정확히 지정해야 한다.
  • Override file 관리에 드는 오버헤드를 고려하여, Application 배포 및 폐기 스크립트 작성과 자동화를 익혀라.

 


3. Environment variation & Secret value

 

📌 Application setting
# secret.js
{
    "ConnectionStrings": {
      "ToDoDb": "Server=todo-db;Database=todo;User Id=postgres;Password=postgres;"
    }
}
# 코어 Compose 파일
services:
  todo-web:
    image: diamol/ch06-todo-list
    secrets:
      - source: todo-db-connection
        target: /app/config/secrets.json
  • Container의 환경 차이는 Override file을 통해 기술할 수 있지만, Application setting은 Environment variation이나 setting file의 값으로 주입할 수 있다.
  • secret value는 Docker compose, Docker swarm, Kubernetes 모두 지원하는 기능이다.
    • secret value 원본 위치 : Container Runtime이 secret value를 읽어오는 경로
    • secret value 대상 위치 : Container 안에서 secret value가 위치할 경로
  • secret source를 명시했으면 해당 secret value가 Compose 파일에 명시되어 있어야 한다.

 

🟡 Override file

# Override file
services:
  todo-web:
    ports:
      - 8089:80
    environment:
      - Database:Provider=Sqlite
    env_file:
      - ./config/logging.debug.env

secrets:
  todo-db-connection:
    file: ./config/empty.json
# ./config/logging.debug.env
Logging__LogLevel__Default=Debug
Logging__LogLevel__System=Debug
Logging__LogLevel__Microsoft=Debug
  • environment
    • Container 안에서만 사용되는 Envirionment variation을 직접 추가한다.
    • 해당 환경 변수 값을 적용하면 데이터베이스로 Sqlite를 사용한다.
    • 평문 텍스트로 작성되므로 API key나 DB 접속 정보 같은 민감한 정보는 사용하지 않는 것이 좋다.
  • env_file
    • 텍스트 파일의 경로를 값으로 읽는다.
    • 변수 이름과 값을 등호(=)로 구분해 한 줄에 하나씩 정의한다.
    • 같은 Environment variation을 여러 Component에서 공유해 사용할 수 있다.
    • Service 간에 공유하는 설정이 많은 경우 유용하다.
    • 원격 컴퓨터에서 실행 중인 Docker engine을 다룰 때도 Local PC 설정값을 적용할 수 있다.
  • secrets
    • Compose 파일 최상위 프로퍼티 중 하나
    • secret source로 명시한 실제 값 혹은 경로가 정의된다.
    • Container Runtime 과정에서 적용 가능하다.
    • 민감한 정보가 유출될 우려가 없기 때문에 유연성 면에서 가장 뛰어나다.

 

🟡 실행해보기

docker-compose -f .\todo-list-configured\docker-compose.yml \
-f .\todo-list-configured\docker-compose-dev.yml \
-f .\todo-list-configured\docker-compose-dev-windows.yml -p todo-dev up -d

curl http://localhost:8089/list

docker container logs --tail 10 todo-dev-todo-web-1

Application이 실행한 SQL 쿼리까지 보인다.

 

📌 Host PC의 환경변수 전달하기
# override file
services:
  todo-web:
    ports:
      - "${TODO_WEB_PORT}:80"
    environment:
      - Database:Provider=Postgres
    env_file:
      - ./config/logging.information.env
    networks:
      - app-net

  todo-db:
    image: diamol/postgres:11.5
    ports:
      - "${TODO_DB_PORT}:5432"
    networks:
      - app-net

networks:
  app-net:
    name: todo-test

secrets:
  todo-db-connection:
    file: ./config/secrets.json
  • Compose 파일을 수정하지 않아도 환경 변수만 바꾸면 다른 테스트 환경을 만들어낼 수 있다. (이식성 증가) 

 

✨ .env

# 컨테이너 설정값 - 공개포트
TODO_WEB_PORT=8877
TODO_DB_PORT=5432

# 도커 컴포즈 실행 옵션 - 컴포즈 파일 지정, 프로젝트 이름
COMPOSE_PATH_SEPARATOR=;
COMPOSE_FILE=docker-compose.yml;docker-compose-test.yml
COMPOSE_PROJECT_NAME=todo_ch10

  • Compose가 Application을 실행할 때 대상 directory에서 .env 파일을 발견하면 환경 파일로 간주한다.
  • Compose는 .env 파일로부터 환경 변수를 읽어 Application을 실행하기 전에 먼저 적용한다.
  • 내용을 조금만 바꾸면 다른 환경에도 적용 가능하다.

 


4. Extended Field

 

📌 확장 필드(Extended Field)
  • Service 간 많은 설정값을 공유하는 Compose file이 너무 커지는 문제를 해소하기 위해 쓴다.
  • YAML의 여러 블록을 한곳에서 정의하는 기능이다.
  • Compose 파일 전체에 걸쳐 해당 블록을 재사용하는 효과를 얻을 수 있다.
  • 최상위 블록 외부라면 어디서든 정의할 수 있으며, 이름에 앰퍼샌드 문법을 사용한다.
  • 일종의 사용자 정의 필드다.

그런데 그리 널리 쓰이는 기능은 아니라고 한다.

 

x-logging: &logging
  logging:
    options:
      max-size: '100m'
      max-file: '10'

x-labels: &labels
  app-name: image-gallery
  • 확장 필드 블록은 관습적으로 기존 블록에 'x-'를 접두어로 붙여 쓴다.
  • logging 블록은 logging 속성을 명시했으므로 serivce 정의에 바로 사용할 수 있다.
  • labels 블록은 labels 속성을 명시하지 않았으므로 labels 필드 내에서 사용할 수 있다.

 

services:
  accesslog:
    <<: *logging
    labels:
      <<: *labels

  iotd:
    ports:
      - 8080:80
    <<: *logging
    labels:
      <<: *labels
      public: api

  • <<:*필드명 : YAML 병합 문법
  • 해당 위치에 확장 필드값이 병합된다.

하지만 이 또한 여러 Compose 파일에 한꺼번에 적용할 수는 없다. (Override해서 확장 필드를 쓸 수는 없다.)

이는 Compose의 한계라기 보다는 YAML 포맷의 한계에 가깝다.

 


5. Setting workflow

 

📌 환경을 분리하는 핵심 목적

1️⃣ Application 구성 요소의 조합

  • 모든 환경에서 전체 스택을 실행할 필요는 없으니, 필요한 요소만 선택할 수 있다.
    • 개발자는 모니터링을 위한 대시보드를 제외할 수 있다. 
    • 테스트 환경에서는 Container에서 실행한 DB를 사용하고, 운영 환경에서는 Cloud DB를 사용하도록 선택할 수 있다.
  • Override 파일을 사용하면 공통된 Service를 제외하고, 환경마다 Service를 다르게 설정할 수 있다.

 

2️⃣ Container 설정

  • 각 환경의 상황과 요구 사항에 맞추어 설정을 바꿀 수 있다.
    • 공개 포트는 다른 Container와 충돌하지 않아야 한다.
    • Volume 경로는 테스트 환경에선 Local drive를 사용하겠지만, 운영 환경에서는 공유 Storage가 될 것이다.
  • Override 파일과 Docker network로 각 Application을 분리하여 단일 서버에 여러 개의 Application을 실행할 수 있다.

 

3️⃣ Application 설정

  • Environment 별로 Container 내부 동작을 다르게 할 수 있다.
  • Override 파일과 secret value를 이용해 상황에 맞는 Application 설정 값을 Container에 주입할 수 있다.

 

📌 Workflow
💡 같은 Image가 모든 환경에서 Container Platform에서 제공된 설정값에 따라 동작한다.
  1. Build process를 거친다.
  2. 자동화 테스트를 수행하여 통과하면 특정 태그가 부여된 Container Image가 생성된다.
  3. 해당 Image를 Compose 파일에 설정된 값으로 빌드 검증 테스트(sanity test) 환경에 배포한다.
  4. 빌드 검증 테스트에 통과하면 다음 환경(다른 compose 파일 설정값 주입)으로 넘어간다.
  5. 모든 테스트를 통과하면 Docker Swarm이나 Kubernetes 배포 manifest로 운영 환경에 Image를 배포한다.

 


6. Practice

 

개발 환경과 테스트 환경을 하나의 Host PC에서 실행하라

 

개발 환경을 docker-compose up 명령의 기본값으로 삼아라

  • 로컬 파일 데이터베이스 사용
  • 8089번 포트 공개
  • to-do application v2 버전 실행

 

테스트 환경은 프로젝트 이름과 특정 컴포즈 파일을 지정해 실행하라

  • 별도의 데이터베이스 Container 사용
  • 데이터베이스 스토리지를 위한 볼륨 사용
  • 8080번 포트 공개
  • to-do Application 최신 버전 실행

 

# dev env
docker-compose up -d

# test env
docker-compose -f .\docker-compose.yml -f .\docker-compose-test.yml -p ch10-lab-test up -d

 

🟡 docer-compose.yml

services:
  todo-web:
    image: diamol/ch06-todo-list
    secrets:
      - source: todo-db-connection
        target: /app/config/secrets.json

 

🟡 docker-compose-dev.yml

services:
  todo-web:
    image: diamol/ch06-todo-list:v2
    ports:
      - 8089:80
    environment:
      - Database:Provider=Sqlite

secrets:
  todo-db-connection:
    file: empty.json

 

🟡 .env

# 컨테이너 설정값 - 공개포트
TODO_WEB_PORT=8089
TODO_DB_PORT=5432

# 도커 컴포즈 실행 옵션 - 컴포즈 파일 지정, 프로젝트 이름
COMPOSE_PATH_SEPARATOR=;
COMPOSE_FILE=docker-compose.yml;docker-compose-dev.yml
COMPOSE_PROJECT_NAME=todo

 


🟡 docker-compose-test.yml

services:
  todo-web:
    ports:
      - "8080:80"
    environment:
      - Database:Provider=Postgres
    networks:
      - app-net

  todo-db:
    image: diamol/postgres:11.5
    environment:
      - PGDATA=/data
    ports:
      - "5433:5432"
    volumes:
      - "todo-database:/data"
    networks:
      - app-net

networks:
  app-net:
    name: todo-test

secrets:
  todo-db-connection:
    file: postgres-connection.json

volumes:
  todo-database:

 

🟡 postgres-connection.json

{
    "ConnectionStrings": {
      "ToDoDb": "Server=todo-db;Database=todo;User Id=postgres;Password=postgres;"
    }
}

 

저작자표시 비영리 (새창열림)
  1. 1. Deploy Multiple Applications
  2. 2. Override file
  3. 3. Environment variation & Secret value
  4. 4. Extended Field
  5. 5. Setting workflow
  6. 6. Practice
'DevOps/Docker & Kubernetes' 카테고리의 다른 글
  • [Docker] Nginx 구성과 HTTPS 설정
  • [Docker] Application Build & Test with Docker & Docker compose
  • [Docker] Container monitoring
  • [Docker] Health check & Dependency check
나죽못고나강뿐
나죽못고나강뿐
싱클레어, 대부분의 사람들이 가는 길은 쉽고, 우리가 가는 길은 어려워요. 우리 함께 이 길을 가봅시다.
  • 나죽못고나강뿐
    코드를 찢다
    나죽못고나강뿐
  • 전체
    오늘
    어제
    • 분류 전체보기 (458)
      • Computer Science (60)
        • Git & Github (4)
        • Network (17)
        • Computer Structure & OS (13)
        • Software Engineering (5)
        • Database (9)
        • Security (5)
        • Concept (7)
      • Frontend (21)
        • React (13)
        • Android (4)
        • iOS (4)
      • Backend (77)
        • Spring Boot & JPA (50)
        • Django REST Framework (14)
        • MySQL (8)
        • Nginx (1)
        • FastAPI (4)
      • DevOps (24)
        • Docker & Kubernetes (11)
        • Naver Cloud Platform (1)
        • AWS (2)
        • Linux (6)
        • Jenkins (0)
        • GoCD (3)
      • Coding Test (112)
        • Solution (104)
        • Algorithm (7)
        • Data structure (0)
      • Reference (134)
        • Effective-Java (90)
        • Pragmatic Programmer (0)
        • CleanCode (11)
        • Clean Architecture (2)
        • Test-Driven Development (4)
        • Relational Data Modeling No.. (0)
        • Microservice Architecture (2)
        • 알고리즘 문제 해결 전략 (9)
        • Modern Java in Action (0)
        • Spring in Action (0)
        • DDD start (0)
        • Design Pattern (6)
        • 대규모 시스템 설계 (6)
        • JVM 밑바닥까지 파헤치기 (4)
      • Service Planning (2)
      • Side Project (5)
      • AI (0)
      • MATLAB & Math Concept & Pro.. (1)
      • Review (18)
      • Interview (2)
      • IT News (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 깃
  • 공지사항

    • 한동안 포스팅은 어려울 것 같습니다. 🥲
    • N Tech Service 풀스택 신입 개발자가 되었습니다⋯
    • 취업 전 계획 재조정
    • 취업 전까지 공부 계획
    • 앞으로의 일정에 대하여..
  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
나죽못고나강뿐
[Docker] Docker Compose : Multiple Environment

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.