FRANKMAYER.ME Blog

Sorry for the long title, just wanted to be as precise as possible :)

A quick bit of history...

I recently  started experimenting with Docker and revamped some of my development environment with it.
So, I am in the middle of developing a kind of middleware that glues onto a low-level-driver in order to provide event-driven, non-blocking I/O with PHP (via Guzzle ReactPHP) to communicate with the very versatile open-source NoSQL Database Server ArangoDB. BTW, you should try ArangoDB out! It's really great! My favorite Swiss Army knife in the NoSQL DB World!

Here is the problem that I faced:

When you tell ReactPHP to connect to some host, it does not honour host files (in any system, be it Linux-ish, Windows or any other). It only makes DNS lookups in order to resolve the host you told it to connect to. If  you have not been bitten by this, consider yourself lucky!

There are some open GitHub issues in various parts of the ReactPHP library, that ask for some way of respecting the hosts file, but there has been no actual solution, yet.

Essentially, my problem was, that I could not connect from the docker PHP container to the linked ArangoDB Container, because there was no way to tell ReactPHP to read /etc/hosts... in order to find the IP address of the linked container.
Since each new docker container (at least in my environment) would be assigned a different ip address than what it had during its last run, a hardcoded ip address for testing would not be viable. Also, it would make testing it, with 
Travis-CI for example, very difficult.

That was a tough one to crack, but a quick search for a DNS server, that would provide the contents of /etc/hosts to a DNS lookup query, brought me to Dnsmasq. It does exactly what I wanted. It loads /etc/hosts on startup and provides it to DNS lookups.

So I changed the dockerfile for my PHP image to have it install Dnsmasq and start it along PHP-FPM. In order to make this work in Ubuntu (on which the PHP image is based on), I needed to also add user=root to the /etc/dnsmasq.conf file. Not sure if this is needed in other flavours.

Now, the only thing that was left to do, was to tell the ReactPHP DNS Resolver, which DNS Server to use... in my case simply 127.0.0.1:

$dnsResolverFactory = new \React\Dns\Resolver\Factory();
$dnsResolver        = $dnsResolverFactory->createCached('127.0.0.1', $loop);

 

Note, since we are essentially using /etc/hosts it makes a lot of sense to create a cached DNS Resolver ($dnsResolverFactory->createCached) to avoid unnecessary lookups past the first one, inside the running loop.

Hope this helps some of you out there. See you next time. :)

 

Published: Saturday, 18 April 2015 20:22