Docker Compose로 Redis & SpringBoot 연결 실패 트러블 슈팅 (어이없음 주의)

Damongsanga·2024년 3월 21일
0
post-thumbnail

당장 오늘 있었던 트러블 슈팅이다. 이걸 5시간을 붙잡고 있던게 너무 웃겨(?)서 집 오자마자 글로 남겨본다. 결론은 너무나도 어이 없으니 해결 과정에 주목하여 읽어주면 감사하겠다!


문제 상황

별도의 도커 컨테이너로 띄워둔 back springboot WAS, redis 컨테이너를 도커 파일 & 도커 컴포즈로 함께 관리하도록 docker-compose.yml 파일을 만들며 테스트 중이었다. 그런데 잘 동작하던 springboot가 터지는 것 아닌가.

에러 로그를 보니 아래와 같았다.

Caused by: io.lettuce.core.RedisConnectionException: Unable to connect to localhost/<unresolved>:6379

...

Caused by: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: localhost/127.0.0.1:6379
Caused by: java.net.ConnectException: Connection refused: no further information

...?
localhost/:6379 라니 이게 뭔가 ㅠㅠ
lettuce, netty 모두 연결에 실패하는 것으로 보이는데 로컬에서는 잘 테스트가 되었는데 왜 그럴까. 트러블슈팅 해보자!

해결 과정

  1. docker-compose.yml command 추가 (유효)

    • 기존 application.yml 파일은 아래와 같았었다
    spring:
      data:
        redis:
          host: localhost
          port: 6379
          password: mypassword
    • 기존에 컨테이너에서 관리할 때와 로컬에서 관리할 때는 비밀번호를 redis 내부에서 설정해주었는데, 이제는 docker-compose로 관리할 것임으로 컨테이너가 사라지고 생성되어도 비밀번호를 계속 걸어주어야 했다.

    • 그런데 docker-compose.yml 파일에 redis를 띄울 때 비밀번호를 설정해지 않아서 연결이 안되는 것이라고 생각했다. 실제로도 비밀번호가 틀리면 연결이 거부당해서 Connection refused가 발생할 수 있다.

    • command 사용하여 redis-server --requirepass mypassword --port 6379 로 비밀번호를 지정해주었다.

      redis:
        container_name: redis
        networks:
          - mynetwork
        image: redis
        restart: always
        command: redis-server --requirepass mypassword --port 6379
        ports:
        - "6379:6379"
    
  2. application.yml host 변경 (유효)

    • https://okky.kr/questions/1058298

    • 기존에는 local에서 redis를 올려두고 테스트하여 application.yml에 localhost로 되어있었는데, docker에서는 네트워크로 관리되어 컨테이너 host 명으로 ip가 매핑되어 구분되어있다.

    • 실제로 매핑된 IP는 docker network inspect [네트워크 명] 으로 확인할 수 있다.

    spring:
      data:
        redis:
          host: redis
          port: 6379
          password: mypassword
  3. application.yml password ' ' 추가 (효과 없음)

    • https://github.com/spring-projects/spring-boot/issues/35612
    • 해당 문제에서 비밀번호에 ‘’를 쳤더니 해결되었다는 글이 있었지만 해당 글은 숫자인 003214 같은 값을 비밀번호로 설정하여 string으로 인식을 못했기 때문에 유효했던 방법이었다. 혹시 비밀번호를 이와 같이 설정했다면 이 방법도 사용해볼 수 있다. 하지만 나는 아님 ㅠ
    spring:
      data:
        redis:
          host: redis
          port: 6379
          password: 'mypassword'
  4. docker-compose.yml hostname 추가 (효과 없음)

    • host 명을 hostname으로 따로 지정해야된다고 한다는 글도 보았지만 그렇다면 이미 mysql도 host명을 사용하고 있기 때문에 이는 문제가 아님을 알고있었다
      redis:
        container_name: redis
        hostname: redis
        networks:
          - mynetwork
        image: redis
        restart: always
        command: redis-server --requirepass mypassword --port 6379
        ports:
        - "6379:6379"
    
  5. application.yml ssl secure 추가 (효과 없었음)

    • https://github.com/spring-projects/spring-boot/issues/35612

    • springboot 3.1 버전으로 올라가면서 lettuce를 쓰게 되어 ssl 설정을 해줘야 한다는 글도 보아 추가해보았지만 여전히 변하는 것은 없었다

    • 실제로 이 방법이 효과가 있었다고 하니 (버전을 2.X 에서 3.X로 옮겨지면서) 문제가 생겼다면 이 방법도 확인해볼것

    spring:
      data:
        redis:
          host: redis
          port: 6379
          password: mypassword
          ssl:
            enabled: true
  6. application.yml host 실제 ip로 지정 (효과 없었음)

    • 몇시간 쯔음 되었을 때 뭔가 이상함을 느꼈다. 백 팀원은 내 레디스에 잘 접근해서 pub/sub 테스트를 하고 있었던 것이다..!

    • 설마 설마 host 명인 redis를 인식 못하는건가? network 는 확인했는데..?! 하면서 host를 실제 도메인 명으로 바꿔보았다.

    • 비록 비효율적이지만 로컬에서 서버에 있는 레디스로 테스트할 때 처럼 실제 도메인 명을 사용했는데도 안됐다.

    spring:
      data:
        redis:
          host: [실제 도메인명]
          port: 6379
          password: mypassword
  1. 어이없게도 원인은 자바 소스코드

    • 원인은.. git 소스 코드 자체에서 redis Connection Factory 자체가 주석쳐있어서 host를 지정하지 못한 것이었다.

    • 따라서 localhost로 계속 연결되었던 것이었다..

    • 백 담당이 로컬에서 서버에 올라간 redis 통신을 하고 있어서 전혀 의심하지 못했는데 알고보니 혼자서 주석 해제하고 테스트하고 있었던거였다..

    • 아..ㅋㅋㅋㅋㅋㅋㅋㅋ 그래도 어찌저찌 찾긴함..!

    @Configuration
    @RequiredArgsConstructor
    public class RedisConfig {
    
        private final RedisMessageListener redisMessageListener;
    
        @Value("${spring.data.redis.host}")
        private String host;
    
        @Value("${spring.data.redis.port}")
        private int port;
    
        @Value("${spring.data.redis.password}")
        private String password;
    
        @Bean
        public RedisConnectionFactory redisConnectionFactory() {
            RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
    
    //        configuration.setHostName(host);
    //        configuration.setPort(port);
    //        configuration.setPassword(password);
    
            return new LettuceConnectionFactory(configuration);
        }
    
        //..
    }

오늘의 결론

이 글을 읽고 있다면 너무 허무하겠지만 정말 별 것 아닌 데에서 에러가 터짐을 오늘도 몸소 겪어버렸다. 인프라쪽에 내가 모르는게 있겠지 라는 생각에 잘 아는 springboot 쪽을 오히려 생각 안해버린.. 물론 통신 테스트를 잘 하고 있었기에 소스코드 문제일거라고는 생각도 못했다 ㅠㅠ 오늘도 뻘짓과 함께 성장한(?) 하루였다 ㅎㅅㅎ

참조 자료

https://github.com/spring-projects/spring-boot/issues/35612

https://www.inflearn.com/questions/12010/어플리케이션-실행시-에러

https://okky.kr/questions/1058298

profile
향유하는 개발자

0개의 댓글