본문 바로가기
Docker

10. 도커 컴포즈 -(3)

by shulk 2024. 11. 19.

7. 컴포즈로 컨테이너를 동시에 2개 띄워보기

이전에 컴포즈의 장점중 여러개의 컨테이너를 하나의 환경에서 실행하고 관리하니 편하고 좋기때문에 사용한다 해서 이번에 동시에 2개 띄워보기

 

(1) Redis 랑 Mysql 동시에 띄워보기

이전과 같이 컨테이너 1개 띄웠을때랑 별 차이 없이 services 하위에 저렇게 따로따로 적고 실행시키면 끝이다.

 

(2) Spring Boot 랑 Mysql 동시에 띄워보기

일단 스프링 부트 프로젝트니 이전과 마찬가지로 도커 파일로 이렇게 하나 이번엔 jar 파일을 절대 경로로 적어본다

 

위에서 했던 redis,mysql 처럼 services 하위에 저렇게 각각 적는데 이번에 보면 mysql 코드쪽에 

MYSQL_DATABASE는 컨테이너 생성할때 데이터베이스도 생성해주는 옵션이다.즉,mydb라는 이름의 데이터베이스 생성

 

그리고 스프링이랑 mysql 동시에 띄울때 생각해보면 mysql부터 띄워야한다. 왜냐하면 스프링부터 띄우면 스프링은 실행할때 mysql 연결 확인하나 mysql이 안띄워져 있어서 에러난다.

 

 

depends_on의 의미는 my-server는 my-db가 먼저 띄워지고 실행이 되야 my-server 컨테이너 띄우고 실행한다는거다. 

my-db가 먼저 띄워지고 실행된지 확인하는건 헬스 체크로  확인한다.

test는 mysql의 명령어고 ,interval은 주기를 말해서 5초마다 확인하고, retries는 재시도인데 총 10번까지 재시도 허용한다는거다 

services:
  my-server:
    build: .
    ports:
      - 8080:8080 
    depends_on: # my-db의 컨테이너가 생성되고 healthy 하다고 판단 될 때, 해당 컨테이너를 생성한다.
      my-db:
        condition: service_healthy
  my-db:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: pwd1234
      MYSQL_DATABASE: mydb # MySQL 최초 실행 시 mydb라는 데이터베이스를 생성해준다.
    volumes:
      - ./mysql_data:/var/lib/mysql
    ports:
      - 3306:3306
    healthcheck:
      test: [ "CMD", "mysqladmin", "ping" ] # MySQL이 healthy 한 지 판단할 수 있는 명령어
      interval: 5s # 5초 간격으로 체크
      retries: 10 # 10번까지 재시도

 

이후 당연 빌드 클리어후 다시 빌드를 하고 이제 docker compose up -d --build 해보면 저렇게 헬스체크를 한다.

근데 지금보니 mysql만 띄워져있고 스프링은 안띄워져있다.

 

(3) Spring Boot 안띄워진거 해결하기

[1]. 원인

docker ps -a 로 확인후 스프링 컨테이너 로그를 보니 저렇게 에러가 있다.

저 에러는  데이터 베이스가 제대로 연결이 안됬을때 뜨는 이유다.

근데 위에보면 mysql은 제대로 띄워져 있는데 왜 그러는지 알아본다.

 

지금 스프링부트,MYSQL 동시에 띄운거 사진으로 보면 저렇게 있는데,각각의 컨테이너는 자신만의 네트워크망과 IP 주소를 가지고 있다.

이렇게 스프링 프로젝트에서는 3306 포트에 연결을 하겠다 적었는데,사진을 보고 생각해보면 스프링 부트 프로젝트 컨테이너에는 3306 포트가 없어서 그렇다.

 

[2]. 해결

이를 해결하는 방법은 compose.yml에서 정의한 Service 이름으로 서로 통신할 수 있다
그러니 application.yml DB 설정 코드쪽 url에 로컬호스트 말고 서비스명(컨테이너 이름)을 적어주면 도커가 해당 이름의 컨테이너로 잘 연결해준다. 
즉 서비스 이름이 컨테이너의 주소를 뜻하고 해당 컨테이너의 IP 주소와 같은 역할을 한다.


다시 빌드 클리어후 빌드하고 컴포즈 내리고 다시 실행해보면 정상적으로 띄워져있다.

 

(4) Spring Boot , MYSQL,Redis 3개 동시에 띄워보기

#application.yml
spring:
  datasource:
    url: jdbc:mysql://my-db:3306/mydb
    username: root
    password: pwd1234
    driver-class-name: com.mysql.cj.jdbc.Driver
  data:
    redis:
      host: localhost
      port: 6379
services:
  my-server:
    build: .
    ports:
      - 8080:8080
    depends_on:
      my-db:
        condition: service_healthy
      my-cache-server:
        condition: service_healthy  
  my-db:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: pwd1234
      MYSQL_DATABASE: mydb
    volumes:
      - ./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

이렇게 redis도 mysql 처럼 마찬가지로 헬스체크하게 하고 띄운담 홈 api 요청 해봤는데, 에러가 일어난다.

이유는 홈api에 레디스에 데이터 넣는 동작 코드 있는데 위에 mysql때 처럼 마찬가지로 스프링 부트 컨테이너가 이제 레디스 컨테이너에 접근해야하나 못한다. 

 

즉 각 컨테이너는 각자의 네트워크를 가지고 있기 때문에, localhost가 아니라 Redis가 실행되고 있는 컨테이너로 통신을 해야 한다.

 

그러므로 Mysql 때랑 마찬가지로 서비스 이름으로 변경해준다. 이후 해보면 정상 작동

#application.yml
spring:
  data:
    redis:
      host: my-cache-server
      port: 6379

이렇게 사용자는 호스트 컴퓨터에 요청하면 호스트 포트가 컨테이너로 연결해주고, 각 컨테이너에서 다른 컨테이너 포트에 연결 원할시에는 서비스 이름으로해서 연결

'Docker' 카테고리의 다른 글

9. 도커 컴포즈 -(2)  (0) 2024.11.18
8. 도커 컴포즈 -(1)  (0) 2024.11.18
7. 도커파일 -(2)  (0) 2024.11.15
6. 도커 파일 -(1)  (0) 2024.11.15
5. 도커 볼륨 -(2)  (0) 2024.11.14