it-source

도커 컨테이너로 호스트 포트 전달

criticalcode 2023. 8. 29. 20:41
반응형

도커 컨테이너로 호스트 포트 전달

호스트에서 도커 컨테이너 액세스 포트를 열 수 있습니까?구체적으로 호스트에서 MongoDB와 RabbitMQ를 실행하고 있으며 Docker 컨테이너에서 대기열을 듣고 (선택적으로) 데이터베이스에 쓰기 위한 프로세스를 실행하고 싶습니다.

컨테이너에서 호스트로 포트를 전달할 수 있으며(-p 옵션을 통해) 도커 컨테이너 내에서 외부(즉, 인터넷)에 연결할 수 있지만 호스트의 RabbitMQ 및 MongoDB 포트를 외부에 노출하지는 않습니다.

편집: 몇 가지 설명:

Starting Nmap 5.21 ( http://nmap.org ) at 2013-07-22 22:39 CEST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00027s latency).
PORT     STATE SERVICE
6311/tcp open  unknown

joelkuiper@vps20528 ~ % docker run -i -t base /bin/bash
root@f043b4b235a7:/# apt-get install nmap
root@f043b4b235a7:/# nmap 172.16.42.1 -p 6311 # IP found via docker inspect -> gateway

Starting Nmap 6.00 ( http://nmap.org ) at 2013-07-22 20:43 UTC
Nmap scan report for 172.16.42.1
Host is up (0.000060s latency).
PORT     STATE    SERVICE
6311/tcp filtered unknown
MAC Address: E2:69:9C:11:42:65 (Unknown)

Nmap done: 1 IP address (1 host up) scanned in 13.31 seconds

컨테이너 내에서 인터넷 연결을 위해 다음과 같은 방법을 사용해야 했습니다.방화벽이 도커 컨테이너에서 외부로의 네트워크 연결을 차단하고 있습니다.

편집: 결국 파이프 구조를 사용하여 사용자 지정 브리지를 만들고 브리지 IP에서 서비스를 수신하도록 했습니다.저는 MongoDB와 Rabbit 대신에 이 접근법을 사용했습니다.MQ는 더 많은 유연성을 제공하기 때문에 도커 브리지에서 청취합니다.

간단하지만 상대적으로 안전하지 않은 방법은 다음을 사용하는 것입니다.--net=host에 대한 선택권.docker run.

이 옵션을 사용하면 컨테이너가 호스트의 네트워킹 스택을 사용합니다.그런 다음 "localhost"를 호스트 이름으로 사용하여 호스트에서 실행 중인 서비스에 연결할 수 있습니다.

도커 컨테이너의 IP 주소에서 연결을 허용하도록 서비스를 구성할 필요가 없고 포트만 있으면 도커 컨테이너에 연결할 특정 IP 주소나 호스트 이름을 지정할 필요가 없기 때문에 구성이 더 쉽습니다.

예를 들어 다음 명령을 실행하여 테스트할 수 있습니다. 이 명령은 이미지의 호출을 가정합니다.my_image당신의 이미지는 다음을 포함합니다.telnet25에 . 포트 25는 다음과 같습니다.

docker run --rm -i -t --net=host my_image telnet localhost 25

이 방법을 사용할 경우 이 페이지의 보안에 대한 주의 사항을 참조하십시오.

https://docs.docker.com/articles/networking/

다음과 같이 표시됩니다.

--net=host - 컨테이너를 별도의 네트워크 스택 내부에 배치하지 않도록 도커에 지시합니다.본질적으로, 이 선택은 도커에게 컨테이너의 네트워킹을 컨테이너화하지 말라고 말합니다!컨테이너 프로세스는 여전히 자체 파일 시스템과 프로세스 목록 및 리소스 제한으로 제한되지만, 빠른 ip addr 명령을 사용하면 기본 도커 호스트에서 "외부"에 상주하며 해당 네트워크 인터페이스에 대한 전체 액세스 권한을 가지고 있음을 알 수 있습니다.이렇게 하면 컨테이너가 호스트 네트워크 스택을 재구성할 수 없습니다. --privileged=true가 필요합니다. 그러나 컨테이너 프로세스는 다른 루트 프로세스와 마찬가지로 낮은 번호의 포트를 열 수 있습니다.또한 컨테이너가 D-bus와 같은 로컬 네트워크 서비스에 액세스할 수 있도록 합니다.이로 인해 컨테이너의 프로세스가 컴퓨터를 다시 시작하는 등 예기치 않은 작업을 수행할 수 있습니다.이 옵션은 주의해서 사용해야 합니다.

도커 호스트가 어댑터를 모든 컨테이너에 노출합니다.최근 Ubuntu를 사용하고 있다고 가정하면

ip addr

네트워크 어댑터 목록이 제공되며, 그 중 하나는 다음과 같습니다.

3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 22:23:6b:28:6b:e0 brd ff:ff:ff:ff:ff:ff
inet 172.17.42.1/16 scope global docker0
inet6 fe80::a402:65ff:fe86:bba6/64 scope link
   valid_lft forever preferred_lft forever

토끼/몽고에게 해당 IP(172.17.42.1)에 바인딩하도록 지시해야 합니다.그런 다음 컨테이너 내에서 172.17.42.1에 대한 연결을 열 수 있습니다.

코멘트 중 하나에서 언급한 것처럼, 이것은 Mac에서도 작동합니다(아마도 Windows/Linux에서도 작동할 수 있습니다.

컨테이너에서 호스트의 서비스로 연결합니다.

호스트의 IP 주소가 변경되고 있습니다(네트워크 액세스 권한이 없는 경우에는 IP 주소가 변경되지 않음).한 DNS 이름 "DNS"에 하는 것이 .host.docker.internal호스트에서 사용하는 내부 IP 주소로 확인됩니다.이는 개발 목적이며 Mac용 Docker Desktop 이외의 운영 환경에서는 작동하지 않습니다.

다음을 사용하여 게이트웨이에 도달할 수도 있습니다.gateway.docker.internal.

https://docs.docker.com/docker-for-mac/networking/ 에서 인용

이것은 사용하지 않고도 작동했습니다.--net=host.

SSH 터널을 생성할 수도 있습니다.

docker-compose.yml:

---

version: '2'

services:
  kibana:
    image: "kibana:4.5.1"
    links:
      - elasticsearch
    volumes:
      - ./config/kibana:/opt/kibana/config:ro

  elasticsearch:
    build:
      context: .
      dockerfile: ./docker/Dockerfile.tunnel
    entrypoint: ssh
    command: "-N elasticsearch -L 0.0.0.0:9200:localhost:9200"

docker/Dockerfile.tunnel:

FROM buildpack-deps:jessie

RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive \
    apt-get -y install ssh && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

COPY ./config/ssh/id_rsa /root/.ssh/id_rsa
COPY ./config/ssh/config /root/.ssh/config
COPY ./config/ssh/known_hosts /root/.ssh/known_hosts
RUN chmod 600 /root/.ssh/id_rsa && \
    chmod 600 /root/.ssh/config && \
    chown $USER:$USER -R /root/.ssh

config/ssh/config:

# Elasticsearch Server
Host elasticsearch
    HostName jump.host.czerasz.com
    User czerasz
    ForwardAgent yes
    IdentityFile ~/.ssh/id_rsa

이쪽은elasticsearch인 서비스search, )가 .SQL) 및 해당 서비스를 통해 포트 9200을 노출합니다.

TLDR;

로컬 개발의 경우에만 다음을 수행합니다.

  1. 랩톱/컴퓨터/PC/Mac에서 서비스 또는 SSH 터널을 시작합니다.
  2. 호스트 이름에 연결할 도커 이미지/컨테이너 구축/실행host.docker.internal:<hostPort>

": 또있습다니한참고다있"도 있습니다.gateway.docker.internal내가 시도하지 않은 것.

END_TLDR;

예를 들어 컨테이너에서 이 기능을 사용하는 경우:

PGPASSWORD=password psql -h localhost -p 5432 -d mydb -U myuser

다음으로 변경:

PGPASSWORD=password psql -h host.docker.internal -p 5432 -d mydb -U myuser

그러면 호스트 시스템에서 실행 중인 서비스에 마법처럼 연결됩니다.당신은 필요없다니습가사를 사용할 .--net=host또는-p "hostPort:ContainerPort"또는-P

배경

자세한 내용은 https://docs.docker.com/docker-for-mac/networking/ #사용 사례 및 해결 방법을 참조하십시오.

Windows 10에서 AWS RDS Postgres 인스턴스에 대한 SSH 터널과 함께 사용했습니다.사용에서 변경하기만 하면 되었습니다.localhost:containerPort에서 의용에까지.host.docker.internal:hostPort.

도커 컨테이너에서 LDAP-서버에 액세스하는 데 비슷한 문제가 있었습니다.컨테이너에 고정 IP를 설정하고 방화벽 규칙을 추가했습니다.

docker-compose.yml:

version: '2'
services:
  containerName:
    image: dockerImageName:latest
    extra_hosts:
      - "dockerhost:192.168.50.1"
    networks:
      my_net:
        ipv4_address: 192.168.50.2
networks:
  my_net:
    ipam:
      config:
      - subnet: 192.168.50.0/24

iptables 규칙:

iptables -A INPUT -j ACCEPT -p tcp -s 192.168.50.2 -d $192.168.50.1 --dport portnumberOnHost

컨테이너 내부 액세스dockerhost:portnumberOnHost

MongoDB 및 RabbitMQ가 호스트에서 실행 중인 경우 포트가 도커 내에 없으므로 포트가 이미 노출되어 있어야 합니다.

필요하지 않습니다.-p옵션을 사용하여 컨테이너에서 호스트로 포트를 노출합니다.기본적으로 모든 포트가 노출됩니다.-p옵션을 사용하면 컨테이너의 포트를 호스트 외부에 노출할 수 있습니다.

그래서, 내 생각엔 당신은 필요 없을 것 같아요.-p전혀 그리고 그것은 잘 작동하고 있을 것입니다 :)

host.docker.internal또는gateway.docker.internal일반적으로 도커 맥 데스크톱 컨테이너에 매우 잘 작동하지만, 이것은 또한 그것이 설정하는 수용된 수신기에 매우 인색한 카프카에 관한 한 실패합니다.

socat를 실행하여 컨테이너 내부의 9092 포트를 호스트로 전달하여 이 문제를 우회했습니다.

apt-get install -y socat && socat tcp-l:9092,fork tcp:host.docker.internal:9092 &

기본적으로 저는 카프카를 실행하는 컨테이너 1개와 카프카에 연결해야 하는 앱 컨테이너 1개를 가지고 있습니다.앱 컨테이너 kafka 브로커 설정하기["host.docker.internal:9092"]작동하지 않습니다.그래서 저는 카프카 브로커들을["localhost:9092"]socat을 사용하여 포트를 호스트로 포워딩합니다. 호스트는 카프카 컨테이너로 포트 포워딩을 수행합니다.

저는 많은 시행착오 끝에 이 해결책에 도달했습니다.이것이 누군가에게 도움이 되기를 바랍니다!

올바른 질문에 답하고 있는지는 잘 모르겠지만, ssh 터널링을 통해 컨테이너 내부에서 원격 서비스에 대한 액세스를 허용해야 하는 경우 다음과 같이 작동합니다.

원격 호스트의 서비스가 포트 8081에서 액세스할 수 있다고 가정하고 ssh로 연결하고 다음과 같은 터널을 생성합니다(시작할 때 0.0.0).

ssh ubuntu@remoteIp -L 0.0.0.0:8080:localhost:8081

이렇게 하면 컴퓨터에 액세스할 수 있는 모든 사용자가 포트 8080에 연결하여 연결된 서버의 포트 8081에 액세스할 수 있습니다.

그런 다음 컨테이너 내부에서 "host.docker.internal"을 사용합니다. 예:

curl host.docker.internal:8081

이렇게 약간 다른 솔루션을 사용하면 어떨까요?

services:
  kubefwd:
    image: txn2/kubefwd
    command: ...
  app:
    image: bash
    command:
     - sleep
     - inf
    init: true
    network_mode: service:kubefwd

참조: txn2/kubewd: 현지 개발을 위한 벌크 포트 포워딩 쿠베르네테스 서비스.

오늘날의 모든 플랫폼에서 사용하기 쉬운 방법host.docker.internal먼저 Docker run 명령부터 시작하겠습니다.

docker run --add-host=host.docker.internal:host-gateway [....]

또는 Docker Compose를 사용할 때 서비스에 다음을 추가합니다.

extra_hosts:
  - "host.docker.internal:host-gateway"

이러한 도커 합성 파일의 전체 예는 다음과 같습니다.

version: "3"
services:
  your_service:
    image: username/docker_image_name
    restart: always
    networks:
      - your_bridge_network
    volumes:
      - /home/user/test.json:/app/test.json
    ports:
      - "8080:80"
    extra_hosts:
      - "host.docker.internal:host-gateway"

networks:
  your_bridge_network:

다시 말하지만, 그것은 단지 예시일 뿐입니다.그러나 이 도커 이미지가 포트 80에서 서비스를 시작하는 경우 포트 8080의 호스트에서 사용할 수 있습니다.

사용 사례에서 더 중요한 것은 도커 컨테이너가 호스트 시스템에서 제공하는 서비스를 사용하려는 경우 이 특수 기능을 사용할 수 있다는 것입니다.host.docker.internal 해당 으로 ( Docker 됩니다. 해당 이름은 자동으로 내부 Docker IP 주소로 확인됩니다.docker0인터페이스)를 선택합니다.

어쨌든, 예를 들어...또한 호스트 시스템에서 웹 서비스를 실행합니다(포트 80).이제 도커 컨테이너 내에서 해당 서비스에 액세스할 수 있습니다.사용해 보십시오.nc -vz host.docker.internal 80.

사용하지 않고 모두 사용network_mode: "host".

언급URL : https://stackoverflow.com/questions/17770902/forward-host-port-to-docker-container

반응형