How to access host port from docker container

前端 未结 14 1500
南旧
南旧 2020-11-22 03:41

I have a docker container running jenkins. As part of the build process, I need to access a web server that is run locally on the host machine. Is there a way the host web s

相关标签:
14条回答
  • 2020-11-22 04:00

    This is an old question and had many answers, but none of those fit well enough to my context. In my case, the containers are very lean and do not contain any of the networking tools necessary to extract the host's ip address from within the container.

    Also, usin the --net="host" approach is a very rough approach that is not applicable when one wants to have well isolated network configuration with several containers.

    So, my approach is to extract the hosts' address at the host's side, and then pass it to the container with --add-host parameter:

    $ docker run --add-host=docker-host:`ip addr show docker0 | grep -Po 'inet \K[\d.]+'` image_name
    

    or, save the host's IP address in an environment variable and use the variable later:

    $ DOCKERIP=`ip addr show docker0 | grep -Po 'inet \K[\d.]+'`
    $ docker run --add-host=docker-host:$DOCKERIP image_name
    

    And then the docker-host is added to the container's hosts file, and you can use it in your database connection strings or API URLs.

    0 讨论(0)
  • 2020-11-22 04:01

    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.

    0 讨论(0)
  • 2020-11-22 04:02

    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

    0 讨论(0)
  • 2020-11-22 04:02

    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
    
    0 讨论(0)
  • 2020-11-22 04:03

    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).

    0 讨论(0)
  • 2020-11-22 04:03

    For docker-compose using bridge networking to create a private network between containers, the accepted solution using docker0 doesn't work because the egress interface from the containers is not docker0, but instead, it's a randomly generated interface id, such as:

    $ ifconfig
    
    br-02d7f5ba5a51: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 192.168.32.1  netmask 255.255.240.0  broadcast 192.168.47.255
    

    Unfortunately that random id is not predictable and will change each time compose has to recreate the network (e.g. on a host reboot). My solution to this is to create the private network in a known subnet and configure iptables to accept that range:

    Compose file snippet:

    version: "3.7"
    
    services:
      mongodb:
        image: mongo:4.2.2
        networks:
        - mynet
        # rest of service config and other services removed for clarity
    
    networks:
      mynet:
        name: mynet
        ipam:
          driver: default
          config:
          - subnet: "192.168.32.0/20"
    

    You can change the subnet if your environment requires it. I arbitrarily selected 192.168.32.0/20 by using docker network inspect to see what was being created by default.

    Configure iptables on the host to permit the private subnet as a source:

    $ iptables -I INPUT 1 -s 192.168.32.0/20 -j ACCEPT
    

    This is the simplest possible iptables rule. You may wish to add other restrictions, for example by destination port. Don't forget to persist your iptables rules when you're happy they're working.

    This approach has the advantage of being repeatable and therefore automatable. I use ansible's template module to deploy my compose file with variable substitution and then use the iptables and shell modules to configure and persist the firewall rules, respectively.

    0 讨论(0)
提交回复
热议问题