Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/tianon/rawdns

a direct, raw DNS interface to the Docker API
https://github.com/tianon/rawdns

Last synced: about 2 months ago
JSON representation

a direct, raw DNS interface to the Docker API

Awesome Lists containing this project

README

        

# ![rawdns](https://raw.githubusercontent.com/tianon/rawdns/master/logo-black.png)

- [Docker Hub](https://index.docker.io/u/tianon/rawdns/)
- [GitHub](https://github.com/tianon/rawdns)
- [![Smoke Test](https://github.com/tianon/rawdns/workflows/Smoke%20Test/badge.svg?branch=master)](https://github.com/tianon/rawdns/actions?query=workflow%3A%22Smoke+Test%22+branch%3Amaster)

Save as `/etc/rawdns/config.json`:

```json
{
"docker.": {
"type": "containers",
"socket": "unix:///var/run/docker.sock"
},
"local.": {
"type": "forwarding",
"nameservers": [ "192.168.1.1" ]
},
".": {
"type": "forwarding",
"nameservers": [ "8.8.8.8", "8.8.4.4" ]
}
}
```

Then:

```console
$ docker run --rm -p 53:53/udp -v /var/run/docker.sock:/var/run/docker.sock -v /etc/rawdns/config.json:/etc/rawdns/config.json:ro tianon/rawdns rawdns /etc/rawdns/config.json
2014/09/23 14:46:10 listening on domain: docker.
2014/09/23 14:46:10 listening on domain: local.
2014/09/23 14:46:10 listening on domain: .
```

The most-specific domain gets the request (ie, if you have both `docker.` and `containers.docker.` and you do a lookup for `something.containers.docker`, you'll get back the IP of the container named `something`).

The default configuration only includes `docker.` going to `/var/run/docker.sock` and `.` going to `8.8.8.8`+`8.8.4.4`.

## wat

Since DNS is a protocol (which is a type of API), and Docker has an API, it makes a lot more sense to have DNS be a raw interface to Docker than it does to treat DNS like a database and try to synchronize the two data sources.

## why

I've eventually grown to dislike every "Docker DNS" project for one reason or another, and usually the misgivings boil down to treating DNS like a database, which reminds me of my favorite thing to say about databases: if you have the same data in two places, they are guaranteed to eventually get out of sync in some way (no matter how clever you or your code are).

## how

This is implemented by borrowing the core of SkyDNS, [`github.com/miekg/dns`](https://github.com/miekg/dns). It's a really great, but very raw, DNS library for Go that makes it really easy to write a DNS server or client. One of the explicit design goals of the project is "If there is stuff you should know as a DNS programmer there isn't a convenience function for it."

## SHOW ME

```console
$ dig @localhost dns.docker

; <<>> DiG 9.9.5 <<>> @localhost dns.docker
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18138
;; flags: qr rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;dns.docker. IN A

;; ANSWER SECTION:
dns.docker. 0 IN A 172.18.0.30

;; Query time: 1 msec
;; SERVER: ::1#53(::1)
;; WHEN: Wed Sep 24 23:06:33 MDT 2014
;; MSG SIZE rcvd: 54

$ ping dns.docker
PING dns.docker (172.18.0.30) 56(84) bytes of data.
64 bytes from 172.18.0.30: icmp_seq=1 ttl=64 time=0.025 ms
64 bytes from 172.18.0.30: icmp_seq=2 ttl=64 time=0.049 ms
64 bytes from 172.18.0.30: icmp_seq=3 ttl=64 time=0.041 ms
^C
--- dns.docker ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 0.025/0.038/0.049/0.011 ms
```

## swarm support

`rawdns` can be used with swarm by creating a configuration that provides the socket details using the `tcp://` scheme. You will also need to enable `swarmnode` by setting it to true. The `swarmnode` option enables `rawdns` to look at the `Node` section of the inspect API response for the external/host IP address.

Example swarm configuration:

```json
{
"swarm.": {
"type": "containers",
"socket": "tcp://192.168.99.100:3376",
"swarmnode": true,
"tlsverify": true,
"tlscacert": "/var/lib/boot2docker/ca.pem",
"tlscert": "/var/lib/boot2docker/server.pem",
"tlskey": "/var/lib/boot2docker/server-key.pem"
},
"docker.": {
"type": "containers",
"socket": "unix:///var/run/docker.sock"
},
"local.": {
"type": "forwarding",
"nameservers": [ "172.17.42.1" ]
},
".": {
"type": "forwarding",
"nameservers": [ "8.8.8.8", "8.8.4.4" ]
}
}
```

Example usage:

```shell
$ docker run --name dns --rm -it \
-p 53:53/udp \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /var/lib/boot2docker:/var/lib/boot2docker \
-v /etc/rawdns/config.json:/etc/rawdns/config.json:ro \
tianon/rawdns rawdns /etc/rawdns/config.json

2015/09/14 21:50:49 rawdns v1.2 (go1.4.2 on linux/amd64; gc)
2015/09/14 21:50:49 listening on domain: .
2015/09/14 21:50:49 listening on domain: swarm.
2015/09/14 21:50:49 listening on domain: docker.
2015/09/14 21:50:49 listening on domain: local.

...

$ docker run -it debian:jessie bash

root@69967c3e5179:/# ping redis.swarm
PING redis.swarm (192.168.99.101): 56 data bytes
64 bytes from 192.168.99.101: icmp_seq=0 ttl=63 time=0.001 ms

root@69967c3e5179:/# ping dns.swarm
PING dns.swarm (192.168.99.100): 56 data bytes
64 bytes from 192.168.99.100: icmp_seq=0 ttl=64 time=0.030 ms

root@69967c3e5179:/# ping dns.docker
PING dns.docker (172.17.0.85): 56 data bytes
64 bytes from 172.17.0.85: icmp_seq=0 ttl=64 time=0.076 ms
```