docker could not use system proxy - docker

I am trying to use docker behind corporate firewall.
I would like to force docker to use system Proxy, but this option is not available. How can I make docker to system Proxy.

I've written a blog post about using the weird DummyDesperatePoitras virtual switch as an anchor for CNTLM, and that resolves some of the problems I mentioned here (having to change the proxy address for Docker every time your IP changes, among other things):
http://mandie.net/2017/12/10/docker-for-windows-behind-a-corporate-web-proxy-tips-and-tricks/
As of November 2017, this feature was still not implemented in Docker for Windows: https://github.com/docker/for-win/issues/589
The best solution I've found is CNTLM, but I'm not delighted with it, because:
1) CNTLM has not been updated in 5 years
2) You have to set the proxy IP in the Docker GUI, making it rather automation-resistant. The Docker for Windows GUI reads the proxy settings from the MobyLinux VM, not from the Windows registry, a config file or Windows environment variables. Setting HTTP_PROXY and HTTPS_PROXY in Windows has absolutely no effect on Docker. I've not found any way of setting the proxy value programmatically; the MobyLinux VM doesn't accept ssh connections. If anyone ever finds a way to do this from a command line or script, I'd love to know.
3) Setting the proxy IP to 127.0.0.1 won't work, because that will get the virtual machine that Docker is really running on to try its own interface, not the one on the host PC running CNTLM. I have also tried the DockerNAT interface IP, 10.0.75.1, with no success.
4) This means that the proxy IP needs to be the current IP address of your active external network interface. If you move around buildings a lot, you need to check this every time you want to use Docker.
Set CNTLM to listen on 0.0.0.0 3128, not just 3128 or 127.0.0.1 3128. This will save you the trouble of updating this IP address every time your PC gets a new IP address. Just having the port number will keep traffic from the VM running Docker from being "heard".
Calculate the NTLMv2 hash and store that in the config file instead of your username and password. This will be different for every PC and user account, so don't share your unredacted config file with another PC unless you want to get locked out. You will need to update this stored hash when you next change your Windows password.
Restart the cntlm Windows service after any changes to its config file.
Run ipconfig in cmd.exe or PowerShell to find your current IP address. If you're using corporate VPN, use the IP address of the WiFi or Ethernet adapter, not the VPN.
Type http://ipfromipconfig:3128/ into the "Web Server (HTTP)" box. Make sure the checkbox "Use same for both" is checked.

Using CNTLM automates working behind proxy. It allows us to specify everywhere IP address without any credentials, so security is better and whenever we change password we only have to do it in one place, we can also specify URLs that should not be proxied.
Since 18.03 Docker version, there is available special DNS name: host.docker.internal. That allows to connect to the host machine from Docker containers. Now, when we setup our CNTLM proxy in cntlm.ini to make it listen on 0.0.0.0:3128:
Listen 0.0.0.0:3128
Then we can specify in Docker settings proxy using host.docker.internal:3128 address, which will be translated to appropriate and current local address of our machine.

you can set up two environment variables http_proxy and https_proxy
http_proxy with value http://username:password#proxyIp:proxyport
for example, in my case it was
http://venkat_krish:password#something.ad.somthing.com:80
you can use the same for https proxy
Note:
If you have any special characters apart from _ & . in the username or password
you have to encode the url. follow this link for url encoding https://grox.net/utils/encoding.html
For example if your password is abc#123, then it will be written as abc%40123

Related

How do I connect to other computers via Host Name on Ubuntu?

I have a docker container that is running on Windows currently and it is accessing database resources via the host name (e.g Desktop1, Desktop2, etc...). The docker container is using a bridge network that was created new for the purpose of the system.
What I notice on Windows is that I can ping or connect to those resources simply via the host name and I do not need to remember the IP address of the computer.
I also notice that this can also be done even if I don't have a DNS server running locally (I think?).
However, when I run the container on an Ubuntu host, I keep getting connection errors and timeouts.
I have tried to edit the /etc/hosts and /etc/hostname to include the proper host name of the PC and the fixed wired IP I am using.
I have also tried a test database on the same Ubuntu system but I cannot connect to it via its host name. At best, I am able to connect via something like Desktop1.local but it only solves 1 issue. The other responses I receive from the other systems on the network return only the hostname (e.g. http://Desktop2/api/..., ws://Desktop3/api/..., etc...).
I was wondering if there is a configuration I am missing to have the same functionality as Windows? Do I need to change my code to handle this kind of situations or do I need to do something else like on the OS level?
My command for creating the docker container is along these lines:
docker create -p 172.16.0.1:50000:80/tcp --env MongoDatabaseSettings__ConnectionString="mongodb://desktop1:27017/?uuidRepresentation=standard" --env ConnectionStrings__MySQLConnection="server=desktop2;database=DB;user=user;password=password" --name container1 registry.gitlab.com/group/image:latest
Contents of my /etc/hosts
127.0.0.1 localhost
172.16.0.1 desktop1
If it's me, maybe will try to build the reverse proxy server.
Step. 1
choose your server. (recommend Nginx)
Step. 2
Forward traffic
For example, if your ip of docker service is 192.168.1.2:8080, then you can make 127.0.0.1:80 to forward to it. (or any port you want)
Then you just need to access 127.0.0.1:80, the server will forward the traffic to service of docker.
I dont know is that you actually want to do.
oh, btw, if you still want to access via host name, just edit host file with root user. (make 127.0.0.1:80 a custom domain.
I dont know the reason of that why you can not setting the host file, but set 127.0.0.1 in host file is always working for me.

Updated windows docker and now it doesn't work outside localhost

I have been running a media cluster for sometime without any issues. I have everything networked into two different docker networks... the first network just bridges the docker instance to the local machine, the second network is a docker VPN container that I use for the other media services (an earlier version of what I am working on can be found here: https://github.com/Xander-Rudolph/MediaDocker)
The strangest thing happened today though. I ran the docker update for windows and now docker spools up without any errors or issues, however none of the services work outside of the machine running docker. Usually I have a poke through for a couple of the services in my router (namely wordpress/joomla which is on the bridge) and they work outside of my local network, but none of them are working anymore. I was able to confirm its not the DNS A record because I'm able to use the RDP ports I have mapped for my router, and when I test on another machine in the same network, it can't access the services via the internal IP (but it can RDP).
Anyone have any idea what could have changed to break this? I've already updated all my docker images and even rebuilt my VPN container (before I realized its a networking issue). What are some steps I can do to try to troubleshoot what is going wrong in docker to prevent access outside of localhost?
Update
I've been able to rule out the docker update as the root cause... I upgraded docker on my laptop (which was previously running the same version as my desktop) and its not having the same issue... this configuration must be localized to this desktop... No idea what the issue is... Will try a linux VM on the desktop instead of docker for windows...
Update 2
After a lot of screwing around in both a VM and in WSL, I'm still only able to access the docker services from localhost but not a different machine on my network or via the IP on the host machine (perhaps something similar to this: Can't access localhost via IP address). RDP does work so the computer is accessible but the services are not.
I'm not sure if this is a result of a docker networking config or a windows network config (I'm using WSL with docker installed on ubuntu 20.08) but I'm not seeing anything stick out. I'm going to remove the tag for docker windows but this is definitely an issue with networking and I suspect it has something to do with the fact that the containers are running behind a VPN... although I don't know why I would be able to access them on localhost but not the IP on another VM...
When I run
netstat -a -o
on WSL I can see the established ports on localhost... EX:
tcp 0 0 localhost:7878 localhost:37520 ESTABLISHED
but when I look on the host machine (for wsl) I don't see the connection. I tried to use netsh to create a firewall rule to see if that would help:
netsh advfirewall firewall add rule name="TCP Port 7878" dir=in localport=7878 protocol=TCP action=allow
but it didn't have any effect.
Any suggestions for ways to trace the network to see where/how its failing/getting blocked would be extremely helpful.
Your question: "...What are some steps I can do to try to troubleshoot what is going wrong in docker to prevent access outside of localhost?..."
Troubleshooting help for you, first do you have multiple networking adapters (Ethernet, Wi-Fi, etc.) present on the host. First ensure, the priority of these adapters needs to be configured in correct order so the Windows networking stack can correctly choose gateway routes.
Now, to fix this set your primary internet-connected networking adapter to have the lowest InterfaceMetric value, use can use these Powershell commands from an elevated console:
Get-NetIPInterface -AddressFamily IPv4 | Sort-Object -Property InterfaceMetric -Descending
Please ensure that the host's primary internet-connected network adapter has the lowest InterfaceMetric value.
// Use this command to make the change for e.g. lets say your
// primary adapter InterfaceAlias is 'Wi-Fi'
Set-NetIPInterface -InterfaceAlias 'Wi-Fi' -InterfaceMetric 3
Now step two, if your host's primary network adapter is bridged because you have an External virtual switch setup in Hyper-V, then you will set the external virtual switch to have the lowest InterfaceMetric value.
Lastly, confirm/verify your routing tables, when you run this, the last line should show the primary adapter's gateway address along with it's ifMetric value):
Get-NetRoute -AddressFamily IPv4
If you’re using Docker Toolbox then any port you publish with docker run -p will be published on the Toolbox VM’s private IP address.
docker-machine ip will tell you.
It is frequently
192.168.99.100
Taken from: https://forums.docker.com/t/cant-connect-to-container-on-localhost-with-port-mapping/52716/25
After several attempts using the references below, I was still not getting anywhere. The recommendation by #derple didn't get me anywhere (since I was in wsl) but the article he linked someone had said they switched to linux and uninstalled and reinstalled docker desktop... and for some stupid reason that works.
These are my exact steps I took to fix it:
Uninstall docker desktop
Install WSL and docker inside an ubuntu18.04 instance in wsl
Test docker in wsl with localhost (worked only on localhost still)
Uninstall WSL using windows add/remove features
reinstall docker desktop
Oddly the get-netipinterface and get-netroute look exactly the same as they did before I did the uninstall and reinstall but things seem to be working now... I have no idea why the above worked...

What are the possible formats of the DOCKER_HOST URLs?

Remote docker servers can be reached by the docker cli by settings the DOCKER_HOST environment variable.
Mostly, tcp://<hostname-or-ip>:<port> or sometimes ssh://<hostname-or-ip>:<port> is used.
Unfortunately, the docker documentation talks about everything, except the possible URL formats of this variable. What are they, how do they work?
The parsing of the DOCKER_HOST variable happens in the parseDockerDaemonHost function in the opts/hosts.go source fragment of the docker-cli.
The possible values are the following:
tcp://1.2.3.4:2375 - it connects to the docker server at the TCP port 2375 of the remote system. Beside the IP, also the hostname can be used. Leaving out the port field, it defaults to 2375 in normal mode, or to 2376 if we use TLS encryption (docker client should be called with the --tls flag for that).
unix:///path/to/socket - it connects to a docker server listening on the local unix socket /path/to/socket. Unix sockets exist only on Linux (& co) systems. The path does not need to be an absolute one. The default value is /var/run/docker.sock (is connected if DOCKER_HOST=unix://).
npipe:///./pipe/docker_engine - named pipes are similar to the Unix sockets, but in the Windows world. It probably connects a local docker server running on a Windows. Note, docker on Windows runs on a Linux VM, over the HyperV virtualization engine of the Microsoft. And it is reached probably over the virtual network provided by the HyperV. Native Windows docker is not very widely used.
fd://1.2.3.4:5678 - Contrary its name, it has probably nothing to do to file descriptors. It behaves similarly to the tcp://, except that the port number does not default to 2375. The exact working would probably need further digging in the docker-cli source.
ssh://1.2.3.4:22 - it calls the ssh command to remotely login the remote server. The docker command should be available there in the default PATH. There it executes a docker command, passing exactly the same arguments to it, with them we called it locally. Probably it can connect the docker server only on its default address (/var/run/docker.sock) on the remote side.
Protocol-less URLs (//host:port) default to tcp://. Any other URL formats are rejected with the Invalid bind address format error message.
The communication protocol is http(s), although I had some issues with it in proxied configurations.

Make docker machine available under host name in Windows

I'm trying to make a docker machine available to my Windows by a host name. After creating it like
docker-machine create -d virtualbox mymachine
and setting up a docker container that exposes the port 80, how can I give that docker machine a host name such that I can enter "http://mymachine/" into my browser to load the website? When I change "mymachine" to the actual IP address then it works.
There is an answer to this question but I would like to achieve it without an entry in the hosts file. Is that possible?
You might want to refer to docker documentaion:
https://docs.docker.com/engine/userguide/networking/#exposing-and-publishing-ports
You expose ports using the EXPOSE keyword in the Dockerfile or the
--expose flag to docker run. Exposing ports is a way of documenting which ports are used, but does not actually map or open any ports.
Exposing ports is optional.
You publish ports using the --publish or --publish-all flag to docker
run. This tells Docker which ports to open on the container’s network
interface. When a port is published, it is mapped to an available
high-order port (higher than 30000) on the host machine, unless you
specify the port to map to on the host machine at runtime. You cannot
specify the port to map to on the host machine when you build the
image (in the Dockerfile), because there is no way to guarantee that
the port will be available on the host machine where you run the
image.
I also suggest reviewing the -P flag as it differs from the -p one.
Also i suggest you try "Kitematic" for Windows or Mac, https://kitematic.com/ . It's much simpler (but dont forget to commit after any changes!)
Now concerning the network in your company, it has nothing to do with docker, as long as you're using docker locally on your computer it wont matter what configuration your company set. Even you dont have to change any VM network config in order to expose things to your local host, all comes by default if you're using Vbox ( adapter 1 ==> NAT & adapter 2 ==> host only )
hope this is what you're looking for
If the goal is to keep it as simple as possible for multiple developers, localhost will be your best bet. As long as the ports you're exposing and publishing are available on host, you can just use http://localhost in the browser. If it's a port other than 80/443, just append it like http://localhost:8080.
If you really don't want to go the /etc/hosts or localhost route, you could also purchase a domain and have it route to 127.0.0.1. This article lays out the details a little bit more.
Example:
dave-mbp:~ dave$ traceroute yoogle.com
traceroute to yoogle.com (127.0.0.1), 64 hops max, 52 byte packets
1 localhost (127.0.0.1) 0.742 ms 0.056 ms 0.046 ms
Alternatively, if you don't want to purchase your own domain and all developers are on the same network and you are able to control DHCP/DNS, you can setup your own DNS server to include a private route back to 127.0.0.1. Similar concept to the Public DNS option, but a little more brittle since you might allow your devs to work remote, outside of a controlled network.
Connecting by hostname requires that you go through hostname to IP resolution. That's handled by the hosts file and falls back to DNS. This all happens before you ever touch the docker container, and docker machine itself does not have any external hooks to go out and configure your hosts file or DNS servers.
With newer versions of Docker on windows, you run containers with HyperV and networking automatically maps ports to localhost so you can connect to http://localhost. This won't work with docker-machine since it's spinning up virtualbox VM's without the localhost mapping.
If you don't want to configure your hosts file, DNS, and can't use a newer version of docker, you're left with connecting by IP. What you can do is use a free wildcard DNS service like http://xip.io/ that maps any name you want, along with your IP address, back to that same IP address. This lets you use things like a hostname based reverse proxy to connect to multiple containers inside of docker behind the same port.
One last option is to run your docker host VM with a static IP. Docker-machine doesn't support this directly yet, so you can either rely on luck to keep the same IP from a given range, or use another tool like Vagrant to spin up the docker host VM with a static IP on the laptop. Once you have a static IP, you can modify the host file once, create a DNS entry for every dev, or use the same xip.io URL, to access the containers each time.
If you're on a machine with Multicasting DNS (that's Bonjour on a Mac), then the approach that's worked for me is to fire up an Avahi container in the Docker Machine vbox. This lets me refer to VM services at <docker-machine-vm-name>.local. No editing /etc/hosts, no crazy networking settings.
I use different Virtualbox VMs for different projects for my work, which keeps a nice separation of concerns (prevents port collisions, lets me blow away all the containers and images without affecting my other projects, etc.)
Using docker-compose, I just put an Avahi instance at the top of each project:
version: '2'
services:
avahi:
image: 'enernoclabs/avahi:latest'
network_mode: 'host'
Then if I run a webserver in the VM with a docker container forwarding to port 80, it's just http://machine-name.local in the browser.
You can add a domain name entry in your hosts file :
X.X.X.X mymachine # Replace X.X.X.X by the IP of your docker machine
You could also set up a DNS server on your local network if your app is meant to be reachable from your coworkers at your workplace and if your windows machine is meant to remain up as a server.
that would require to make your VM accessible from local network though, but port forwarding could then be a simple solution if your app is the only webservice running on your windows host. (Note that you could as well set up a linux server to avoid using docker-machine on windows, but you would still have to set up a static IP for this server to ensure that your domain name resolution works).
You could also buy your own domain name (or get a free one) and assign it your docker-machine's IP if you don't have rights to write in your hosts file.
But these solution may not work anymore after some time if app host doesn't have a static IP and if your docker-machine IP changes). Not setting up a static IP doesn't imply it will automatically change though, there should be some persistence if you don't erase the machine to create a new one, but that wouldn't be guaranteed either.
Also note that if you set up a DNS server, you'd have to host it on a device with a static IP as well. Your coworkers would then have to configure their machine to use this one.
I suggest nginx-proxy. This is what I use all the time. It comes in especially handy when you are running different containers that are all supposed to answer to the same port (e.g. multiple web-services).
nginx-proxy runs seperately from your service and listens to docker-events to update it's own configuration. After you spun up your service and query the port nginx-proxy is listening to, you will be redirected to your service. Therefore you either need to start nginx-proxy with the DEFAULT_HOST flag or send the desired host as header param with the request.
As I am running this only with plain docker, I don't know if it works with docker-machine, though.
If you go for this option, you can decide for a certain domain (e.g. .docker) to be completely resolved to localhost. This can be either done company-wide by DNS, locally with hosts file or an intermediate resolver (the specific solution depends on your OS, of course). If you then try to reach http://service1.docker nginx-proxy will route to the container that has then ENV VIRTUAL_HOST=service1.docker. This is really convenient, because it only needs one-time setup and is from then on dynamic.

Docker - set DNS from inside container - for VPN?

I'm trying to set up a docker container to access my VPN (IVPN). I want to use the DNS of the VPN, but the DNS is selected based on the IP address I'm assigned - which occurs within the container...
https://www.ivpn.net/knowledgebase/163/What-is-the-IP-address-of-your-DNS-servers.html
To work out the address of the closest DNS server simply look at
the IP assigned to you when you connect. The DNS servers are in
the format 10.x.x.1. For example, if you receive the address
10.16.4.66 then the DNS is on 10.16.4.1.
Is there some way of updating the DNS from within the container?
Or can I (massively over-engineer a solution by...) start the container, get the IP address assigned by the VPN, then (somehow) do a DNS update from the host?
Do I just give up and hard code some DNS servers that aren't "closest"
[Edit thanks to #MrE] I want to run openvpn IN the container (so I'll use someone else's image) - and have other containers use this one as their only connection to the 'net. Basically, I'm trying to build fully isolated containers and then have their connections configurable via either our corporate (or other commercial) VPN.

Resources