TrueNAS 25.04.2.4 Docker pull timeout after migrating from 24.04 (via 24.10)

Summary

Docker on TrueNAS 25.04.2.4 (Fangtooth) consistently fails to pull images from any container registry with timeout errors. Network connectivity is confirmed working, DNS resolution succeeds, and curl from within Docker’s network namespace can successfully connect to registries. However, Docker’s own pull mechanism fails with “net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)”.

System Information

  • TrueNAS version: 25.04.2.4

  • Docker version: 27.5.0 (community edition)

  • containerd version: 1.7.25

  • runc version: 1.2.4

  • Network: 192.168.168.192/24 on working LAN

  • Migration context: Upgraded from TrueNAS 24.04.2.5 (trying to migrate from k3s to Docker-based apps manually)

Problem Description

All docker pull commands fail with timeout errors:


$ sudo docker pull hello-world

Using default tag: latest

Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)

This affects all registries (Docker Hub, ghcr.io, gcr.io, quay.io).

What Works

  1. Host can reach Docker Hub:

$ curl https://registry-1.docker.io/v2/

# Returns 401 (expected - authentication required)

  1. DNS resolution works:

$ nslookup registry-1.docker.io

# Resolves correctly to multiple IPs

  1. Docker daemon starts and runs normally

  2. No proxy configuration present

  3. No firewall blocking (iptables OUTPUT chain is ACCEPT)

Diagnostic Journey

Initial Investigation

Docker daemon logs show timeout before attempting connection:


time="2025-10-05T23:32:10.576807676+01:00" level=debug msg="Trying to pull hello-world from https://registry-1.docker.io"

time="2025-10-05T23:32:25.577663725+01:00" level=warning msg="Error getting v2 registry: Get \"https://registry-1.docker.io/v2/\": context deadline exceeded"

tcpdump during pull attempt shows zero packets sent to registry:


$ sudo tcpdump -i any -n host registry-1.docker.io

# 0 packets captured - Docker doesn't even attempt the connection

IPv6 Investigation

Docker was attempting to use IPv6 despite the network being IPv4-only:


$ sudo journalctl -u docker | grep -i ipv6

time="2025-10-05T23:31:22.902956494+01:00" level=debug msg="Adding route to IPv6 network fdd0::1/64 via device docker0"

time="2025-10-05T23:31:22.903089365+01:00" level=debug msg="Could not add route to IPv6 network fdd0::1/64 via device docker0: network is down"

Mitigation attempted:

  1. Removed IPv6 configuration from /etc/docker/daemon.json

  2. Disabled IPv6 in Docker’s network namespace: nsenter -t $(pidof dockerd) -n sysctl -w net.ipv6.conf.all.disable_ipv6=1

  3. Created systemd startup script to permanently disable IPv6 in Docker’s namespace

Result: IPv6 disabled successfully, but pull still fails.

DNS Investigation

Testing DNS within Docker’s network namespace initially showed timeout:


$ sudo nsenter -t $(pidof dockerd) -n curl -v --max-time 10 https://registry-1.docker.io/v2/

* Resolving timed out after 10000 milliseconds

Mitigation attempted:

Added explicit DNS servers to /etc/docker/daemon.json:


{

"dns": ["1.1.1.1", "8.8.8.8"]

}

Result: DNS resolution now works in Docker’s namespace, but pull still fails.

Network Connectivity Verification

After DNS fix, curl from within Docker’s namespace works perfectly:


$ sudo nsenter -t $(pidof dockerd) -n curl -4 -v https://registry-1.docker.io/v2/

* Connected to registry-1.docker.io (34.237.110.211) port 443

< HTTP/2 401

{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":null}]}

# Connection succeeds, returns expected 401 auth error

But Docker pull still fails:


$ sudo docker pull hello-world

Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)

Traffic Analysis

During a pull attempt, tcpdump shows Docker makes NO network connections to external registries. Only local traffic (192.168.168.x) is captured. This confirms Docker’s HTTP client is failing before attempting any network I/O.

Current Configuration

/etc/docker/daemon.json:


{

"data-root": "/mnt/.ix-apps/docker",

"exec-opts": ["native.cgroupdriver=cgroupfs"],

"iptables": true,

"storage-driver": "overlay2",

"default-address-pools": [

{

"base": "172.17.0.0/12",

"size": 24

}

],

"dns": ["1.1.1.1", "8.8.8.8"]

}

/etc/systemd/system/docker.service.d/override.conf:


[Unit]

StartLimitBurst=1

StartLimitIntervalSec=910

[Service]

ExecStartPost=/bin/sh -c "iptables -P FORWARD ACCEPT && ip6tables -P FORWARD ACCEPT"

ExecStartPost=/mnt/.ix-apps/docker-disable-ipv6.sh

TimeoutStartSec=900

TimeoutStartFailureMode=terminate

Restart=on-failure

Key Findings

  1. Docker’s Go HTTP client fails while curl succeeds from the same network namespace - This indicates the issue is not network-level but specific to Docker’s HTTP transport implementation.

  2. Zero network packets sent to registries - Docker times out before attempting any TCP connection, suggesting the failure occurs in Docker’s registry client initialization or HTTP transport setup.

  3. All registries affected equally - Not specific to Docker Hub; affects ghcr.io, gcr.io, quay.io as well.

  4. Standard Docker binary - strings /usr/bin/dockerd | grep -i truenas returns no results; this is upstream Docker, not a TrueNAS custom build.

  5. No proxy or environment issues - Verified no HTTP_PROXY, HTTPS_PROXY, or NO_PROXY variables in dockerd process environment.

Unsuccessful Mitigation Attempts

  1. Disabled IPv6 completely (both in daemon.json and via sysctl)

  2. Added explicit DNS servers to daemon.json

  3. Verified and corrected iptables NAT/MASQUERADE rules

  4. Removed all IPv6 address pools from Docker configuration

  5. Deleted and recreated docker0 bridge interface

  6. Removed /var/lib/docker/network state

  7. Tested with registry mirrors

  8. Verified MTU settings (1500 on all interfaces)

  9. Confirmed no seccomp/AppArmor/SELinux restrictions

  10. Verified no systemd service hardening blocking network access

Comparison with Working System

On a working system, curl from Docker’s namespace would behave identically to Docker pull. On TrueNAS 25.04.2.4:

  • nsenter + curl: Works perfectly

  • Docker pull: Fails consistently

This strongly suggests a bug in Docker’s registry client or HTTP transport specific to how TrueNAS 25.04.2.4 was built or configured during the k3s to Docker migration.

Hypothesis

This appears to be a regression introduced in TrueNAS 25.04.2.4’s Docker implementation. The k3s to Docker migration may have left Docker in a broken state, or there’s an incompatibility between TrueNAS’s system configuration and Docker 27.5.0’s HTTP client.

Given that the June 1st 2025 app catalog update was supposed to break automatic migration from Dragonfish, users who migrated after that date may have incomplete or corrupted Docker setups.

Questions for TrueNAS Team

  1. Is this a known issue in TrueNAS 25.04.2.4?

  2. Are there TrueNAS-specific Docker configurations or middleware components that could interfere with Docker’s HTTP client?

  3. Should users who migrated from 24.04.2.5 to 25.04.2.4 perform any additional migration steps?

  4. Is downgrading to Electric Eel 24.10.2.2 a viable workaround?

Additional Context

This issue makes TrueNAS Apps completely non-functional as no images can be pulled. The system is otherwise healthy with all storage, networking, and services working correctly.

Any guidance would be greatly appreciated. Happy to provide additional diagnostics or test potential fixes.

Did you not upgrade in time?

After June 1st, Cobia and Dragonfish users with Kubernetes Apps will need to manually back up and restore their application data and configuration to a new Electric Eel installation. The manual update process is more complex and should be avoided.

From WARNING: June 1st is the Apps Migration Deadline for TrueNAS 24.04 and 23.10

Can you spell out which Apps you are updating.
Did you upgrade Apps to 24.10?.. or just through 24.10.

Were they TrueNAS apps or TrucCharts apps?

Are you using TrueNAS Apps or generic docker Apps.

Is the data for each App in a well-defined host path dataset?

They were TrueNAS apps with config in ixvolumes and data on host, but at this point I haven’t even got to being able to start restoring them, whichever app I try to install from scratch, Docker just can’t pull the image.

So I opened the shell to debug it and spent hours, but there’s still something going on with Docker that prevents it from connecting to any of the registries. I posted this massive wall of text to explain what I tried, I truly ran out of ideas what to try next other than a full reinstall which I’m not super keen on.

Lets start with simple examples…

TrueNAS Apps

or custom Docker Apps

Pick one and lets diagnose the simplest issue…

OK, so I’m trying to install an official App and the issue is the same as this forum post:

And then:

admin@truenas[~]$ sudo cat /var/log/app_lifecycle.log
[sudo] password for admin: 
[2025/10/05 19:15:06] (ERROR) app_lifecycle.compose_action():56 - Failed 'up' action for 'adguard-home' app:  adguard Pulling \n adguard Error Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)\nError response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)\n
[2025/10/05 20:51:58] (ERROR) app_lifecycle.compose_action():56 - Failed 'up' action for 'adguard-home' app:  adguard Pulling \n adguard Error Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)\nError response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)\n
[2025/10/05 21:00:44] (ERROR) app_lifecycle.compose_action():56 - Failed 'up' action for 'filebrowser' app:  init Pulling \n filebrowser Pulling \n permissions Pulling \n permissions Error Get "https://registry-1.docker.io/v2/": context deadline exceeded (Client.Timeout exceeded while awaiting headers)\n init Error context canceled\n filebrowser Error context canceled\nError response from daemon: Get "https://registry-1.docker.io/v2/": context deadline exceeded (Client.Timeout exceeded while awaiting headers)\n
[2025/10/05 21:12:40] (ERROR) app_lifecycle.compose_action():56 - Failed 'up' action for 'filebrowser' app:  init Pulling \n permissions Pulling \n filebrowser Pulling \n init Error Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)\n filebrowser Error context canceled\n permissions Error context canceled\nError response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)\n
[2025/10/05 21:14:42] (ERROR) app_lifecycle.compose_action():56 - Failed 'up' action for 'filebrowser' app:  permissions Pulling \n filebrowser Pulling \n init Pulling \n filebrowser Error Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)\n permissions Error context canceled\n init Error context canceled\nError response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)\n
[2025/10/05 21:18:52] (ERROR) app_lifecycle.compose_action():56 - Failed 'up' action for 'filebrowser' app:  init Pulling \n permissions Pulling \n filebrowser Pulling \n permissions Error Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)\n filebrowser Error context canceled\n init Error context canceled\nError response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)\n
[2025/10/05 21:20:03] (ERROR) app_lifecycle.compose_action():56 - Failed 'up' action for 'filebrowser' app:  filebrowser Pulling \n init Pulling \n permissions Pulling \n filebrowser Error Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)\n permissions Error context canceled\n init Error context canceled\nError response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)\n
[2025/10/06 08:19:02] (ERROR) app_lifecycle.compose_action():56 - Failed 'up' action for 'filebrowser' app:  filebrowser Pulling \n init Pulling \n permissions Pulling \n filebrowser Error Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)\n permissions Error context canceled\n init Error context canceled\nError response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)\n

I assume the system is broken because Apps that were installed with 24.04 have not been successfully migrated or deleted.

Does this seem like a reasonable supposition?

No-one without this migration issue are seeing the same problems.

How many Apps do you need to migrate… and do you have a plan for each?

This is starting from 0 apps, though maybe there are some corrupted remnants of the k3s ones. I knew that I’ll have to recreate my apps from scratch and I exported the configs from ixVolumes ready to import them back in. I wouldn’t mind working on the apps or even starting form scratch.

What I didn’t expect is that somehow I’ll end up with a completely broken Docker installation that is unable to make network requests. So it seems that the – now unavailable – migration scripts possibly also did something to clean up the k3s setup and the absence of which made it impossible for me to do anything with Docker.

So what I’m hoping to get out of this forum thread is a maintainer going “oh yes, of course, there’s this script to run or that Docker customisation that you’d need to change to make its networking work” or just generally some pointers what might be custom in the TrueNAS Docker setup that my standard Linux poking didn’t reveal.

It would be useful to understand what apps need to be rebuilt and that you have the data in host path volumes ready for attachment.

If this is Ok, you can reset the applications completely and start building apps from scratch?

(i’m guessing that you are working at the linux level and need to use the normal TrueNas processes so that the TrueNAS middleware and configuration are restored to a normal state)

@HoneyBadger Can you confirm the process to use.

I would guess it is to unset the Apps and pool and then go to Apps and set the pool again.

During the migration I lost all my apps (at least as far as the UI is concerned):

But these are the ones I’d like to get back:

adguard-home
filebrowser
immich
jellyfin
metube
prowlarr
qbittorrent
syncthing
tailscale

I tried unsetting and setting up the app pool just now, but it didn’t make much difference, still can’t install apps or even log in to Docker Hub:

That error message is wrong, the failure must also be due to the Docker networking issue as the same credentials copy/pasted from my password manager work elsewhere:

Also just realised there’s an image pull option in the UI so I can test without the shell:

I’ve only used the shell in TrueNAS to try to diagnose and possibly fix things with this migration, I’m a software developer with cloud infrastructure experience so can find my way around but I’d much more prefer to work with TrueNAS UI only and use it as an appliance as intended to and not spend my free time configuring Linux so I’d like to stick to out-of-the-box TrueNAS as much as possible.

Is there any other way to reset the Apps?

I should get a 2nd opinion…

The question is what has been corrupted in your system??

Do we need to re-install???

Exactly, these are the questions I’m trying to work out. I guess not using the official migration scripts while they were available is probably not great… But also maybe that I upgraded from Dragonfish to Electric Eel to Fangtooth relatively quickly and maybe some scripts were still running in Electric Eel?

Are there some particular logs I should check?

This feels more like a networking issue to me, especially considering we’ve seen users in this forum that have successfully made this transition without this problem both before and after the migration deadline.

I tried searching your error message in Jira and came up with two older issues. The first one looks like it was probably a temporary networking problem that resolved itself (Jira) and the second in a change to allow docker to see a configured http proxy (Jira) but that’s old enough that it should have no impact here. Other than those we have no bug reports involving this error from docker.

Maybe if you post more details about your networking setup someone might have some idea? I know there have been similar issues where people could not reach docker hub due to a nameserver misconfiguration or bridge issues.

I have bog standard network setup with micro PC running TrueNAS plugged in to an ISP router via ethernet cable running behind CGNAT:

Networking elsewhere in TrueNAS all works, just sent a test email to myself with Gmail OAuth.

Even the new Containers feature works:

Curl can reach the Docker registry:

admin@truenas[~]$ curl -v https://registry-1.docker.io/v2/
*   Trying 34.204.64.57:443...
* Connected to registry-1.docker.io (34.204.64.57) port 443 (#0)
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=*.docker.com
*  start date: Sep 24 00:00:00 2025 GMT
*  expire date: Oct 23 23:59:59 2026 GMT
*  subjectAltName: host "registry-1.docker.io" matched cert's "*.docker.io"
*  issuer: C=US; O=Amazon; CN=Amazon RSA 2048 M01
*  SSL certificate verify ok.
* using HTTP/2
* h2h3 [:method: GET]
* h2h3 [:path: /v2/]
* h2h3 [:scheme: https]
* h2h3 [:authority: registry-1.docker.io]
* h2h3 [user-agent: curl/7.88.1]
* h2h3 [accept: */*]
* Using Stream ID: 1 (easy handle 0x562756ac9ce0)
> GET /v2/ HTTP/2
> Host: registry-1.docker.io
> user-agent: curl/7.88.1
> accept: */*
> 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
< HTTP/2 401 
< date: Tue, 07 Oct 2025 15:02:02 GMT
< content-type: application/json
< content-length: 87
< docker-distribution-api-version: registry/2.0
< www-authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io"
< strict-transport-security: max-age=31536000
< 
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":null}]}
* Connection #0 to host registry-1.docker.io left intact

It’s just something’s going on with Docker’s networking, but even using Claude to give me commands to try I couldn’t find what’s misconfigured.

Just found out that I only let Electric Eel run for ~9 minutes:

But it’s a reasonably performant PC with nothing else to do so should have been able to run at least basic migration scripts in that time?

Scrolled through /var/log/syslog but nothing jumped out from the boots after these updates, but I also don’t know what to look for.

@dain did validate that the system has reachability to docker hub.

Do you think a reinstall might clear up whatever issue is causing it?

I think this is what’s tripping things up here. CGNAT (Carrier Grade Network Address Translation) basically means you’re being piped through two layers of NAT device - so from Docker’s perspective, it’s probably seeing dozens/hundreds/thousands of image pull requests, all coming from what appears to be a single endpoint - one of the carrier’s available IPv4 addresses.

Unfortunately the only way around this would be to register a Docker account and let the TrueNAS Apps service leverage it (I’m not sure offhand how to do this) or switch ISPs/get out from behind CGNAT somehow.

1 Like

That could have been it, but I also can’t log in to the Docker Hub in the TrueNAS UI, pulling images always work on my laptop, and it’s not rate limit error that I’m getting but not being able to connect. Oh, and I tried a few other registries like quay and ghcr.

I found that and tried to log in, but that also doesn’t work, see this post:

I wanted to try logging in to ghcr.io but they only accept Github tokens, not username / password.