You can try disable userland-proxy
in Docker daemon config. On a linux host you would usually do this:
/etc/docker/daemon.json
:
{
"userland-proxy": false
}
Then restart the Docker daemon: systemctl restart docker
This disables some conveniences mostly related to localhost to container routing. I documented differences here some time ago, with a handy true
/ false
table.
Disabling the proxy like this will remove notable amount of network overhead if there was a performance issue there (quite observable difference with network perf tests at least).
You can run into a variety of other gotchas that depends on the environment and how you’ve configured it.
Another big performance gotcha that you can run into is with file descriptors, this shouldn’t affect Caddy, but if the issue is possibly tied to the service you’re connecting to then you should consider checking ulimit -Sn
output from inside the container, if that number is not 1024
, it will likely approximately 1 million, or 1 billion.
Either of those larger values is technically a bug and should be finally resolved in a Docker release later this year or in 2025. 1 million usually isn’t noticeable for regressions it causes, but 1 billion often is. Some software will also appear to randomly crash if the value is above 1024
due to select()
legacy syscall usage.
To rule this one out, if you have a value that was higher than 1024
, configure the container ulimit
setting (CLI, Compose) to use 1024
as the soft limit and 524288
as the hard limit, the soft limit is the important one.
A common bug this resolves is high CPU activity from processes that are iterating through the entire file descriptor limit. 1024
is a small range vs a billion syscalls. I’ve come across various software where that introduced slowdowns of operations that should take less than 1 sec become 10 minutes or even beyond an hour.
HTTPS doesn’t normally support IP in certs from public CAs.
Just query the actual FQDN and if the cert is provisioned internally but you lack it in your trust store, you can skip verification curl --insecure https://example.com
(you should also be able to do https://ip
too since this skipping cert verification via --insecure
).
Since you mentioned the backend service you’re connecting to is on another host, and is the IP you’re connecting to, if that runs in Docker too, you should apply the advice about ulimit
above, and possible userland-proxy
to that instead. Shouldn’t really matter for Caddy container AFAIK.
If anything, I would suggest trying to verify if you can reproduce with Caddy and the backend service on the same server. There are a variety of network gotchas that can occur with Docker, especially if preserving the original client IP is important.