Docker는 컨테이너화된 애플리케이션을 손쉽게 배포하고 관리할 수 있는 강력한 도구입니다.
단일 컨테이너를 다룰 때는 관리가 간단하지만, 여러 개의 컨테이너를 사용할 때는 문제가 발생할 수 있습니다.
여러 컨테이너가 서로 상호작용하며 네트워크를 통해 연결되고, 각 컨테이너가 사용하는 포트와 환경 변수를 모두 고려해야 하기 때문에 관리가 복잡해질 수 있습니다.
이러한 상황에서 Docker Compose는 매우 유용한 도구가 됩니다.
Docker Compose란❓
Docker Compose는 멀티 컨테이너 Docker 애플리케이션을 정의하고 실행하기 위한 오케스트레이션(Orchestration) 도구입니다.
여러 개의 Docker 컨테이너를 하나의 YAML 파일로 정의하고, 단일 명령어로 이들을 관리할 수 있도록 해주는 도구입니다. 주로 다음과 같은 기능을 제공합니다.
1. YAML(YML) 파일로 구성 관리
Docker Compose는 docker-compose.yml이라는 설정 파일을 사용하여 애플리케이션의 모든 컨테이너, 네트워크, 볼륨 등의 설정을 정의합니다. 이 파일은 사람이 읽기 쉬운 YAML 형식으로 작성되며, 다음과 같은 내용을 포함할 수 있습니다.
- 서비스 정의
- 애플리케이션을 구성하는 컨테이너의 목록과 그 설정.
- 네트워크 정의
- 컨테이너들 간의 네트워크 설정.
- 볼륨 정의
- 컨테이너와 호스트 간의 데이터 공유 설정.
- 컨테이너와 호스트 간의 데이터 공유 설정.
docker-compose.yml
version: '3'
services:
web:
image: nginx
ports:
- "8080:80"
app:
build: .
ports:
- "8081:8080"
depends_on:
- db
db:
image: postgres
environment:
POSTGRES_PASSWORD: example
이 파일은 Docker Compose를 사용하여 세 가지 서비스를 정의하고 있습니다.
version: '3'
- Docker Compose 파일의 버전을 지정합니다.
- 버전 3은 Docker Compose의 다양한 기능을 지원하며, Docker의 최신 기능과 호환됩니다.
2.services
- 애플리케이션을 구성하는 서비스들을 정의하는 섹션입니다.
- 각 서비스는 개별적으로 설정되며, Docker 컨테이너를 나타냅니다.
3. web 서비스
- image: nginx
- 이 서비스는 nginx 이미지를 사용하여 컨테이너를 생성합니다. 이미지는 Docker Hub와 같은 레지스트리에서 가져옵니다.
- ports
- 호스트와 컨테이너 간의 포트 매핑을 설정합니다. "8080:80"은 호스트의 8080 포트를 컨테이너의 80 포트에 매핑합니다.
4. app 서비스
- build:.
- 이 서비스의 이미지를 현재 디렉터리에서 Dockerfile을 사용하여 빌드합니다.
- 점(.)은 현재 디렉터리를 가리키며, Dockerfile이 이 디렉터리에 위치해야 합니다.
- ports
- 호스트와 컨테이너 간의 포트 매핑을 설정합니다.
- "8081:8080"은 호스트의 8081 포트를 컨테이너의 8080 포트에 매핑합니다.
- depends_on
- 이 서비스가 시작되기 전에 db 서비스가 시작되어야 함을 지정합니다.
- 의존 관계를 설정하여 컨테이너의 시작 순서를 조정합니다.
5. DB 서비스
- image: postgres
- 이 서비스는 postgres 이미지를 사용하여 컨테이너를 생성합니다.
- PostgreSQL 데이터베이스 서버를 제공하는 이미지입니다.
- environment
- 컨테이너의 환경 변수를 설정합니다.
- POSTGRES_PASSWORD: example은 PostgreSQL 데이터베이스의 슈퍼유저 비밀번호를 example로 설정합니다.
2. 멀티 컨테이너 애플리케이션 관리
Docker Compose를 사용하면 여러 개의 컨테이너를 한 번에 실행, 중지, 업데이트할 수 있습니다. 이를 통해 애플리케이션의 모든 구성 요소를 하나의 파일에서 관리할 수 있으며, 복잡한 설정을 단순화할 수 있습니다.
주요 명령어
docker-compose up
- docker-compose.yml 파일을 기반으로 정의된 모든 컨테이너를 실행합니다.
- -d (--detach)
- 설명: 컨테이너를 백그라운드에서 실행합니다.
- 예시: docker-compose up -d
- --build
- 설명: 서비스를 시작하기 전에 이미지를 새로 빌드합니다.
- 예시: docker-compose up --build
- --force-recreate
- 설명: 기존 컨테이너가 있더라도 항상 새로운 컨테이너를 생성합니다.
- 예시: docker-compose up --force-recreate
- --no-deps
- 설명: 지정한 서비스의
의존 서비스를 시작하지 않고, 지정한 서비스만 시작합니다. - 예시: docker-compose up --no-deps web
- 설명: 지정한 서비스의
- --remove-orphans
- 설명: 현재 docker-compose.yml 파일에서 정의되지 않은 컨테이너를 삭제합니다.
- 예시: docker-compose up --remove-orphans
docker-compose down
- 실행 중인 컨테이너를 중지하고 네트워크 및 볼륨을 제거합니다.
- --rmi
- 설명: 서비스에 의해 사용된 이미지를 제거합니다.
- 옵션 값:
- all: 모든 이미지를 제거합니다.
- local: 로컬에서 사용된 이미지만 제거합니다.
- 예시: docker-compose down --rmi all
- --volumes, -v
- 설명: 정의된 볼륨을 제거합니다.
- 예시: docker-compose down -v
docker-compose build
- 정의된 서비스의 이미지를 빌드합니다
docker-compose logs
- 실행 중인 컨테이너의 로그를 출력합니다.
오케스트레이션(Orchestration) 도구란❓
오케스트레이션 도구는 복잡한 애플리케이션 환경에서 여러 시스템과 서비스를 자동으로 배포, 관리, 조정하는 소프트웨어입니다.
주로 컨테이너화된 애플리케이션 환경에서 사용되며, 애플리케이션의 다양한 구성 요소를 통합하고, 이들의 상호작용을 조율하여 안정적이고 효율적인 운영을 지원합니다.
주요 기능
자동 배포 (Automated Deployment)
- 애플리케이션의 다양한 구성 요소를 자동으로 배포하고 설정합니다. 이를 통해 배포 프로세스의 일관성과 신뢰성을 보장할 수 있습니다.
- 예시: 새로운 버전의 애플리케이션을 자동으로 배포하거나, 환경 설정에 따라 컨테이너를 자동으로 배포하는 작업.
스케일링 (Scaling)
- 애플리케이션의 요구에 따라 서비스의 인스턴스 수를 자동으로 조절합니다. 트래픽 증가나 감소에 대응하여 자원을 효율적으로 관리합니다.
- 예시: 웹 애플리케이션의 트래픽이 증가하면 자동으로 추가 인스턴스를 생성하여 부하를 분산시키는 작업
로드 밸런싱 (Load Balancing)
- 여러 인스턴스에 요청을 고르게 분산시켜 성능을 최적화합니다. 이를 통해 특정 인스턴스에 과도한 부하가 걸리지 않도록 합니다.
- 예시: 다수의 웹 서버 인스턴스에 들어오는 HTTP 요청을 분산시키는 작업.
서비스 디스커버리 (Service Discovery)
- 새로운 서비스 인스턴스가 추가되거나 제거될 때, 이를 자동으로 인식하고 업데이트합니다. 서비스를 동적으로 찾고 연결할 수 있게 합니다.
- 예시: 새로운 데이터베이스 인스턴스가 추가되면 애플리케이션이 자동으로 이를 인식하고 연결하는 작업.
모니터링 및 로깅 (Monitoring and Logging)
- 시스템의 상태와 성능을 지속적으로 모니터링하고, 로그를 수집하여 문제를 신속하게 파악하고 해결할 수 있도록 합니다.
- 예시: 시스템의 CPU 사용량, 메모리 사용량, 네트워크 트래픽 등을 모니터링하고, 에러 로그를 수집하여 문제를 분석하는 작업.
복구 및 롤백 (Recovery and Rollback)
- 시스템에서 오류가 발생하거나 실패가 발생할 경우, 자동으로 복구하거나 이전 안정된 상태로 롤백합니다.
- 예시: 배포가 실패할 경우, 자동으로 이전 버전으로 롤백하여 서비스를 계속 제공하는 작업.
Docker compose 사용해 보기
- 클라이언트에서 Service A로의 요청
- 클라이언트가 A 서비스의 /hi 엔드포인트에 http://localhost:8080/hi 주소로 HTTP 요청을 보냅니다.
- Service A의 Feign 클라이언트 호출:
- A 서비스의 AController는 BServiceClient를 통해 B 서비스의 /hello 엔드포인트에 HTTP 요청을 보냅니다.
- Feign 클라이언트는 B 서비스의 URL(http://service-b:8080)로 요청을 보냅니다.
- Feign 클라이언트와 Service B 간의 통신
- Feign 클라이언트는 B 서비스의 /hello 엔드포인트에 http://service-b:8080/hello 주소로 HTTP GET 요청을 보냅니다.
- Service B의 응답
- B 서비스의 BController가 /hello 요청을 처리하고 "hello"라는 문자열을 응답으로 반환합니다.
- Service A의 응답 반환:
- Feign 클라이언트는 B 서비스의 응답을 받아 AController에 반환합니다.
- A 서비스의 AController는 이 응답을 포함하여 최종 응답을 클라이언트에게 반환합니다
- 최종 응답 : "service-a: hi ###### service-b: hello".
사용 코드
service-a
service-b
위의 간단한 service-a와 service-b를 docker compose 컨테이너로 올려보겠습니다.
- services:
- Docker Compose에서 관리할 서비스 목록을 정의합니다. 각 서비스는 독립적인 컨테이너로 실행됩니다.
- service-a:
- image: 이 서비스에서 사용할 Docker 이미지를 지정합니다. img-service-a라는 이미지를 사용합니다.
- ports: 호스트와 컨테이너 간의 포트 매핑을 설정합니다. 호스트의 18080 포트가 컨테이너의 8080 포트로 매핑됩니다.
- environment: 이 서비스에서 사용할 환경 변수를 설정합니다. SERVICE_B_URL 환경 변수를 설정하여 service-b의 URL을 지정합니다.
- depends_on: 이 서비스가 시작되기 전에 service-b 서비스가 먼저 시작되어야 함을 지정합니다.
- service-b:
- image: img-service-b라는 이미지를 사용합니다.
- ports: 호스트의 18081 포트가 컨테이너의 8080 포트로 매핑됩니다.
- networks:
- default 네트워크를 정의하며, driver를 bridge로 설정합니다. 이는 기본 Docker 브리지 네트워크를 사용하겠다는 의미입니다. 이 설정은 두 서비스가 서로 통신할 수 있도록 합니다.
중요한 포인트
- 네트워크 설정:
- 두 서비스가 동일한 Docker 네트워크(default 네트워크)에 연결되어 있으므로, service-a는 http://service-b:8080 주소를 통해 service-b에 접근할 수 있습니다.
- Docker Compose는 서비스 이름을 DNS 이름으로 해석하여, 컨테이너 간 통신을 가능하게 합니다.
- 포트 매핑:
- service-a는 호스트의 18080 포트에서 8080 포트로 요청을 라우팅 합니다.
- service-b는 호스트의 18081 포트에서 8080 포트로 요청을 라우팅 합니다.
- 환경 변수:
- SERVICE_B_URL 환경 변수는 service-a에서 service-b를 호출할 때 사용됩니다.
- 이 URL은 service-b 컨테이너의 DNS 이름을 사용하여 http://service-b:8080으로 설정되어 있습니다.
Docker compose yml파일을 생성해야 하는데, service-a와 service-b를 같이 실행할 것이기 때문에 상위 폴더에서 생성을 해야 합니다.
docker-compose.yml 파일을 기반으로 정의된 모든 컨테이너를 실행합니다.
docker compose up을 실행하면 위와 같이 두 개의 컨테이너가 동시에 실행되는 것을 확인할 수 있습니다. 하지만 두 개의 컨테이너만 실행되었는데도 로그가 복잡해질 수 있기 때문에, 일반적으로 -d 옵션을 사용하여 백그라운드에서 실행하는 것이 좋습니다.
-d 옵션을 사용하면 Docker Compose가 컨테이너를 백그라운드에서 실행하며, 터미널은 즉시 제어를 반환하므로 로그를 실시간으로 확인할 필요가 없고, 다른 작업을 계속할 수 있습니다. 백그라운드에서 실행함으로써 로그의 혼잡함을 피하고, 시스템 자원을 더 효율적으로 활용할 수 있습니다.
docker compose up -d으로 docker-compose.yml 파일을 기반으로 정의된 모든 컨테이너를 실행합니다.
docker compose를 사용하여 service-a와 service-b 컨테이너를 실행한 후, http://localhost:8080/hi로 접속해 보면, service-a에서 FeignClient를 통해 service-b의 http://localhost:8081/hello 엔드포인트를 호출하여 'hello'라는 문자열을 받아오는 것을 확인할 수 있습니다.
Docker compose 사용해 보기
Docker Compose를 사용하여 서비스를 실행하면, Docker Compose는 기본적으로 새 브리지 네트워크를 생성하여 각 서비스 컨테이너를 그 네트워크에 연결합니다.
이 네트워크는 docker-compose.yml 파일에 정의된 모든 서비스가 서로 통신할 수 있도록 합니다.
Docker Compose는 자동으로 네트워크를 생성하며, 이 네트워크의 이름은 docker-compose.yml 파일이 있는 디렉터리의 이름을 기반으로 형성됩니다. 네트워크의 이름은 일반적으로 <디렉토리명>_default 형식으로 생성됩니다.
따라서 앞서 yml 파일에서 networks.default.driver:bridge이기 때문에 docker-compose.yml 파일이 있는 디렉토리의 이름(Docker)을 기반으로 형성된 것을 확인할 수 있습니다.
'DevOps > Docker' 카테고리의 다른 글
[Docker] Docker 주요 명령어 알아보기 🐳 (0) | 2024.08.12 |
---|---|
[Docker] Docker와 가상 머신(Virtual Machine, VM)의 차이 (0) | 2024.08.12 |
[Docker] Docker란 무엇일까❓ (0) | 2024.08.12 |