# 11notes/docker-unbound: a rootless, distroless DNS resolver image that trades convenience for control

> This image packages Unbound as a 12MB, read-only, rootless container with no shell. It targets operators who want a minimal DNS resolver and are willing to manage configuration and updates themselves.

**11notes/docker-unbound** — Run unbound rootless and distroless.

- Repository: https://github.com/11notes/docker-unbound
- Stars: 25 · Forks: 2
- Language: Dockerfile
- License: MIT
- Published: 2026-08-21 · Updated: 2026-08-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/11notes-docker-unbound

## What this image actually solves

Most Unbound containers run as root, include a shell, and ship a full OS layer. That is convenient but expands the attack surface. This image starts from scratch and adds only a minimal distroless layer with users, timezones, and root CA certificates. The result is a 12MB image that runs as UID 1000, has no shell, and mounts its configuration directory read-only. The target user is someone who runs a recursive resolver for a home or small office network and wants the smallest possible footprint with the fewest privileges. It is not for people who need to exec into the container and poke around.

## How the image is built and what that means

The README states the image is not based on another image but uses scratch as the starting layer. On top of that it adds two layers from the 11notes/distroless repository: one that contains users, timezones, and root CA certificates, and another that includes a dnslookup app. Because there is no shell, you cannot run arbitrary commands inside the container. Debugging has to happen from outside, either by reading logs or by mounting different configurations. The read-only root filesystem is enforced in the compose example with read_only: true and security_opt no-new-privileges. That combination is the core security story: even if an attacker compromises the Unbound process, there is no shell to escalate into and no writable filesystem to modify.

## Configuration: the default is a local-only resolver

The default config is written for use as a local resolver. It sets root-hints, enables both IPv4 and IPv6, listens on port 53 for UDP and TCP, and allows queries from private ranges like 10.0.0.0/8 and 192.168.0.0/16. It hides identity and version, hardens DNSSEC, and sets use-caps-for-id. The README is explicit: this default does not send queries to third-party resolvers like Google or Quad9. If you want that, you must add tls-upstream: yes and point tls-cert-bundle to the CA bundle. That is a deliberate design choice. The image pushes you toward a recursive resolver that talks directly to the root servers, which is more private but also more dependent on your network's ability to reach those servers.

## Getting it running: commands and compose

You pull the image with docker pull 11notes/unbound:1.25.1 or from ghcr.io and quay.io. The main tags are the version, plus -unraid and -nobody variants that change the UID/GID to 99:100 or 65534:65534. The compose example mounts a volume at /unbound/etc, sets TZ, exposes port 53 over UDP and TCP, and applies the lockdown settings. There is no latest tag. The README explains you can use short semver tags like :1 or :1.25, or the :rolling tag if you accept breaking changes. For configuration, the UNBOUND_CONFIG environment variable can overwrite the entire default config with an inline value. That is useful for automation, but it means you must provide a complete config, not a partial override.

## Limitations and failure modes

The most obvious limitation is the lack of a shell. If Unbound fails to start, you cannot exec in to inspect the environment. The README does not describe a debug process for that case. Second, the image is auto-updated via CI/CD, but you are expected to pin versions. The README warns that the :rolling tag can bring breaking changes or security issues instantly. That is a real risk if you forget to update your tag. Third, the default config allows queries only from private ranges. If you run this on a host with a public interface and forget to adjust access-control, you could expose your resolver to the internet. The README does not emphasize that risk, but it is inherent in the default config. Finally, the image is built for amd64, arm64, and armv7, not for armv6, which some older Raspberry Pi models use.

## Alternatives and how they differ

The README compares this image to klutchell/unbound. Both run as UID 1000 and are distroless, but klutchell/unbound is 14MB and supports armv6 in addition to amd64, arm64, and armv7. The size difference is small, but the architecture support matters if you run an older Pi. Another alternative is the official Unbound image from the NLnet Labs, which is not distroless and typically runs as root. That image gives you a shell and more conventional debugging, at the cost of a larger attack surface. The core difference is not features; Unbound itself is the same. It is the security posture and the operational workflow. With 11notes, you accept less flexibility in exchange for a smaller, more locked-down runtime.

## Maintenance and upgrade costs

The image is actively maintained, with releases in May 2026 and a CI/CD pipeline that scans for CVEs before and after publishing. That is a positive sign, but it does not remove your responsibility. Because there is no latest tag, you must track releases and update your compose file manually. The README suggests using short semver tags to reduce churn, but that still requires you to change the tag when a new minor version comes out. The -unraid and -nobody variants add flexibility for specific host environments, but they also multiply the number of tags you need to track. The license is MIT, which means you can use and modify the Dockerfile freely, but you should check the license of Unbound itself if you plan to redistribute. The image also depends on the 11notes/distroless layers, so upstream changes there can affect this image without a version bump here.

## Conclusion

Adopt 11notes/docker-unbound if you run Unbound as a local resolver and want a minimal, rootless, read-only image with no shell. Do not adopt it if you need a shell for debugging, expect a latest tag, or want to send queries to third-party resolvers without writing extra config. Before deploying, verify the pinned version tag, test your inline config with UNBOUND_CONFIG, and confirm the access-control ranges match your network. The image's value is its strict security posture, not its flexibility.

## FAQ

### What is unbound used for?

Unbound is a validating, recursive, caching DNS resolver, designed to be fast and lean and built on modern open standards. In this image it answers on port 53 over both UDP and TCP, and the default config is meant for local use where queries are not forwarded to third party resolvers such as Google or Quad9.

### Can I run Pi-Hole and unbound in Docker?

The README does not mention Pi-Hole. It documents running unbound itself in Docker, as image 11notes/unbound:1.25.1 publishing 53:53/udp and 53:53/tcp with /unbound/etc mounted as the configuration directory, running rootless as 1000:1000 with a read-only root filesystem.

### Why are people moving away from Docker?

The README does not address that. What it commits to for this image is rootless execution as 1000:1000, a distroless build with no shell, a read-only root filesystem, a health check, and CVE scanning both before and after publishing.

### Is Docker still relevant in 2026?

Not answered in the README. The project publishes releases, with v1.3.2, v1.3.1 and v1.2.4 listed, and states that the image is auto updated to the latest version through a pinned CI/CD process, with the most recent repository push on 30 September 2026.

## Sources

- [Official README](https://github.com/11notes/docker-unbound#readme)
- [Project repository](https://github.com/11notes/docker-unbound)
- [Release notes](https://github.com/11notes/docker-unbound/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/11notes-docker-unbound
