Skip to content

Commit

Permalink
improvements
Browse files Browse the repository at this point in the history
- don't panic for unparsable dns questions
- compress releases (closes #1)
- rename to dockness
  • Loading branch information
bamarni committed Mar 22, 2016
1 parent 6dd287d commit efabfc7
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 31 deletions.
16 changes: 10 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
dev:
tmuxinator start go
clean:
rm -rf build

release:
mkdir -p build
GOOS=darwin GOARCH=amd64 go build -o build/docker-machine-dns-darwin-x64 ./docker-machine-dns.go
GOOS=linux GOARCH=amd64 go build -o build/docker-machine-dns-linux-x64 ./docker-machine-dns.go
build: clean
mkdir -p build/darwin build/linux
GOOS=darwin GOARCH=amd64 go build -o build/darwin/dockness ./dockness.go
GOOS=linux GOARCH=amd64 go build -o build/linux/dockness ./dockness.go

release: build
mkdir -p build/releases
tar -cvzf build/releases/dockness-darwin-x64.tar.gz -C build/darwin dockness
tar -cvzf build/releases/dockness-linux-x64.tar.gz -C build/linux dockness
87 changes: 70 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# docker-machine-dns
# dockness

DNS for Docker machines, allows to access them with the following domain format : `{machine}.docker`.

Expand All @@ -12,31 +12,34 @@ Behind the scene it will run `docker-machine ip {machine}` in order to resolve t

### Prebuilt binaries

Prebuilt binaries are available in the [releases](https://github.com/bamarni/docker-machine-dns/releases).
Prebuilt binaries are available in the [releases](https://github.com/bamarni/dockness/releases).

### From source (requires Go)

go get github.com/bamarni/docker-machine-dns
go get github.com/bamarni/dockness

## Usage

dockness [options...]

Options:
-tld Top-level domain to use (defaults to "docker")
-port Port to listen on (defaults to "53")
-server-only Server only, doesn't try to create a resolver configuration file
-user Execute the "docker-machine ip" command as a different user (defaults to "SUDO_USER")

### Mac OSX

To develop on Mac you probably have a local VM, using VirtualBox for example.
However this machine gets assigned a dynamic IP address.

The program can be up and running in one command :

> sudo docker-machine-dns
> sudo dockness
2016/02/18 10:39:52 Creating configuration file at /etc/resolver/docker...
2016/02/18 10:39:52 Listening on :53...

In another terminal, to make sure it works properly (let's say for a machine called `dev`) :

> dig @localhost dev.docker +short
192.168.99.100

## Linux
### Linux

Even though Linux users might not need a development VM, it can be useful for remote machines
(eg. `ssh staging2.docker`, ...).
Expand All @@ -49,19 +52,69 @@ which provides a lightweight DNS server.

If you have it installed, you can run :

> docker-machine-dns -port 10053
> dockness -port 10053
2016/02/18 10:40:43 Listening on :10053...

Then let Dnsmasq know about the resolver by running those commands :

> echo "server=/docker/127.0.0.1#10053" | sudo tee -a /etc/dnsmasq.conf
> sudo /etc/init.d/dnsmasq restart

### Usage reference
## Configure dockness as a service

docker-machine-dns [options...]
As it's not very convenient to run the program manually in a terminal, you can instead set it as a service.
Doing so, it will be running in the background automatically when booting your computer.

### Mac OSX

Run this command : `echo "nameserver 127.0.0.1\nport 10053" | sudo tee /etc/resolver/docker`

It tells your Mac that the resolver for `.docker` TLD listens locally on port 10053.

You can now create the appropriate service configuration file at `~/Library/LaunchAgents/local.dockness.plist` :

``` xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Disabled</key>
<false/>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/usr/local/bin</string>
</dict>
<key>Label</key>
<string>local.dockness</string>
<key>ProgramArguments</key>
<array>
<string>/path/to/dockness</string>
<string>-server-only</string>
<string>-port</string>
<string>10053</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
```

You'll have to adapt 2 parameters :
- `/path/to/dockness`
- `/usr/local/bin`, which is the directory containing your `docker-machine` executable

Finally, the service can be enabled :

launchctl load ~/Library/LaunchAgents/local.dockness.plist

### Linux

Here again, it will depend on your Linux distribution.
We'll take as example [Systemd](https://freedesktop.org/wiki/Software/systemd/),
which is nowadays the default init system in Ubuntu/Debian.

Create the following file at `/etc/systemd/system/dockness.service`:

TODO

Options:
-port Port to listen on (defaults to "53")
-server-only Server only, doesn't try to create a resolver configuration file
-user Execute the "docker-machine ip" command as a different user (defaults to "SUDO_USER")
21 changes: 13 additions & 8 deletions docker-machine-dns.go → dockness.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,26 @@ func lookup(w dns.ResponseWriter, r *dns.Msg) {
}

domLevels := strings.Split(q.Name, ".")
domLevelsLen := len(domLevels)
if domLevelsLen < 3 {
log.Printf("Couldn't parse the DNS question '%s'", q.Name)
continue
}
machine := domLevels[len(domLevels)-3]

var stdoutBytes []byte
var output []byte
var err error

if user == "" {
stdoutBytes, err = exec.Command("docker-machine", "ip", machine).Output()
output, err = exec.Command("docker-machine", "ip", machine).CombinedOutput()
} else {
stdoutBytes, err = exec.Command("sudo", "-u", user, "docker-machine", "ip", machine).Output()
output, err = exec.Command("sudo", "-u", user, "docker-machine", "ip", machine).CombinedOutput()
}

if err != nil {
log.Printf("No IP found for machine '%s': %s", machine, err)
log.Printf("No IP found for machine '%s' (%s)", machine, output)
continue
}
ip := string(stdoutBytes[:len(stdoutBytes)-1])
ip := string(output[:len(output)-1])

rr = &dns.A{
Hdr: dns.RR_Header{
Expand All @@ -61,13 +65,14 @@ func lookup(w dns.ResponseWriter, r *dns.Msg) {
}

func main() {
tld := flag.String("tld", "docker", "Top-level domain to use")
port := flag.String("port", "53", "Port to listen on")
serverOnly := flag.Bool("server-only", false, "Server only, doesn't try to create a resolver configuration")
flag.StringVar(&user, "user", os.Getenv("SUDO_USER"), "Execute the 'docker-machine ip' command as this user")
flag.Parse()

if *serverOnly == false && runtime.GOOS == "darwin" {
confPath := "/etc/resolver/docker"
confPath := "/etc/resolver/" + *tld
log.Printf("Creating configuration file at %s...", confPath)
conf := []byte("nameserver 127.0.0.1\nport " + *port + "\n")
if err := ioutil.WriteFile(confPath, conf, 0644); err != nil {
Expand All @@ -82,7 +87,7 @@ func main() {
Net: "udp",
}

dns.HandleFunc("docker.", lookup)
dns.HandleFunc(*tld+".", lookup)

log.Printf("Listening on %s...", addr)
go log.Fatal(server.ListenAndServe())
Expand Down

0 comments on commit efabfc7

Please sign in to comment.