Recently we have been updating our Docker images to the latest version of Alpine 3.18.
With this change we noticed that our application was not able to send HTTP requests using cURL to other containers that are running on the same host. This was made possible by using the extra_hosts
flag in our Docker Compose file.
Whilst debugging we noticed that Alpine recently switched to cURL version 8, specifically 8.2.1. In this update it feels like it is ignoring the /etc/hosts
file, which is where Docker writes the extra_hosts
configuration.
docker-compose.yml:
version: "3.8"
services:
test:
image: alpine:3.18
extra_hosts:
- example.localhost:host-gateway
Run container: docker-compose run test sh
Inside the container:
Installing cURL:
apk add curl
Installed version:
/ # curl --version
curl 8.2.1 (aarch64-alpine-linux-musl) libcurl/8.2.1 OpenSSL/3.1.2 zlib/1.2.13 brotli/1.0.9 libidn2/2.3.4 nghttp2/1.55.1
Release-Date: 2023-07-26
Protocols: dict file ftp ftps gopher gophers http https imap imaps mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp ws wss
Features: alt-svc AsynchDNS brotli HSTS HTTP2 HTTPS-proxy IDN IPv6 Largefile libz NTLM NTLM_WB SSL threadsafe TLS-SRP UnixSockets
Execute cURL:
/ # curl -v example.localhost
* processing: example.localhost
* Trying [::1]:80...
* Immediate connect fail for ::1: Address not available
* Trying 127.0.0.1:80...
* connect to 127.0.0.1 port 80 failed: Connection refused
* Failed to connect to example.localhost port 80 after 0 ms: Couldn't connect to server
* Closing connection
curl: (7) Failed to connect to example.localhost port 80 after 0 ms: Couldn't connect to server
Which is odd since
/ # cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
192.168.65.254 example.localhost
172.20.0.3 76a7dfa28161
And
/ # ping example.localhost
PING example.localhost (192.168.65.254): 56 data bytes
64 bytes from 192.168.65.254: seq=0 ttl=62 time=2.224 ms
64 bytes from 192.168.65.254: seq=1 ttl=62 time=0.731 ms
64 bytes from 192.168.65.254: seq=2 ttl=62 time=0.322 ms
^C
--- example.localhost ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.322/1.092/2.224 ms
Am I missing something?
2
Answers
Solved! As mentioned by @β.εηοιτ.βε, the problem was caused by the fact that I was using
.localhost
for my local development setup. cURL fairly recently started to automatically resolve all requests going to.localhost
to127.0.0.1
. This makes cURL ignore/etc/hosts
.The top level domain (TLD)
.localhost
should be treated aslocalhost
, as per RFC 2606Source: https://datatracker.ietf.org/doc/html/rfc2606#section-2
This is further documented in RFC 6761
Source: https://datatracker.ietf.org/doc/html/rfc6761#section-6.3
Which seems to be the rational behind its implementation in CURL as per this pull request: https://github.com/curl/curl/pull/9296.
This can be tested with the Dockerfile:
Running it with a
.localhost
TLD:Running it with another TLD, for example
.example
: