Docker로 nGrinder 실행할 때 발생하는 Connected refused 해결하기

Woody·2024년 9월 20일

TIL

목록 보기
14/19

배경

  • 컴퓨터에 따로 nGrinder를 설치하기 싫어서 도커를 사용하기로 결정했다.
  • nGrinder문서를 참고해서 도커를 이용해서 nGrinder를 실행했다.

nGrinder 도커로 실행하기

docker pull ngrinder/controller
docker run -d -v ~/ngrinder-controller:/opt/ngrinder-controller --name controller -p 80:80 -p 16001:16001 -p 12000-12009:12000-12009 ngrinder/controller
  • -d : 백그라운드로 컨테이너 실행
  • -v ~/ngrinder-controller:/opt/ngrinder-controller : 호스트와 컨테이너 간의 볼륨을 마운트한다. 호스트의 ~ngrinder-controller 경로와 컨테이너 내부의 /opt/ngrinder-controller 경로를 연결한다.
  • -p : 호스트의 포트와 컨테이너의 포트를 바인딩한다.
  • ngrinder/controller : 해당 도커 이미지를 사용한다.
  • --name controller : 컨테이너의 이름을 controller로 설정한다.(중요!!)
docker pull ngrinder/agent
docker run -d --name agent --link controller:controller ngrinder/agent
  • --link controller:controller : 컨테이너 간에 네트워크를 설정하는 단계로 컨테이너 이름이 controller인 컨테이너와 네트워크를 연결한다. :controller 로 인해 agent 컨테이너 내부에서 controller라는 이름으로 controller 컨테이너에 접근할 수 있다.

TMI : --link

  • Docker 공식 문서를 보면 --link 명령어 같은 경우 권장하지 않고, 사용자 정의 네트워크를 만들어서 컨테이너 간의 통신을 설정하는 것을 권장한다.
  • 하지만, 도커 네트워크를 만드는 과정이 수반되기 때문에 귀찮아서 nGrinder 공식 문서대로 실행했다. (--link 를 사용해도 상관없다.)

문제

테스트 할 서버는 인텔리제이를 통해서 로컬에서 실행했고, 현재 상황은 아래와 같다.

도커로 nGrinder를 성공적으로 실행됐다면, localhost:80으로 nGrinder에 접속할 수 있다. 초기 ID, PW는 admin, admin으로 로그인할 수 있다.

nGrinder에 접속해 '127.0.0.1:8080/actuator/health'로 요청을 보내는 스크립트를 작성하고 실행한 결과, Connection refused 에러가 발생했다.

에러 원인을 알기 전에 nGrinder의 동작 방식은 간단하게 다음과 같다.

  • 사용자가 스크립트를 작성해서 테스트 시나리오를 controller에게 전달한다.

  • controller는 여러 대의 agent를 가지고 있으며, 해당 스크립트를 agent에게 실행하도록 한다.

  • agent는 타켓 서버에 요청을 보낸다.

에러 원인

원인

  • agent에서 로컬 서버로 요청을 보낸다.

  • agent는 컨테이너로 실행 중이다.

  • agent 컨테이너를 실행할 때 8080 포트는 아무런 연결을 하지 않았다.

nGrinder의 동작 방식에서 agent에서 타켓 서버로 요청을 보낸다. 를 주목하자. 현재 agent는 컨테이너로 실행되고 있다. 그리고, 컨테이너에서 127.0.0.1을 요청하면 agent 컨테이너 내부의 localhost:8080으로 통신을 요청한다.

하지만, 서버는 agent 컨테이너 외부에 있고, agent 컨테이너 내부의 8080포트에는 서버가 실행되고 있지 않기 때문에 Connection refused 에러가 발생한다.

해결 방법1: ngrok으로 터널링하기 [비추천]

ngrok은 로컬에 실행된 서버를 터널링을 통해 외부에서 접속할 수 있도록 도와주는 플랫폼이다.

ngrok 또한 Docker image가 있기 때문에 다음과 같이 실행할 수 있다. - 공식문서 참고

docker run -it -e NGROK_AUTHTOKEN=xyz ngrok/ngrok:alpine http host.docker.internal:8080
  • -e NGROK_AUTHTOKEN: 환경 변수를 설정한다. ngrok의 토큰으로 NGROK 회원 가입 이후에 받을 수 있다.
  • ngrok/ngrok:alpine: alpine 버전의 ngrok 이미지를 사용한다.
  • host.docker.internal:8080: 문서에 나온 것 같이 윈도우, 맥 환경으로 실행할 때, host.docker.internal:[포트번호] 형식으로 실행해야 한다. 현재 8080 포트로 서버를 실행하기 때문에 8080으로 실행한다.
  • --log stdout: 컨테이너에서 발생하는 것을 로그로 표현하는 명령어로 이를 통해서 url을 확인한다. 하지만 ngrok 홈페이지에 들어가서 확인할 수 있어서 해당 명령어는 선택이다.

이제 테스트 스크립트를 127.0.0.1 대신 ngrok에서 제공해주는 url로 바꾸면 성공적으로 부하 테스트를 성공할 수 있다.

하지만 다음과 같은 이유로 ngrok을 추천하지 않는다.

  • ngrok의 무료 버전은 다음과 같이 트래픽 제한이 있다.

nGrinder에서는 수많은 요청을 ngrok에게 보내면, 대부분의 요청을 429:too many request 에러로 반환해서 20초 내로 부하테스트가 종료된다.

해결법2: 127.0.0.1 대신 host.docker.internal 사용하기

문제의 원인은 agent 컨테이너가 Host의 로컬 서버를 접근하지 못하는 것이다. Docker 문서에서 host.docker.internal명령어를 통해서 Host에 접근할 수 있는 것을 알았다.

host.docker.internal: 컨테이너 내부에서 Host의 접근이 가능하도록 만드는 DNS이다.

부하 테스트 스크립트를 127.0.0.1:8080 → host.docker.internal:8080 으로 변경했고, 그 결과 agent가 Host의 서버로 요청을 잘 보내는 것을 볼 수 있다.

HTTPResponse response = request.GET("http://host.docker.internal:8080/actuator/health", params)

마치며

도커의 동작을 잘 몰랐기 때문에 많이 해맸다고 생각한다. 이 과정을 통해서 도커의 호스트와 컨테이너 관계에 대해 이해할 수 있었고, 역시 기본부터 잘 알아야 된다는 것을 다시금 깨달았다.

0개의 댓글