[Docker / Redis] "No host port mapping found for container port 6379" 해결

Eunbi Lee·2024년 4월 16일

MDP

목록 보기
4/6
post-thumbnail

1. Situation

docker compose.yaml 파일에 redis 관련 내용을 다음과 같이 작성하고, redis container를 띄우려고 시도했다.

version: '2.24.6'

services:
  redis:
    image: redis
    restart: always
    environment:
      REDIS_PASSWORD: hello
    command: redis-server --requirepass ${REDIS_PASSWORD}
  • 추가로, application.yaml 파일은 다음과 같았다.
spring:
  data:
    redis:
      host: localhost
      port: 6379

그런데, No host port mapping found for container port 6379라는 오류를 마주했다.

해결 방법은 예상외로 간단했고, 아직 이해가 안 되는 부분이 존재하지만 리뷰해보도록 하겠다.

2. Task

redis container에 compose.yaml 파일에 기입된 비밀번호가 세팅되고, 이후 spring boot application 실행 시 정상적으로 redis container에 접속한다.

가정

1-1. 기존의 redis conf 파일을 작성한 다음, redis conf 파일의 경로 참조를 통해 비밀번호를 설정해야 한다.

1-2. redis에 직접 접속해서, 비밀번호를 설정해줘야 한다.

version: '2.24.6'

services:
  redis:
    image: redis
    restart: always
    volumes:
      - ./my-redis.conf:/usr/local/etc/redis/redis.conf
    command: redis-server /usr/local/etc/redis/redis.conf
  1. spring boot application 실행 시, 자동으로 생성된 redis 컨테이너이므로 비밀번호 설정과 같은 커스텀 설정을 할 경우, 컨테이너를 내리고 다시 올리거나 / 재생성해줘야 한다.

  2. compose.yaml 파일에 기입된 형식이 잘못되었다.

3. Action

가정 1-1.

처음에는 1-1번이라고 생각했었다.

하지만, 곧 의구심이 들었다.

docker의 모든 설정을 한 곳에서 간편하게 관리하기 위해서 사용하는 것이 docker compose(.yaml)인데, 왜 추가적으로 redis conf 파일을 또 작성해줘야하는거지?

그래서, 위 방법으로 시도를 진행하다가 정공법이 아닌 것 같아 다시 생각을 곰곰히 해보았다.

  • 또, redis를 직접 설치한 것이 아니라 docker로 redis를 띄웠기 때문에 /usr/local 아래에 /etc 폴더가 없었다. 또한, "Permission denied"로 인해 해결하기 위한 여러가지 일련의 추가 과정을 거치면서 분명히 간단한 정답이 있을 것이라는 생각이 들었다.

가정 1-2.

그래서, redis에 직접 접속해서 비밀번호를 설정하기로 마음먹고, redis-cli를 입력했으나..

접속이 거부되었다.

따라서 이 방법은 자연스럽게 제외되었다.

가정 2.

그래서, 2번에 대해서 생각해보았다.

하지만, 이것도 시도하다가 해결되지 않는다는 점과 어색하다고 느껴졌던 부분이 있었다.

  1. 이후, 컨테이너를 내리고 다시 올리기 위해 다음과 같은 명령어를 기입했다.
docker-compose down
docker-compose up
  1. 그리고, 다시 컨테이너 실행을 시도했으나, 여전히 접속이 안 되는 컨테이너만 볼 수 있었다.

가정 3.

가정 3은 사실, 처음부터 생각했던 해결 방향은 아니었고 하다 보니까 떠오른 가능성이었다.

우선, docker dashboard로 확인했을 때,

  1. 아주 수상하게 끊임없이 restart를 반복하는 container의 모습을 볼 수 있었다.
  2. 또한, 다음과 같이 비밀번호가 제대로 전달이 안 되었다는 로그를 확인했다.

정확히는, 인자의 수가 일치하지 않는다는 것.

그래서, 실제로 docker compose.yaml에는 redis의 비밀번호를 설정하기 위해서 어떻게 작성하지? 싶어서 구글링을 시도했다.

  • 키워드는 docker 로그가 가리킨 requirepass가 포함된 redis-server --requirepass '${REDIS_PASSWORD}' 이었다.

그리고, How do I set a password for redis? 라는 게시물을 찾을 수 있었다.

곧, 다양하게 redis의 비밀번호를 설정하는 커맨드를 확인했다.

  1. 직접 " " 안에 비밀번호 하드코딩하기

  1. 나랑 같은데 왜 안됨 형식
  • command: redis-server --requirepass ${REDIS_PASSWORD}
  1. 환경변수를 통해 하드코딩하기

3번을 보고 스쳐지나간 생각이 있었다.

나도 한 번 하드 코딩을 해볼까?

그래서, docker compose.yaml의 파일 형식을 다음과 같이 수정했다.

version: '2.24.6'

services:
  redis:
    image: redis
    restart: always
    command: redis-server --requirepass hello
    ports:
    - '6379:6379'

그리고, 실행해보니..

거짓말같이 성공

  • 단, redis-cli를 통해 접속하였을 경우
    • AUTH "본인이 설정한 패스워드"와 같이 입력해야한다.
      • 그렇지 않을 경우, NOAUTH Aunthentication required 오류를 만날 수 있다.

어안이 벙벙해서, GPT에게 형식에 대해서 질문을 해보았다.

그리고, 두 가지 방식을 모두 시도해보았다.

  1. 이중 달러 기호 사용
version: '2.24.6'

services:
  redis:
    image: redis
    restart: always
    environment:
      REDIS_PASSWORD: "hello"
    command: redis-server --requirepass "$$REDIS_PASSWORD"
    ports:
    - '6379:6379'

문제없이 성공!

하지만, redis-cli를 통해 접속하니 WRONGPASS invalid username-password pair or user is disabled.라는 오류를 마주할 수 있었다.

찾아보니, 비밀번호가 달라서 발생하는 오류라고 한다.

  • 그런데, 비밀번호는 바꾸지 않았는데.. 왜 발생하는건지 궁금하다.
  1. 싱글 쿼트 사용
version: '2.24.6'

services:
  redis:
    image: redis
    restart: always
    environment:
      REDIS_PASSWORD: "hello"
    command: redis-server --requirepass '${REDIS_PASSWORD}'
    ports:
    - '6379:6379'

성공..인줄 알았으나

다음과 같은 로그 발견

이건 또 무엇일까 싶어서 검색을 해봤다.

  • 하지만, 아직 알 수 없는 영역이다.. 아마 docs까지 찾아봐야 나오지 않을까 싶다.

4. Result

결론 : command: redis-server --requirepass 1234과 같이 하드코딩을 하자.

아마 유추한대로, 환경변수로 비밀번호 값을 받아서 넘기는 과정 중에 발생한 오류였던 것 같다.

  • 하지만, 어느 부분에서 잘못 읽은건지는 아직 잘 모르겠다.

우선은, 하드 코딩을 통해 redis를 조작하는 식으로 가봐야겠다.

추가

근데, 가끔 아래와 같은 오류를 뱉으면서 안 될 때도 있다. 왜지?

  • 몇 번 재시도를 하면, 다시 정상적으로 연결이 된 모습을 확인할 수 있다.

NOAUTH HELLO must be called with the client already authenticated, otherwise the HELLO <proto> AUTH <user> <pass> option can be used to authenticate the client and select the RESP protocol version at the same time

redis-cli를 통해 AUTH "비밀번호"를 입력해주고, 몇 번 재시도를 하면 해결이 되던데, 너무 궁금해서 디버깅을 시작했다.

가정

계속 compose.yaml에서 비밀번호 설정 포맷을 바꿔서 진행하다보니, 적용하기까지 딜레이가 있나?

하지만, 더이상 compose.yaml 파일을 건드리지 않은 지금까지도 계속 불안정하게 redis 서버에 연결되는 것 같아 위 가정은 아닌 것 같았다.

해결 과정

  1. redis 서버에 비밀번호를 입력해야, redis 서버에 접근이 가능하다.
  2. 하지만, spring boot application을 실행할 때 mysql을 포함한 redis 컨테이너가 실행된다.
  3. 그럼 redis 서버에 먼저 접근한 다음, spring boot application을 실행하여 mysql을 실행
  4. 결과적으로, redis 서버에 비밀번호를 설정한 이상, redis 서버를 항상 먼저 켜서 비밀번호를 인증해야 한다. (?)

이때, 4번이 너무 이상했다.

spring이 redis의 비밀번호를 자동으로 연결해 줄 법한데..?

그리고 곧, application.yaml이 떠올라서 비밀번호를 기입해보았다.

결과

application.yaml에 redis의 비밀번호를 기입하면 된다.

application.yaml

spring:
  data:
    redis:
      host: localhost
      port: 6379
      password: "hello"

compose.yaml

version: '2.24.6'

services:
  redis:
    image: 'redis'
    restart: always
    command: 'redis-server --requirepass hello'
    ports:
    - '6379:6379'

바로 해결되었다 🤯

구현이 너무 하고 싶어서, application.yaml 및 compose.yaml을 제대로 찾아보지 않고 기재한 나의 잘못인 것 같긴 하다.

어쨌든 4시간에 걸쳐 디버깅 끝.

Reference

  1. NOAUTH Aunthentication required 해결하기
profile
안녕하세요, 개발자 비비입니다.

0개의 댓글