![[Docker] Docker Compose](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQ4rTl%2FbtsJfoCTWhU%2FCfi1RaJSboO8ccgtmJepX1%2Fimg.webp)
이 글은 인프런의 지식 공유자 박재성님과 데브위키님의 강의를 듣고 개인적으로 정리하는 글임을 알립니다.
Docker Compose
Docker Copmose는여러 개의 Docker 컨테이너들을 하나의 서비스로 정의하고 구성해 하나의 묶음으로 관리할 수 있게 도와주는 도구이다.
- 도커 컴포즈는 도커 데스크탑 설치 시 기본으로 설치된다.
- 한 번의 명령어로 여러 개의 컨테이너를 한번에 실행하거나 종료할 수 있다.
- 로컬 개발 환경에서 활용하기 편리합니다.
Docker Compose를 사용하는 이유
- 여러 개의 컨테이너를 관리하는 데 용이
여러 개의 컨테이너로 이루어진 복잡한 애플리케이션을 한 번에 관리할 수 있게 해준다. 여러 컨테이너를 하나의 환경에서 실행하고 관리하는 데 도움이 된다. - 복잡한 명령어로 실행시키던 걸 간소화 시킬 수 있음
이전에 MySQL 이미지를 컨테이너로 실행시킬 때 아래와 같은 명령어를 실행시켰다.
docker run -e MYSQL_ROOT_PASSWORD=password123 -p 3306:3306 -v /Users/jaeseong/Documents/Develop/docker-mysql/mysql_data:/var/lib/mysql -d mysql
- Docker Compose를 사용하면 위와 같이 컨테이너를 실행시킬 때마다 복잡한 명령어를 입력하지 않아도 된다. 단순히 docker compose up 명령어만 실행시키면 된다.
주요 명령어
# YAML 파일에 정의된 서비스 생성 및 시작 (백그라운드 모드)
docker compose up -d
# 현재 실행중인 서비스 상태 표시
docker compose ps
# 현재 실행중인 서비스의 이미지만 빌드
docker compose build
# 실행 중인 서비스의 로그 표시
docker compose logs
# YAML 파일에 정의된 서비스 종료 및 제거
docker compose down
단일 컨테이너 띄우기
mysql 컨테이너
compose.yml
services: my-db: container_name: db image: mysql environment: MYSQL_ROOT_PASSWORD: pwd1234 volumes: - ./mysql_data:/var/lib/mysql ports: - 3306:3306 |
- services: my-db : Docekr Compose에서 하나의 컨테이너를 서비스(service)라고 부른다. 이 옵션은 서비스에 이름을 붙이는 기능이다.
- container_name: db : 컨테이너를 띄울 때 붙이는 별칭이다. CLI에서 --name [별칭] 역할과 동일하다.(혼동 방지를 위해 서비스 이름과 똑같이 설정하는 것을 권장)
- image: mysql : 컨테이너를 실행시킬 때 어떤 이미지를 사용할 지 정의하는 명령어이다. docker run [이미지명]와 비슷한 역할이다.
- environment: ... : CLI에서 -e MYSQL_ROOT_PASSWORD=password 역할과 동일하다.
- volumes: ... : CLI에서 -v {호스트 경로}:/var/lib/mysql 역할과 동일하다.
- ports : 포트 매핑은 어떻게 할 지를 설정하는 옵션이다. CLI에서-p 3306:3306 역할과 동일하다.
compose 로 컨테이너 실행
docker compose up -d
compose 실행 현황
docker compose ps
docker ps
compose로 실행된 컨테이너 중지 및 삭제
- 아래 명령은 도커 컴포즈를 사용해 실행 중인 모든 컨테이너와 관련 리소스를 중지하고 제거하는 명령어이다.
- 기본 옵션으로는 볼륨은 유지되지만 추가 옵션을 통해서 볼륨, 사용된 이미지까지 지울 수 있다.
docker compose down
- --volumes 또는 -v: 볼륨까지 제거한다. 데이터베이스에 저장된 모든 데이터가 삭제되므로 주의해야 한다.
- --rmi all: 사용된 모든 이미지까지 제거한다.
스프링부트 컨테이너
프로젝트 빌드
./gradlew clean build
Dockerfile
FROM eclipse-temurin:17-jre-alpine COPY build/libs/*SNAPSHOT.jar app.jar # java -jar /app.jar 명령어 실행 ENTRYPOINT ["java", "-jar", "/app.jar"] |
compose.yml
services: my-server: build: . ports: - 8080:8080 |
- build: . : compose.yml이 존재하는 디렉토리(.)에 있는 Dockerfile로 이미지를 생성해 컨테이너를 띄우겠다는 의미이다.
compose로 컨테이너 실행
docker compose up -d --build
--build 옵션
- 서비스 시작 전에 이미지를 강제로 재빌드한다.
- 소스 코드가 변경된 경우 최신 변경사항이 반영된다.
- Dockerfile이 수정된 경우 변경사항이 적용된다.
- 캐시된 이미지를 무시하고 새로 빌드한다.
3개의 컨테이너 띄우기
Docker Hub의 최신버전 MySQL은 9.x 버전이다.
그런데 현재 24.8.25일 기준 최신 스프링부트 버전인 3.3.3은 MySQL 9.x 버전을 지원하지 않는다.
따라서 MySQL의 모든 버전은 8.0.32 버전으로 맞추었다.
스프링부트 설정
build.gradle
dependencies { ... implementation 'org.springframework.boot:spring-boot-starter-data-redis' implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation 'mysql:mysql-connector-java:8.0.32' } |
application.yml
spring: datasource: url: jdbc:mysql://my-db:3306/mydb username: root password: 00000000 jpa: properties: hibernate: dialect: org.hibernate.dialect.MySQL8Dialect data: redis: host: my-cache-server port: 6379 |
RedisConfig
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}
}
AppController
@RestController
public class AppController {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@GetMapping("/")
public String home() {
redisTemplate.opsForValue().set("abc", "def");
return "Hello, World!";
}
}
Docker Compose 설정
Dockerfile
FROM eclipse-temurin:17-jre-alpine WORKDIR /spring-boot COPY build/libs/*SNAPSHOT.jar app.jar ENTRYPOINT ["java", "-jar", "/spring-boot/app.jar"] |
compose.yml
services: my-server: build: . ports: - 8080:8080 depends_on: my-db: condition: service_healthy my-cache-server: condition: service_healthy my-db: image: mysql:8.0.32 environment: MYSQL_ROOT_PASSWORD: 00000000 MYSQL_DATABASE: mydb volumes: - /home/ubuntu/mysql_data:/var/lib/mysql ports: - 3306:3306 healthcheck: test: [ "CMD", "mysqladmin", "ping" ] interval: 5s retries: 10 my-cache-server: image: redis ports: - 6379:6379 healthcheck: test: [ "CMD", "redis-cli", "ping" ] interval: 5s retries: 10 |
- my-server
-Spring Boot 애플리케이션을 8080 포트에서 실행한다.
-depends_on 옵션을 사용해 MySQL 데이터베이스와 Redis 캐시 서버가 먼저 준비된 후에 서버가 실행되도록 설정했다.
-depends_on에서 condition: service_healthy를 사용해 각 서비스가 정상적으로 준비된 후에 서버가 실행될 수 있도록 보장한다. - my-db (MySQL 데이터베이스)
-image: mysql로 MySQL 컨테이너를 설정한다. MySQL의 기본 이미지가 사용된다.
-환경 변수로 MYSQL_ROOT_PASSWORD와 MYSQL_DATABASE를 설정해 MySQL의 root 비밀번호와 데이터베이스 이름을 지정한다.
-로컬의 ./mysql_data 디렉터리를 컨테이너 내부의 /var/lib/mysql에 마운트하여 데이터가 유지되도록 설정했다.
-ports 옵션을 사용해 3306 포트를 노출시켜 외부에서 데이터베이스에 접근할 수 있다.
-healthcheck를 설정해 MySQL 서버가 정상적으로 실행 중인지 확인한다. 5초마다 mysqladmin ping 명령어로 상태를 확인하고, 최대 10번의 시도를 한다. - my-cache-server (Redis 캐시 서버)
-image: redis로 Redis 캐시 서버를 설정한다.
-ports 옵션을 통해 6379 포트를 노출시켜 외부에서 Redis에 접근할 수 있다.
-healthcheck를 설정해 Redis 서버가 정상적으로 실행 중인지 확인한다. 5초마다 redis-cli ping 명령어로 상태를 확인하고, 최대 10번의 시도를 한다.
위 설정과 스프링부트의 application.properties 파일을 살펴보면 아래와 같은 그림이 이해가 될 것이다.
spring: datasource: url: jdbc:mysql://my-db:3306/mydb username: root password: 00000000 jpa: properties: hibernate: dialect: org.hibernate.dialect.MySQL8Dialect data: redis: host: my-cache-server port: 6379 |
각 컨테이너는 독립된 네트워크를 구성한다. 따라서 각각의 컨테이너와 통신하기 위해선 각 컨테이너의 ip를 지정해주어야 하지만, 도커에선 컨테이너의 ip 대신 컨테이너의 이름을 작성하면 된다.
- 호스트 컴퓨터: 사용자가 직접 접근하는 주체로, 포트를 통해 각각의 컨테이너와 연결된다.
- 컨테이너들:
-my-db: MySQL 데이터베이스 컨테이너로, 3306번 포트를 통해 외부(호스트 컴퓨터)와 연결된다. my-server 컨테이너는 내부적으로 이 데이터베이스와 통신한다.
-my-server: Spring Boot 서버 애플리케이션이 동작하는 컨테이너로, 8080번 포트를 통해 외부와 통신하며, my-db와 my-cache-server와 내부적으로 연결되어 있다.
-my-cache-server: Redis 캐시 서버가 동작하는 컨테이너로, 6379번 포트를 통해 호스트와 통신한다. my-server 컨테이너는 내부적으로 이 캐시 서버를 사용한다.
각 컨테이너는 외부로부터 특정 포트를 통해 접근할 수 있으며, 컨테이너들끼리는 내부적으로 연결되어 통신한다. my-server는 Spring Boot 기반 애플리케이션으로서 MySQL 데이터베이스(my-db)와 Redis 캐시 서버(my-cache-server)를 이용해 데이터 처리를 한다.
컨테이너 띄우기
- ./gradlew clean build
- docker compose up --build -d
compose.yml 공통 변수 활용
위와 같이 이중화 DB를 구성할때 중복되는 부분이 많다.
한 부분이 변경되면 다른 부분도 변경되어야 하는데, 이는 변경에 용이한 구조가 아니다.
이러한 아래와 같이문제를 공통 변수를 따로 묶어서 처리할 수 있다.
- x-: 확장 필드를 의미한다. 이 필드는 직접적인 Docker Compose 구성이 아니라 재사용 가능한 구성 조각으로 사용된다.
- x-environment: &common_environment: YAML 앵커(anchor)와 참조(reference) 기능을 사용한 공통 환경 변수 설정이다.
- &common_environment: YAML 앵커로, 이 블록에 이름을 붙여 다른 곳에서 참조할 수 있게 한다.
이 공통 환경 변수 블록은 PostgreSQL 및 repmgr(복제 관리자) 관련 설정을 포함한다.
- 데이터베이스 접속 정보 (사용자명, 비밀번호, 데이터베이스명)
- 복제 설정 (비밀번호, 호스트, 포트) - <<: *common_environment: 앵커로 정의된 설정을 참조하여 해당 위치에 포함시키는 YAML 문법이다. 이를 통해 postgres-primary-0와 postgres-standby-1 서비스가 동일한 환경 변수를 공유한다.
'DevOps > Docker' 카테고리의 다른 글
[Docker] 도커 네트워크 (0) | 2025.05.16 |
---|---|
[Docker] 컨테이너 리소스 사용량 제한 (0) | 2025.05.15 |
[Docker] Dockerfile (1) | 2025.05.14 |
[Docker] 볼륨 (Volume) (0) | 2025.05.14 |
[Docker] 자주 사용하는 명령어 정리 (1) | 2025.05.13 |