저는 도커 초보자입니다. 도커 실행 명령에서 이 옵션이 무엇을 하는지에 대한 명확한 설명을 찾을 수 없어서 약간 혼란스러웠습니다.
포트를 지정하지 않고 도커 컨테이너에서 실행되는 애플리케이션에 액세스하는 데 사용할 수 있나요? 예를 들어 도커 실행 명령에서 -p 8080:8080
옵션을 사용하여 포트 8080에서 도커 이미지를 통해 배포 된 웹앱을 실행하는 경우 도커 컨테이너의 8080 포트에서 ip / theWebAppName에 액세스해야한다는 것을 알고 있습니다. 그러나 --net=host
옵션이 어떻게 작동하는지 실제로 생각할 수 없습니다.
도커를 설치하면 기본적으로 3개의 네트워크가 제공됩니다:
docker network ls
NETWORK ID NAME DRIVER SCOPE
f3be8b1ef7ce bridge bridge local
fbff927877c1 host host local
023bb5940080 none null local
저는 이것을 단순하게 유지하려고 합니다. 따라서 기본적으로 컨테이너를 시작하면 브리지(docker0) 네트워크 내부에 생성됩니다.
$ docker run -d jenkins
1498e581cdba jenkins "/bin/tini -- /usr..." 3 minutes ago Up 3 minutes 8080/tcp, 50000/tcp friendly_bell
젠킨스의 도커파일에는 포트 8080
과 50000
이 노출되어 있습니다. 이 포트는 브리지 네트워크의 컨테이너를 위해 열려 있습니다. 따라서 해당 브리지 네트워크 내의 모든 것이 포트 8080
및 50000
의 컨테이너에 액세스할 수 있습니다. 브리지 네트워크의 모든 것이 서브넷
: 172.17.0.0/16
의 프라이빗 범위에 있으므로 외부에서 액세스하려면 `-p 8080:8080
으로 포트를 매핑해야 합니다. 이렇게 하면 컨테이너의 포트가 실제 서버(호스트 네트워크)의 포트에 매핑됩니다. 따라서 8080
에서 서버에 액세스하면 포트 8080
의 브릿지 네트워크로 라우팅됩니다.
이제 호스트 네트워크도 생겼습니다. 이는 컨테이너 네트워킹을 컨테이너화하지 않는다. 따라서 호스트 네트워크에서 컨테이너를 시작하면 다음과 같이 보일 것입니다(첫 번째 컨테이너):
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1efd834949b2 jenkins "/bin/tini -- /usr..." 6 minutes ago Up 6 minutes eloquent_panini
1498e581cdba jenkins "/bin/tini -- /usr..." 10 minutes ago Up 10 minutes 8080/tcp, 50000/tcp friendly_bell
차이점은 포트에 있다. 이제 컨테이너가 호스트 네트워크 안에 있습니다. 따라서 호스트에서 포트 8080
을 열면 컨테이너에 즉시 액세스할 수 있습니다.
$ sudo iptables -I INPUT 5 -p tcp -m tcp --dport 8080 -j ACCEPT
방화벽에서 포트 8080
을 열었고 이제 포트 8080
에서 내 서버에 액세스하면 내 젠킨스에 액세스하는 것입니다. 이 블로그]1도 더 잘 이해하는 데 유용하다고 생각합니다.
net=host` 옵션은 네트워크의 관점에서 Docker 컨테이너 내부의 프로그램이 호스트 자체에서 실행되는 것처럼 보이게 하는 데 사용됩니다. 이를 통해 컨테이너는 일반적으로 얻을 수 있는 것보다 더 많은 네트워크 액세스를 허용합니다.
일반적으로 호스트 머신에서 컨테이너로 포트를 전달해야 하지만, 컨테이너가 호스트의 네트워크를 공유하면 프로그램이 컨테이너 내부가 아닌 로컬에서 실행되는 것처럼 모든 네트워크 활동이 호스트 머신에서 직접 발생합니다.
이는 더 이상 포트를 노출하고 컨테이너 포트에 매핑할 필요가 없다는 것을 의미하지만, 동일한 호스트 포트에서 두 개의 컨테이너가 작동할 수 없기 때문에 충돌을 피하기 위해 각 컨테이너가 수신 대기하는 포트를 조정하기 위해 Docker파일을 편집해야 한다는 것을 의미합니다. 그러나 이 옵션을 사용하는 실제 이유는 포트 수준에서 컨테이너로 전달하기 어려운 네트워크 액세스가 필요한 앱을 실행하기 위해서입니다.
예를 들어 DHCP 서버를 실행하려면 네트워크에서 브로드캐스트 트래픽을 수신하고 패킷에서 MAC 주소를 추출할 수 있어야 합니다. 이 정보는 포트 포워딩 프로세스 중에 손실되므로, Docker 내에서 DHCP 서버를 실행하는 유일한 방법은 컨테이너를 --net=host
로 실행하는 것입니다.
일반적으로 --net=host
는 매우 구체적이고 특이한 네트워크 요구 사항을 가진 프로그램을 실행하는 경우에만 필요합니다.
마지막으로, 보안 관점에서 볼 때, 도커 컨테이너는 단일 포트만 광고(노출)하지만 여러 포트에서 수신 대기할 수 있습니다. 일반적으로는 예상되는 단일 포트만 전달하기 때문에 괜찮지만, --호스트=넷
을 사용하면 호스트에서 컨테이너의 모든 포트를 수신 대기하게 되며, 이는 도커파일에 나열되지 않은 포트도 포함합니다. 즉, 컨테이너를 면밀히 확인하여(특히 소프트웨어 프로젝트에서 제공하는 공식 컨테이너와 같이 내 컨테이너가 아닌 경우) 실수로 머신에 추가 서비스를 노출시키지 않도록 해야 합니다.