Skip to content

setupDNS skipped when installed dnsmasq has a pending upgrade #1611

Description

@jcbl1

Description

On the current Ubuntu 24.04 image, docker pull fails with DNS resolution error:

Error response from daemon: ... lookup registry-1.docker.io on [::1]:53: read udp [::1]:xxxxx->[::1]:53: read: connection refused

Root cause is in environment/vm/lima/dns.go, hasDnsmasq():

func hasDnsmasq(l *limaVM) bool {
    // check if dnsmasq is installed
    return l.RunQuiet("sh", "-c", `apt list | grep 'dnsmasq\/' | grep '\[installed'`) == nil
}

setupDNS() early-returns (does nothing) when hasDnsmasq is false:

if !hasDnsmasq(l) {
    // older image still using systemd-resolved
    // ignore
    return nil
}

The grep \[installed only matches apt list lines that contain the literal [installed marker. When the installed dnsmasq package has a pending upgrade, apt list (without --installed) outputs the line as:

dnsmasq/noble-updates,noble-security 2.90-2ubuntu0.4 all [upgradable from: 2.90-2ubuntu0.3]

Note the marker is [upgradable from: …], NOT [installed] (the latter only appears with apt list --installed, which colima does not use). So hasDnsmasq returns false even though dnsmasq IS installed.

Consequence chain (all verified on my VM):

  1. setupDNS returns nil → /etc/dnsmasq.d/01-colima.conf is never written.
  2. /etc/resolv.conf is left as the image-shipped dangling symlink: /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf. The systemd-resolved package is NOT installed on this image (Unit systemd-resolved.service could not be found), so the symlink target never exists.
  3. glibc resolver reads no nameserver → falls back to default [::1]:53, where nothing listens → connection refused.
  4. Additionally dnsmasq.service fails on every boot because it tries to use /etc/resolv.conf as its resolv-file, which is a dangling symlink:
  • dnsmasq: directory /etc/resolv.conf for resolv-file is missing, cannot poll
  • dnsmasq.service: Failed with result 'exit-code'.

So docker pull cannot resolve registry-1.docker.io.

Note: this is NOT fixed by colima start --dns 8.8.8.8 --dns 1.1.1.1. That flag is written to colima.yaml (network.dns) and correctly reaches netplan/systemd-networkd (networkctl status eth0 shows the DNS), but because setupDNS short-circuits, the DNS never gets written into /etc/resolv.conf (the only file glibc reads).

Suggested fix: detect dnsmasq via a package manager query that doesn't depend on apt list's marker formatting, e.g.:

return l.RunQuiet("sh", "-c", `dpkg -s dnsmasq >/dev/null 2>&1`) == nil

or command -v dnsmasq.

Version

colima version 0.10.3
git commit: 00f6c29

runtime: docker
arch: aarch64
client: v29.6.2
server: v29.5.2
limactl version 2.2.0
qemu-img: N/A (using macOS Virtualization.Framework, not QEMU)

Operating System

  • macOS Intel <= 13 (Ventura)
  • macOS Intel >= 14 (Sonoma)
  • Apple Silicon <= 13 (Ventura)
  • Apple Silicon >= 14 (Sonoma)
  • Linux

Output of colima status

colima is running using macOS Virtualization.Framework
arch: aarch64
runtime: docker
mountType: virtiofs
docker socket: unix:///Users//.colima/default/docker.sock
containerd socket: unix:///Users//.colima/default/containerd.sock

Reproduction Steps

  1. brew install colima docker
  2. colima start # default Ubuntu 24.04 image; ships dnsmasq 2.90-2ubuntu0.3,
    # while noble-updates/noble-security candidate is 2.90-2ubuntu0.4
    # → apt marks dnsmasq as [upgradable from: ...]
  3. docker pull hello-world

Expected behaviour

docker pull hello-world should succeed. When dnsmasq is installed, setupDNS should write
/etc/dnsmasq.d/01-colima.conf and replace /etc/resolv.conf with a regular file
(# Generated by Colima\n\nnameserver <internalIP>\n), and restart dnsmasq to serve DNS —
regardless of whether the installed dnsmasq apt package has a pending upgrade.

Additional context

Workaround that restores docker pull immediately:

colima ssh -- sudo sh -c 'rm -f /etc/resolv.conf; printf "nameserver 8.8.8.8\nnameserver 1.1.1.1\n" > /etc/resolv.conf'

This is stable across colima stop/start because hasDnsmasq stays false (due to the same bug),
so setupDNS never overwrites the manually-written resolv.conf. (If dnsmasq later gets upgraded so
apt list shows [installed] again, colima's setupDNS takes over correctly — also fine.)

The same hasDnsmasq line is unchanged on main as of today, so the bug is present in the latest release.

Possibly related (similar symptom, different sub-cause): #1437 — there resolv.conf WAS written to point at
the internal IP (192.168.5.1) but dnsmasq didn't forward upstream (no such host), whereas here setupDNS
is skipped entirely so resolv.conf is left as the dangling symlink ([::1]:53 connection refused).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions