问题
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 server (which can be configured to run on a port) can be exposed to the jenkins container?
EDIT: I\'m running docker natively on a Linux machine.
UPDATE:
In addition to @larsks answer below, to get the IP address of the Host IP from the host machine, I do the following:
ip addr show docker0 | grep -Po \'inet \\K[\\d.]+\'
回答1:
When running Docker natively on Linux, you can access host services using the IP address of the docker0
interface. From inside the container, this will be your default route.
For example, on my system:
$ 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
And inside a container:
# ip route show
default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth0 src 172.17.0.4
It's fairly easy to extract this IP address using a simple shell script:
#!/bin/sh
hostip=$(ip route show | awk '/default/ {print $3}')
echo $hostip
You may need to modify the iptables
rules on your host to permit
connections from Docker containers. Something like this will do the
trick:
# iptables -A INPUT -i docker0 -j ACCEPT
This would permit access to any ports on the host from Docker containers. Note that:
iptables rules are ordered, and this rule may or may not do the right thing depending on what other rules come before it.
you will only be able to access host services that are either (a) listening on
INADDR_ANY
(aka 0.0.0.0) or that are explicitly listening on thedocker0
interface.
回答2:
For macOS and Windows
Docker v 18.03 and above (since March 21st 2018)
Use your internal IP address or connect to the special DNS name host.docker.internal
which will resolve to the internal IP address used by the host.
Linux support pending https://github.com/docker/for-linux/issues/264
MacOS with earlier versions of Docker
Docker for Mac v 17.12 to v 18.02
Same as above but use docker.for.mac.host.internal
instead.
Docker for Mac v 17.06 to v 17.11
Same as above but use docker.for.mac.localhost
instead.
Docker for Mac 17.05 and below
To access host machine from the docker container you must attach an IP alias to your network interface. You can bind whichever IP you want, just make sure you're not using it to anything else.
sudo ifconfig lo0 alias 123.123.123.123/24
Then make sure that you server is listening to the IP mentioned above or 0.0.0.0
. If it's listening on localhost 127.0.0.1
it will not accept the connection.
Then just point your docker container to this IP and you can access the host machine!
To test you can run something like curl -X GET 123.123.123.123:3000
inside the container.
The alias will reset on every reboot so create a start-up script if necessary.
Solution and more documentation here: https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds
回答3:
Use --net="host"
in your docker run
command, then localhost
in your docker container will point to your docker host.
回答4:
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
回答5:
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).
回答6:
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
回答7:
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.
回答8:
You can access the local webserver which is running in your host machine in two ways.
Approach 1 with public IP
Use host machine public IP address to access webserver in Jenkins docker container.
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
回答9:
I've explored the various solution and I find this the least hacky solution:
- Define a static IP address for the bridge gateway IP.
- 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".
回答10:
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.
来源:https://stackoverflow.com/questions/31324981/how-to-access-host-port-from-docker-container