Docker daemon and DNS - dns

I am trying to force the docker daemon to use my DNS server which is binded to bridge0 interface.
I have added --dns 172.17.42.1 in my docker_opts but no success
DNS server reply ok with dig command:
dig #172.17.42.1 registry.service.consul SRV +short
1 1 5000 registry2.node.staging.consul.
But pull with this domain fails:
docker pull registry.service.consul:5000/test
FATA[0000] Error: issecure: could not resolve "registry.service.consul": lookup registry.service.consul: no such host
PS: By adding nameserver 172.17.42.1 in my /etc/resolv.conf solve the issue but the DNS has to be exclusively for docker commands.
Any idea ?

You passed --dns 172.17.42.1 to docker_opts, so since that you should be able to resolve the container hostnames from inside other containers. But obviously you're doing docker pull from the host, not from the container, isn't it? Therefore it's not surprising that you cannot resolve container's hostname from your host, because it is not configured to use 172.17.42.1 for resolving.
I see two possible solutions here:
Force your host to use 172.17.42.1 as DNS (/etc/resolv.conf etc).
Create a special container with Docker client inside and mount docker.sock inside it. This will make you able to use all client commands including pull:
docker run -d -v /var/run/docker.sock:/var/run/docker.sock:rw --name=client ...
docker exec -it client docker pull registry.service.consul:5000/test

Related

No Internet Access In Docker Container When Connected to Cisco AnyConnect VPN

I am connected to a corporate VPN and need to be able to run docker containers while the VPN is connected due to the fact that the container needs to be able to access corporate endpoints. However, when I am connected with AnyConnect VPN, docker has no internet access at all. Neither to our corporate endpoints or the internet.
I am running CentOS7 as my host operating system.
A simple way to reproduce this issue is to install a minimal linux distro, install AnyConnect VPN, connect to vpn and try to run the following docker container:
docker run -i -t ubuntu:14.04 /bin/bash
Once inside the container I try to ping google dns
[###]$ ping 8.8.8.8
There will be no response. If I disconnect from AnyConnect VPN and retry the above, I get a ping response.
How can I fix this issue?
Ping outside and internet access are different. You could access internet but could not ping as limit by your corporation network. I suggest running busybox
docker run -it --rm busybox
and check the dns setup inside
cat /etc/resolv.conf
From there you may see list of nameserver ip addresses. Now you could try to ping those to make sure they are reachable from inside. If not, you could try
traceroute 1.2.3.4
to see how far you could go from inside container, the first 2 lines should be ip of docker and the host machine, and then the ip of your corporation network
1 172.17.0.1 (172.17.0.1) 0.016 ms 0.011 ms 0.009 ms
2 10.1.249.4 (10.1.249.4) 38.487 ms 35.697 ms 35.558 ms
Usually it's problem of the nameserver generated inside /etc/resolv.conf
file. If it's the case, then you need to check /etc/resolv.conf
in the host machine and update the docker setup to generate the nameservers correctly inside container.
After you make a change to the network interfaces, you often need to restart the docker engine to rebuild all of the routes and iptables entries. With Linux and systemd, use:
systemctl restart docker

Bind docker container loopback to the host loopback

I pull a docker image (will use python 3 as an example)
docker pull python:3.6
Then I launch a docker container
docker run -it -p 127.0.0.1:8000:8000 python:3.6 bash
(note that here 127.0.0.1 in 127.0.0.1:8000:8000 allows to specify the destination, host IP but not the source)
So if I launch a server inside the container at 0.0.0.0:
python -m http.server 8000 --bind 0.0.0.0
then I can access the container's server from the host machine without any problem by going to http://127.0.0.1:8000 at the host machine
However if my docker server binds to 127.0.0.1 instead of 0.0.0.0:
python -m http.server 8000 --bind 127.0.0.1
then accessing http://127.0.0.1:8000 from the host does not work.
What's the proper way of binding the container's loopback 127.0.0.1 to the host loopback?
What's the proper way of binding the container's loopback 127.0.0.1 to the host loopback?
On Linux, this can be done by configuring your Docker container to use the hosts network namespace, ie:
docker run --network=host
This only works on Linux because on Linux, your machine is the host, and the containers run as containers in your machines OS. On Windows/OSX, the Docker host runs as a virtual machine, with the containers running in the virtual machine, and so they can't share your machines network namespace.
What's the proper way of binding the container's loopback 127.0.0.1 to the host loopback?
You can't do that. The loopback interface inside a container means "only this container", just like on the host means "only this host". If a service is binding to 127.0.0.1 then there is no way -- from your host or from another container -- to reach that service.
The only way to do what you want is either:
Modify the application configuration to listen on all interfaces (or eth0 specifically), or
Run a proxy inside your container that binds to all interfaces and forwards connections to the localhost address.

Docker DNS settings

I try create docker container with custom network and dos settings.
docker network create --driver=bridge --opt "com.docker.network.bridge.enable_ip_masquerade"="true" --opt "com.docker.network.bridge.enable_icc"="true" --opt="com.docker.network.driver.mtu"="1500" --opt="com.docker.network.bridge.host_binding_ipv4"="0.0.0.0" net
--
docker run --dns 10.0.0.2 --network=net busybox cat /etc/resolv.conf
nameserver 127.0.0.11
options ndots:0
Else if I use standard network all work fine
docker run --dns 10.0.0.2 --network=bridge busybox cat /etc/resolv.conf
nameserver 10.0.0.2
As of Docker 1.10, DNS is managed differently for user-defined networks. DNS for the default bridge network is unchanged for backwards compatibility. In a user-defined network, docker daemon uses the embedded DNS server. According to the documentation found here:
https://docs.docker.com/engine/userguide/networking/configure-dns/
--dns=[IP_ADDRESS...] The IP addresses passed via the --dns option is used by the embedded
DNS server to forward the DNS query if embedded DNS server is unable
to resolve a name resolution request from the containers. These
--dns IP addresses are managed by the embedded DNS server and will not
be updated in the container’s /etc/resolv.conf file.
So, the DNS nameserver will be used, it just is not visible in the container's /etc/resolv.conf.

Run dnsmasq as DHCP server from inside a Docker container

I'm trying to get dnsmasq to operate as a DHCP server inside a Docker container, issuing DHCP addresses to machines on the host's physical network. I'm using the Alpine Linux 6MB container from https://hub.docker.com/r/andyshinn/dnsmasq/.
It works fine as a DNS server on port 53 on the host machine, however there is nothing listening on port 67/udp, which is where I'm expecting DHCP to be. I use
dhcping 192.168.2.2, but get "no answer". telnet 192.168.2.2 67 returns "Connection refused".
My dnsmasq.conf file in the container looks like this:
interface=eth0
user=root
domain-needed
bogus-priv
no-resolv
local=/mydomain.io/
no-poll
server=8.8.8.8
server=8.8.4.4
no-hosts
addn-hosts=/etc/dnsmasq_static_hosts.conf
expand-hosts
domain=mydomain.io
dhcp-range=192.168.2.10,192.168.2.250,255.255.255.0,192.168.2.255,5m
# Have windows machine release on shutdown
dhcp-option=vendor:MSFT,2,1i
# No default route
dhcp-option=3
The host machine has a static address of 192.168.2.2.
I start the container like this:
docker run -d --name dns -p 192.168.2.2:67:67/udp -p 192.168.2.2:53:53/udp sitapati/dns
There is no firewall on this machine, which is running Ubuntu 16.04.
Things I've thought of/tried:
is it because eth0 in the container has an address on a completely different subnet? (docker inspect tells me it's 172.17.0.2 on the bridged interface)
does it need to use --net host? I tried that, and it still didn't work.
Yes, the container will have its own interfaces on a virtual subnet (the docker0 bridge network). So it will be trying to offer addresses on that subnet.
Using --net host worked for me, I got the DHCP server working using something like the following command:
docker run --name dnsmasq2 -t -v /vagrant/dnsmasq.conf:/opt/dnsmasq.conf -p 67:67/udp --net host centos
--net host ensures that the container appears to using the host's networking stack rather than its own.
dnsmasq -q -d --conf-file=/opt/dnsmasq.conf --dhcp-broadcast
I also needed to add the --dhcp-broadcast flag to dnsmasq within the container to get it to actually broadcast DHCPOFFER messages on the network. For some reason, dnsmasq was trying to unicast the DHCPOFFER messages, and it was using ARP to try to get an address that had not yet been assigned.

how to let docker container work with sshuttle?

I need container be able to use sshuttle tool.
I try either way in host or containner. But none of it will work.
Here's what I need:
I run : sshuttle -r mysshaccount#my.remote.server --dns 0/0 in host. It can help host application access internet via sshuttle. But for container, it can't resolve the DNS request. It seems --dns will affect container's DNS capability. how to make container work with host's sshuttle?
also if I run sshuttle inside the container. It seems container don't have the permission with "--dns" option in sshuttle.
anyway, I need this option "--dns" in container because it's the only way to get over government fire wall (GFW) in china.
anyone help to make it work?
Try sshuttle -l 0.0.0.0 --dns -vvr XXXXXX#YY.YY.YY.YY 0/0, that works for me. I guess we need -l 0.0.0.0 so that docker containers with "remote ip" can connect to the tunnel.
Normally, setting 0.0.0.0 entails listening on externally available interfaces, and this is also the case with sshuttle .
A more secure approach would be the following - on your host:
launch your "normal" sshuttle instance, listening on localhost,
launch another sshuttle instance, listening on your docker host's virtual network interface.
For example:
sshuttle --dns -r <your-ssh-server> 0/0
sshuttle -l 172.17.0.1 --dns -r <your-ssh-server> 0/0
Note that this will interfere with host <-> container communication (such as port binding), but it will allow for secure outside connections for your containers (you can further help yourself with excluding Docker's subnet, e.g. with -x 172.17.0.0/24).
you can see your network bridge subnets and exclude it in sshuttle
e.g,
sudo sshuttle -l 0.0.0.0:0 -r user#host -x host -x 127.0.0.1 -x 172.21.0.0/24 -x 172.22.0.0/24 -x 172.23.0.0/24 0/0 --dns

Resources