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
For me (Windows 10, Docker Engine v19.03.8) it was a mix of https://stackoverflow.com/a/43541732/7924573 and https://stackoverflow.com/a/50866007/7924573 .
version: '3.7'
services:
server:
build: .
ports:
- "5000:5000"
network_mode: bridge
or alternatively: Use --net="bridge"
if you are not using docker-compose (similar to https://stackoverflow.com/a/48806927/7924573)I've explored the various solution and I find this the least hacky solution:
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".
For linux systems, you can – starting from major version 20.04
of the docker engine – now also communicate with the host via host.docker.internal
. This won't work automatically, but you need to provide the following run flag:
--add-host=host.docker.internal:host-gateway
See
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
EDIT 2020-04-27: recommended for use only in local development environment.
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 the docker0
interface.
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.