docker swarm에서 nginx가 실제 ip를 전달하는 방법
2026. 01. 06.
왜 실제 ip가 아니라 ingress ip가 나타났을까?
docker service create \
--name my-web \
--replicas 2 \
-p 8080:80 \
nginx
위와 같이 nginx 서비스를 생성했을 때 유저의 ip를 찍어보면 10.0.0.x 형태의 ingress ip가 찍히는 것을 알 수 있다. 왜 그럴까? 도커스웜은 스웜 모드에 참여한 모드 서버(노드)를 ingress routing mesh에 참가시킨다. 그래서 만들어진 서비스에 연결되기 전 라우팅 메시를 거쳐가기 때문에 유저의 실제 ip를 수집하려고 해도 10.0.0.x 형태의 ingress ip를 수집하게 된 것이다.
라우팅 메시의 역할은 무엇일까?
우선 공식 문서에 있는 위의 이미지를 이해해보자.
- 100번, 101번, 102번의 서버가 있고 스웜모드로 연결되어 있다.
- my-web이라는 서비스가 스웜모드 내에서 2개 띄워져있다(replica가 2개)
- 노드의 8080 포트와 서비스의 80 포트가 연결되어 있다.
기본적으로 이미지를 보면 위와 같은 상황을 알 수 있다. 이제 102번의 8080 포트로 접근했을 때 일어나는 일을 살펴보자. 102번 서버에는 my-web이라는 서비스가 실제 띄워져 있지만 않지만 실제 서비스가 돌아가고 있는 서버로 라우팅 되는 것을 알 수 있는데 이것이 스웜 모드에서 라우팅 메시의 역할이다. 그리고 nginx를 통해서 proxy pass 해주기 전에 라우팅 메시를 거쳐가기 때문에 사용자의 ip를 제대로 수집할 수 없는 것이다.
라우팅 메시 우회하기
라우팅 메시를 우회해서 특정 노드의 포트로 바로 접근할 수 있도록 설정할 수 있는데, 이것을 host 모드라고 한다. host 모드로 해주려면 위에서 했던 설정을 아래처럼 바꿔주어야 한다.
docker service create \
--name my-web \
--mode global \
--publish published=8080,target=80,protocol=tcp,mode=host \
nginx
mode를 host로 입력해주려면 축약형이 아니라 설정을 다 써줘야 한다. 그리고 host 모드를 사용하는데 있어서 중요한 점은 mode를 global로 설정해주는 것이다. 위에 이미지를 다시 살펴보자. 102번의 8080포트에 접속했지만 라우팅 메시가 없다면 102번에서만 연결된 서비스를 찾을 것이다. 그래서 여러대의 노드(서버)를 사용하고 있다면 global 설정을 통해서 각 노드가 1개씩의 서비스를 가지도록 해서 서비스를 못 찾는 일이 없도록 해줘야 한다.