Programing

도커 컨테이너에서 호스트 포트에 액세스하는 방법

lottogame 2020. 5. 6. 20:49
반응형

도커 컨테이너에서 호스트 포트에 액세스하는 방법


jenkins를 실행하는 도커 컨테이너가 있습니다. 빌드 프로세스의 일부로 호스트 시스템에서 로컬로 실행되는 웹 서버에 액세스해야합니다. 호스트 웹 서버 (포트에서 실행되도록 구성 할 수있는)가 jenkins 컨테이너에 노출 될 수있는 방법이 있습니까?

편집 : Linux 시스템에서 기본적으로 docker를 실행하고 있습니다.

최신 정보:

아래 @larsks 응답 외에도 호스트 컴퓨터에서 호스트 IP의 IP 주소를 얻으려면 다음을 수행하십시오.

ip addr show docker0 | grep -Po 'inet \K[\d.]+'

Linux에서 Docker를 기본적으로 실행하는 경우 docker0인터페이스 의 IP 주소를 사용하여 호스트 서비스에 액세스 할 수 있습니다 . 컨테이너 내부에서 기본 경로가됩니다.

예를 들어, 내 시스템에서 :

$ ip addr show docker0
7: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::f4d2:49ff:fedd:28a0/64 scope link 
       valid_lft forever preferred_lft forever

그리고 컨테이너 내부 :

# ip route show
default via 172.17.0.1 dev eth0 
172.17.0.0/16 dev eth0  src 172.17.0.4 

간단한 쉘 스크립트를 사용하여이 IP 주소를 추출하는 것은 매우 쉽습니다.

#!/bin/sh

hostip=$(ip route show | awk '/default/ {print $3}')
echo $hostip

iptablesDocker 컨테이너의 연결을 허용하기 위해 호스트 규칙 을 수정해야 할 수도 있습니다 . 이와 같은 것이 트릭을 수행합니다.

# iptables -A INPUT -i docker0 -j ACCEPT

이렇게하면 Docker 컨테이너에서 호스트의 모든 포트에 액세스 할 수 있습니다. 참고 :

  • iptables 규칙이 순서화되어 있으며이 규칙은 다른 규칙이 무엇인지에 따라 올바른 작업을 수행하거나 수행하지 않을 수 있습니다.

  • (a) 청취 중 INADDR_ANY(일명 0.0.0.0)이거나 docker0인터페이스 에서 명시 적으로 청취중인 호스트 서비스에만 액세스 할 수 있습니다.


macOS 및 Windows의 경우

Docker v 18.03 이상 (2018 년 3 월 21 일부터)

host.docker.internal내부 IP 주소를 사용하거나 호스트가 사용하는 내부 IP 주소로 해석되는 특수 DNS 이름에 연결 하십시오.

Linux 지원 보류 https://github.com/docker/for-linux/issues/264

이전 버전의 Docker가있는 MacOS

Mac 용 Docker v 17.12 ~ v 18.02

위와 동일하지만 docker.for.mac.host.internal대신 사용하십시오.

Mac 용 Docker v 17.06 ~ v 17.11

위와 동일하지만 docker.for.mac.localhost대신 사용하십시오.

Mac 17.05 이하용 Docker

도커 컨테이너에서 호스트 시스템에 액세스하려면 IP 별칭을 네트워크 인터페이스에 연결해야합니다. 원하는 IP를 바인딩 할 수 있으며 다른 IP에는 사용하지 않아야합니다.

sudo ifconfig lo0 alias 123.123.123.123/24

그런 다음 서버가 위에서 언급 한 IP 또는를 듣고 있는지 확인하십시오 0.0.0.0. 로컬 호스트에서 수신 대기 중이 127.0.0.1면 연결을 수락하지 않습니다.

그런 다음 도커 컨테이너를이 IP를 가리키면 호스트 시스템에 액세스 할 수 있습니다!

테스트하기 curl -X GET 123.123.123.123:3000위해 컨테이너 내부 와 같은 것을 실행할 수 있습니다 .

별칭은 재부팅 할 때마다 재설정되므로 필요한 경우 시작 스크립트를 작성하십시오.

Solution and more documentation here: https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds


Use --net="host" in your docker run command, then localhost in your docker container will point to your docker host.


Solution with docker-compose: For accessing to host-based service you can use network_mode parameter https://docs.docker.com/compose/compose-file/#network_mode

version: '3'
services:
  jenkins:
    network_mode: host

Currently the easiest way to do this on Mac and Windows is using host host.docker.internal, that resolves to host machine's IP address. Unfortunately it does not work on linux yet (as of April 2018).


I created a docker container for doing exactly that https://github.com/qoomon/docker-host

You can then simply use container name dns to access host system e.g. curl http://dockerhost:9200


We found that a simpler solution to all this networking junk is to just use the domain socket for the service. If you're trying to connect to the host anyway, just mount the socket as a volume, and you're on your way. For postgresql, this was as simple as:

docker run -v /var/run/postgresql:/var/run/postgresql

Then we just set up our database connection to use the socket instead of network. Literally that easy.


You can access the local webserver which is running in your host machine in two ways.

  1. Approach 1 with public IP

    Use host machine public IP address to access webserver in Jenkins docker container.

  2. Approach 2 with the host network

    Use "--net host" to add the Jenkins docker container on the host's network stack. Containers which are deployed on host's stack have entire access to the host interface. You can access local webserver in docker container with a private IP address of the host machine.

NETWORK ID          NAME                      DRIVER              SCOPE
b3554ea51ca3        bridge                    bridge              local
2f0d6d6fdd88        host                      host                local
b9c2a4bc23b2        none                      null                local

Start a container with the host network Eg: docker run --net host -it ubuntu and run ifconfig to list all available network IP addresses which are reachable from docker container.

Eg: I started a nginx server in my local host machine and I am able to access the nginx website URLs from Ubuntu docker container.

docker run --net host -it ubuntu

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
a604f7af5e36        ubuntu              "/bin/bash"         22 seconds ago      Up 20 seconds                           ubuntu_server

Accessing the Nginx web server (running in local host machine) from Ubuntu docker container with private network IP address.

root@linuxkit-025000000001:/# curl 192.168.x.x -I
HTTP/1.1 200 OK
Server: nginx/1.15.10
Date: Tue, 09 Apr 2019 05:12:12 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 26 Mar 2019 14:04:38 GMT
Connection: keep-alive
ETag: "5c9a3176-264"
Accept-Ranges: bytes

I've explored the various solution and I find this the least hacky solution:

  1. Define a static IP address for the bridge gateway IP.
  2. Add the gateway IP as an extra entry in the extra_hosts directive.

The only downside is if you have multiple networks or projects doing this, you have to ensure that their IP address range do not conflict.

Here is a Docker Compose example:

version: '2.3'

services:
  redis:
    image: "redis"
    extra_hosts:
      - "dockerhost:172.20.0.1"

networks:
  default:
    ipam:
      driver: default
      config:
      - subnet: 172.20.0.0/16
        gateway: 172.20.0.1

You can then access ports on the host from inside the container using the hostname "dockerhost".


When you have two docker images "already" created and you want to put two containers to communicate with one-another.

For that, you can conveniently run each container with its own --name and use the --link flag to enable communication between them. You do not get this during docker build though.

When you are in a scenario like myself, and it is your

docker build -t "centos7/someApp" someApp/ 

That breaks when you try to

curl http://172.17.0.1:localPort/fileIWouldLikeToDownload.tar.gz > dump.tar.gz

and you get stuck on "curl/wget" returning no "route to host".

The reason is security that is set in place by docker that by default is banning communication from a container towards the host or other containers running on your host. This was quite surprising to me, I must say, you would expect the echosystem of docker machines running on a local machine just flawlessly can access each other without too much hurdle.

The explanation for this is described in detail in the following documentation.

http://www.dedoimedo.com/computers/docker-networking.html

Two quick workarounds are given that help you get moving by lowering down the network security.

The simplest alternative is just to turn the firewall off - or allow all. This means running the necessary command, which could be systemctl stop firewalld, iptables -F or equivalent.

Hope this information helps you.

참고URL : https://stackoverflow.com/questions/31324981/how-to-access-host-port-from-docker-container

반응형