Spring/팀 프로젝트

[Spring] EC2에 Docker에 Redis SpringBoot 프로젝트 연동

jungmin.park 2023. 12. 16. 16:03

티켓 예매 프로젝트에 진행하게 되면서 ec2에 redis 및 springboot 배포해야 할 일이 생겼다.

그 중 Spring과 Redis 연결이 잘되지 않아 하루넘게 시간이 걸려서 해결했다.

 

이 오류만 정말 수십번의 커밋과 푸시 배포과정을 진행했고 결론적으론 해결했다.

현재 redissonLockTicketFacade 클래스에 redis를 이용한 로직이 구현되어있고 마지막 오류메시지를 보면 계속 로컬로 연결되는 문제였다.

Error creating bean with name 'redissonLockTicketFacade' defined in URL [jar:nested:/app.jar/!BOOT-INF/classes/!/com/example/yetiproject/facade/RedissonLockTicketFacade.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'redisson' defined in class path resource [org/redisson/spring/starter/RedissonAutoConfiguration.class]: Failed to instantiate [org.redisson.api.RedissonClient]: Factory method 'redisson' threw exception with message: Unable to connect to Redis server: localhost/127.0.0.1:6379

 

 


사용기술

  • githubAction CI/CD green blue 전략 사용
  • EC2 인스턴스
  • SpringBoot
  • Docker
  • Redis

Github Action에서 APPLICATION 수정

GihubAction > [프로젝트 Repository] > Settings > Security > Secrets and variables > Actions

 

Repository secrets > New repository secret > APPLICATION 수정

spring:
  datasource:
    url: jdbc:postgresql://[rds 엔드 포인트]/postgres
    driver-class-name: org.postgresql.Driver
    username: [postgresql 계정]
    password: [postgresql 비밀번호]
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
  data:
    redis:
      host: [redis가 깔린 EC2] 주소
      port: 6379
      timeout: 3000
jwt:
  secret:
    key:
      [ jwt key secret token] 
feUrl:
  http://localhost:3000

 

이 중 Redis 설정 부분은 이 부분이다. 다른 블로그들을 아무리 찾아봐도 host에 redis를 써주었고 도커 이미지의 이름인줄 알았다.

data:
    redis:
      host: [redis가 깔린 EC2] 주소
      port: 6379
      timeout: 3000

 


docker-compose blue/green 파일 수정

docker-compose.blue.yml 파일 수정

version: '3'
services:
  backend:
    build: .
    ports:
      - "[blue port]:8080"
    container_name: seniors-blue
    environment:
      - REDIS_HOST = [redis가 있는 ec2주소]
      - REDIS_PORT = 6379
volumes:
  redis_data:

 

docker-compose.green.yml 파일 수정

version: '3'
services:
  backend:
    build: .
    ports:
      - "[green port]:8080"
    container_name: seniors-green
    environment:
      - REDIS_HOST = [redis가 깔린 ec2 주소]
      - REDIS_PORT = 6379
volumes:
  redis_data:

 

 

잘못된 docker-compse 파일

version: '3'
services:
  backend:
    build: .
    ports:
      - "8081:8080"
    container_name: seniors-blue
    depends_on:
      - redis
  redis:
    image: redis
    container_name: redis
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data

volumes:
  redis_data:
version: '3'
services:
  backend:
    build: .
    ports:
      - "[green port]:8080"
    container_name: seniors-green
    environment:
      - REDIS_HOST = [redis가 깔린 ec2 주소]
      - REDIS_PORT = 6379
    depends_on:
      - redis
volumes:
  redis_data:

 

 

environment를 추가하고 depends_on을 제거하니 서비스가 잘 실행되었다. depends_on이 왜 제거되어야 할까? 궁금해서 기록해본다.

 


environment 

컨테이너를 띄우기 위한 환경변수 지정

 

services:
  postgres:
    image: postgres:13
    container_name: postgres
    ports:
      - '5432:5432'
    environment:
      - POSTGRES_PASSWORD=pw1234

 

 

예시를 하나 가져왔다 해당 docker-compose파일은 postgres를 사용하고 있고 포트는 5432이다.

이 DB를 사용하기 위한 postgres의 암호를 POSTGRES_PASSWORD에 지정해주었다.

그렇다면 redis를 사용하기 위해 필요한것들이 있을 것이다. 호스트 주소와 포트번호를 알아야 사용이 가능하다.

만약 비밀번호를 설정해주었다면 추가적으로 비밀번호를 넣어줘야 할 것이다.

필요한 환경변수들을 environment 밑에 추가해주는 것이다.

 

그럼 왜 depends_on을 제거해야 실행되었을까?

 


depends_on

service 간의 종속성을 표현
  • docker-compose up을 실행하면 종속된 것들이 먼저 실행되고 그 뒤 서비스가 실행된다.
  • docker-compose stop을 하면 서비스를 먼저 종료하고 db, redis가 그 다음 종료된다.
version: "3.9"
services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: postgres
  • 예시 파일은 그럼 db, redis가 먼저 실행되고 web이 제일 마지막에 실행된다.
  • docker-compose up web을 실행해도 자동으로 depends_on에 있는 서비스 먼저 실행되고
  • docker-compose stop을 하면 web 먼저 종료되고, db, redis가 그 다음에 종료된다.
  • depends_on은 web을 실행하기 전에 db와 redis가 준비되었는지 기다리지 않는다. 그냥 db와 redis을 시작할 뿐이다.

 

서비스를 띄우는데 redis를 계속 올렸다 내렸다 해야하는지 의문이 생겼다. 또한 서비스를 실행할때마다 deploy.sh에서 docker rm / rmi 로 컨테이너를 죽이고 이미지도 삭제한뒤 다시 그걸 올릴 필요가 있을까 의문이 들었고 deploy.sh에서 redis를 컨테이너를 내리고 시작하는 명령어를 빼고 처음부터 redis서버를 올려놓고 시작해보기로 했다.

 

그래서 redis를 먼저 띄워놓고 서비스 배포를 시작했다.

REPOSITORY                     TAG       IMAGE ID       CREATED       SIZE
redis                          latest    76506809a39f   11 days ago   138MB

 

 

결론적으론 redis-springboot 연동이 성공적으로 끝났다.

CONTAINER ID   IMAGE                          COMMAND                  CREATED       STATUS       PORTS                                       NAMES
43f476cf4bd5   ec2-application-blue-backend   "java -jar /app.jar"     3 hours ago   Up 3 hours   0.0.0.0:8081->8080/tcp, :::8081->8080/tcp   seniors-blue
a1d3d563c282   redis                          "docker-entrypoint.s…"   4 hours ago   Up 4 hours   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp   redis

 

 


참조

https://seongjin.me/environment-variables-in-docker-compose/

https://jandari91.github.io/posts/Environment/