Skip to content

feat: added Docker image configuration for testing with Unbound#2

Merged
dominis merged 1 commit intoberbyte:mainfrom
sbarbett:main
Aug 8, 2025
Merged

feat: added Docker image configuration for testing with Unbound#2
dominis merged 1 commit intoberbyte:mainfrom
sbarbett:main

Conversation

@sbarbett
Copy link
Contributor

@sbarbett sbarbett commented Aug 6, 2025

Add Docker Compose setup for Sinkzone with Unbound

Summary

This adds a working Docker stack for Sinkzone, using Unbound as the upstream resolver. It's meant as an alternative to installing everything natively, for testing or just keeping things self-contained.

What’s Included

Docker Setup

  • Dockerfile: Built using Alpine
  • docker-compose.yml: Brings up Sinkzone and Unbound in a shared network

Configuration Highlights

  • Sinkzone DNS listens on port 5353 (non-privileged)
    • Easily remapped to 53 in the Compose manifest, if desired
  • API exposed on 8080
  • Unbound listens on 5335
  • Custom bridge network with static IPs to avoid weird Docker name resolution issues

Docs

  • New README-Docker.md with setup instructions and usage examples
  • Updated README.md with a Docker section

Quick Start

git clone https://github.com/sbarbett/sinkzone.git
cd sinkzone
docker compose up -d

dig @127.0.0.1 -p 5353 google.com

Running Sinkzone Commands

docker compose exec -it sinkzone ./sinkzone tui --api-url http://localhost:8080
docker compose exec -it sinkzone ./sinkzone allowlist add google.com
docker compose exec -it sinkzone ./sinkzone focus start

Env Vars

  • SINKZONE_UPSTREAM_NAMESERVERS: Defaults to unbound
  • DOCKER_NETWORK_SUBNET: Customize bridge subnet if needed
  • SINKZONE_IP, UNBOUND_IP: Optional static IPs for easier linking

Tested

[x] DNS forwarding works
[x] Sinkzone API healthy
[x] Custom focus/allowlist behavior intact
[x] Docker exec commands function as expected
[x] Containers talk to each other reliably

Changed Files

  • Dockerfile: Builds Sinkzone binary
  • docker-compose.yml: Stack setup
  • internal/config/config.go: Env var support for upstream DNS
  • README-Docker.md: New
  • README.md: Added Docker section

Breaking Changes

None—this doesn’t interfere with existing install methods.

@dominis
Copy link
Member

dominis commented Aug 7, 2025

Hello @sbarbett, congratulations — you’re the first contributor! 🎉
Could you please share the prompt you used to generate the PR?

@sbarbett
Copy link
Contributor Author

sbarbett commented Aug 7, 2025

There wasn't a singular prompt, per se. I use an AI-assisted IDE (Cursor). The Unbound container config is something I copied directly from my Pihole config, which you can find a sample of here:

https://github.com/sbarbett/proxmox-ansible/blob/main/roles/docker_compose/files/compose_files/pihole-unbound.yml

I simply took out the volume mounts. Creating a Dockerfile that compiles and runs the Go binary is straightforward, and I borrowed from this:

https://github.com/sbarbett/go-mud/blob/main/Dockerfile

So, to answer the question more directly, the prompt involved copying and pasting samples above directly into Cursor chat and instructing it to create something similar - a Dockerfile that compiles the Go code and a Compose manifest that networks the container together with Unbound, then manually editing it to actually work.

I performed some manual testing to make sure the TUI and CLI worked appropriately through docker exec, and to assert that Unbound was performing the upstream recursion.

For the text of the PR itself, I requested Cursor provide an itemized summary of the changes. I pasted that into ChatGPT and asked it to write a PR summary, then I deleted all the things I felt were irrelevant. Since there wasn't a specific PR template, I just went with my gut.

A couple things that might be worth adding here:

  • Using volume mounts so that configuration settings persist through container teardowns. My intention was ad hoc testing and I wasn't concerned with retaining settings.
  • Building the container image and submitting it to Docker Hub so consumers of the project can spin it up without cloning the whole repo.

Hope this helps.

@dominis dominis merged commit 5f0258d into berbyte:main Aug 8, 2025
2 of 3 checks passed
@dominis
Copy link
Member

dominis commented Aug 8, 2025

Thank you for your contribution! 👍
Are you using Sinkzone on your machine? Any feedback/ideas?

@sbarbett
Copy link
Contributor Author

sbarbett commented Aug 12, 2025

@dominis sorry for the delay. Regarding your questions:

Are you using Sinkzone on your machine?

Not personally, no. My interest was purely academic. I work in the DNS industry as a researcher and this crossed my desk last week.

Any feedback/ideas?

Here are some thoughts:

For general use, a pure-whitelist DNS forwarder isn’t very practical—it effectively disables most of the internet. That said, I can imagine a couple of scenarios:

  1. Home/family network control. Install the forwarder on an intermediate device (e.g., a Raspberry Pi or Proxmox LXC—Pi-hole style) and manage clients via an admin UI. Example:

    • Children’s iPads are configured to use Sinkzone.
    • Admin enables Focus Mode so those devices can temporarily only access the school website (maybe whitelist *.edu) while they do homework.
    • Feature idea: Support a “relay” deployment where Focus Mode can be enabled per client IP.
      e.g., iPad number 1 → 192.168.1.201, iPad number 2 → 192.168.1.202; toggle Focus Mode for just one device (192.168.1.20x).
  2. CTI sandboxing. Use it to detonate malicious URLs and analyze all domains the site attempts to resolve. (There are mature tools in this space already, so the demand may vary.)

Additional fringe cases:

  • IoT isolation: Keep low-trust devices from “phoning home” except to allowed services. Many vendors change endpoints or use questionable third-party analytics; default-deny with explicit allows can help.

    • Smart TV → only resolve Netflix, Hulu, Disney+, and firmware update domains.
    • Security camera → only vendor cloud + NTP.
  • Kiosks/POS: Locked-down workstations.

  • High-assurance builds: Air-gap-like DNS control in CI/CD or code-signing environments.

  • Incident response: Temporary containment during an event.


Other than that, it would be great if the project could perform full recursion and DNSSEC validation natively, rather than relying on a third-party upstream resolver or Unbound. It’s doable in Go, though not trivial. For reference: https://github.com/semihalev/sdns

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants