사용자 공간 프록시가 비활성화된 경우 컨테이너에서 호스트 포트에 액세스

사용자 공간 프록시가 비활성화된 경우 컨테이너에서 호스트 포트에 액세스

브리지된 네트워크에 컨테이너가 있습니다. 문제 없이 호스트에 도달하고 호스트의 모든 포트에 연결됩니다(다른 컨테이너에서 게시한 포트 제외).

사용자 영역 프록시를 비활성화했기 때문에 docker가 iptable 규칙을 설정하는 방법과 관련이 있을 수 있다고 생각했습니다.

컨테이너가 다른 컨테이너(다른 브리지 네트워크에서 실행)가 게시한 포트에 도달하도록 허용하는 쉬운 방법이 있습니까?

두 컨테이너를 동일한 네트워크에 두지 않거나 호스트 네트워크로 전환하고 싶습니다.

답변1

문제를 재현할 수 없습니다.

두 개의 Docker 브리지 네트워크를 정의했습니다.

eecf335e7600   net1                   bridge    local
5c7ca74637b0   net2                   bridge    local

c1네트워크에서 컨테이너를 시작하고 net1컨테이너 포트를 8080호스트 포트에 게시합니다 8081.

$ docker run -d --rm --net net1 -p 8081:8080 --name c1 \
  --add-host host.docker.local:host-gateway  alpinelinux/darkhttpd

c2네트워크에서 컨테이너를 시작하고 net2컨테이너 포트를 8080호스트 포트에 게시합니다 8082.

$ docker run -d --rm --net net2 -p 8082:8080 --name c2 \
  --add-host host.docker.local:host-gateway  alpinelinux/darkhttpd

이제 컨테이너 내부에서 c1호스트 포트에 액세스하여 컨테이너의 웹 서비스에 액세스할 수 있습니다.c28082

$ docker exec c1 wget -O- http://host.docker.local:8082
Connecting to host.docker.local:8082 (172.17.0.1:8082)
writing to stdout
-                    100% |********************************|   191  0:00:00 ETA
written to stdout
<html>
<head>
...

컨테이너에서 c2호스트 포트에 액세스하여 컨테이너의 웹 서비스에 액세스할 수 있습니다.c18081

$ docker exec c2 wget -O- http://host.docker.local:8081
Connecting to host.docker.local:8081 (172.17.0.1:8081)
writing to stdout
-                    100% |********************************|   191  0:00:00 ETA
written to stdout
<html>
<head>
...

모든 것이 광고된 대로 작동하는 것 같았습니다. 동일한 단계를 반복해도 결과가 달라지는 경우 가장 먼저 확인해야 할 것은 호스트에 트래픽을 방해할 수 있는 방화벽 규칙이 있는지 확인하는 것입니다.

고쳐 쓰다

--add-host예상대로 해당 옵션을 사용하는 대신 호스트 주소만 선택해도 동작은 동일합니다. 예를 들어 다음과 같은 경우가 있습니다.

$ ip -o addr |grep -o '.*inet [^ ]*'
1: lo    inet 127.0.0.1/8
2: eth0    inet 192.168.123.106/24
4: docker_gwbridge    inet 172.23.0.1/16
8: br-70f125dc5b7d    inet 192.168.208.1/20
15: br-a87cc1462629    inet 172.29.0.1/16
18: docker0    inet 172.17.0.1/16
35: br-eecf335e7600    inet 172.18.0.1/16
36: br-5c7ca74637b0    inet 172.19.0.1/16

그러면 이것들은 모두 작동합니다:

$ docker exec c2 wget -O- 192.168.123.106:8081 | head -3
Connecting to 192.168.123.106:8081 (192.168.123.106:8081)
writing to stdout
-                    100% |********************************|   191  0:00:00 ETA
written to stdout
<html>
<head>
 <title>/</title>
$ docker exec c2 wget -O- 172.29.0.1:8081 | head -3
Connecting to 172.29.0.1:8081 (172.29.0.1:8081)
writing to stdout
-                    100% |********************************|   191  0:00:00 ETA
written to stdout
<html>
<head>
 <title>/</title>
$ docker exec c2 wget -O- 172.18.0.1:8081 | head -3
Connecting to 172.18.0.1:8081 (172.18.0.1:8081)
writing to stdout
-                    100% |********************************|   191  0:00:00 ETA
written to stdout
<html>
<head>
 <title>/</title>

등.

비활성화하기 전에 이 문제가 있었던 것이 확실하기 때문에 질문에서 언급하지 않았습니다.

이는 기본 설정에 비해 꽤 큰 구성 변경 사항입니다. :)

사용자 레이어 프록시를 비활성화하면 모든 것이 작동하지 않습니다.

이 기사관심이 있을 수 있는 항목:

이전 섹션에서는 Docker가 iptables NAT 규칙을 사용하여 게시된 포트를 컨테이너 서비스에 매핑할 수 없는 두 가지 시나리오를 식별했습니다.

  • 다른 Docker 네트워크에 연결된 컨테이너가 서비스에 액세스하려고 할 때(Docker가 Docker 네트워크 간의 직접 통신을 차단하고 있는 경우)
  • 로컬 프로세스가 루프백 인터페이스를 통해 서비스에 액세스하려고 시도하는 경우.

두 경우 모두 Docker는 사용자 수준(Linux 프로세스) TCP 또는 UDP 프록시를 사용합니다. 게시된 포트로 컨테이너를 시작한 후 netstat 명령을 사용하여 프록시를 쉽게 식별할 수 있습니다(표준 Flask 애플리케이션을 다시 사용하겠습니다).

관련 정보