How to Fix Docker Container Unable to Access AWS Metadata Service (169.254.169.254)
Quick answer
Your containerized application, running on an EC2 instance and expecting to fetch temporary AWS credentials or instance metadata, can't reach the special...
Your containerized application, running on an EC2 instance and expecting to fetch temporary AWS credentials or instance metadata, can't reach the special metadata endpoint β even though the underlying EC2 host itself can reach it without any issue. Docker's networking layer sits between your container and that endpoint, and depending on configuration, it can block or interfere with reaching it.
The Problem
Code inside the container that expects to fetch instance metadata or IAM role credentials times out or fails outright:
$ docker exec myapp curl -s http://169.254.169.254/latest/meta-data/
curl: (28) Failed to connect to 169.254.169.254 port 80 after 5013 ms: Connection timed out
Meanwhile, the same request succeeds without any issue when run directly on the EC2 host, outside any container:
$ curl -s http://169.254.169.254/latest/meta-data/
ami-id
ami-launch-index
...
Why It Happens
The AWS instance metadata service lives at a special link-local address (169.254.169.254) that's normally reachable in exactly one network hop from the EC2 instance itself. Docker's default bridge networking mode inserts an additional network hop (through NAT) between your container and the host's network interfaces, which can interfere with reaching this specific address in a few distinct ways:
- IMDSv2's hop limit β AWS's more secure metadata service version (IMDSv2) defaults to a hop limit of 1, meaning requests that cross more than one network hop (as Docker's bridge networking introduces) get silently dropped by the metadata service itself, even though basic connectivity might otherwise be fine.
- Docker's default bridge network NAT not correctly routing the link-local address range, since
169.254.0.0/16is a special-purpose address block that doesn't always route the same way as normal traffic through Docker's virtual networking. - A custom Docker network configuration (a user-defined bridge network with specific settings, or an overlay network in Swarm/ECS) that doesn't have a clear route to the host's network interface at all.
- ECS-specific task networking mode β the
awsvpcnetwork mode behaves differently from bridge mode regarding metadata access, and using the wrong mode for your use case can cause exactly this symptom.
The Fix
For the IMDSv2 hop-limit issue, which is the most common cause when running Docker with bridge networking, raise the instance's metadata hop limit to accommodate the extra hop Docker's networking introduces:
aws ec2 modify-instance-metadata-options \
--instance-id i-0123456789abcdef0 \
--http-put-response-hop-limit 2 \
--http-endpoint enabled
This single change resolves the majority of "metadata unreachable from inside a container" issues on EC2 instances using Docker's default bridge networking, since it explicitly accounts for the extra hop rather than requiring any change to your container's networking configuration.
If you're running plain Docker (not orchestrated by ECS) and want the container to use the host's networking stack directly rather than Docker's bridge, host networking mode bypasses this issue entirely by removing the extra hop:
docker run --network host myapp
Be aware this removes network isolation between the container and host entirely, so it should be a deliberate choice rather than a default, especially in any multi-tenant or security-sensitive environment.
For ECS tasks specifically, using awsvpc network mode gives each task its own elastic network interface, which handles metadata access differently (and generally more predictably) than the default bridge mode β check your task definition's network mode:
aws ecs describe-task-definition --task-definition my-task --query 'taskDefinition.networkMode'
"bridge"
If it's set to bridge and you're relying on IAM role credentials via the metadata service inside the task, either raise the hop limit as shown above, or migrate the task definition to awsvpc mode if your workload and VPC configuration support it.
Still Not Working?
If you've raised the hop limit and confirmed the network mode but the metadata service is still unreachable, check whether a custom iptables rule or security tool on the host is specifically blocking traffic to the link-local address range for containers, which is sometimes intentionally configured as a security hardening measure on shared or multi-tenant hosts to prevent containers from accessing host credentials:
sudo iptables -L -n -v | grep 169.254
If you find an explicit block, that's likely an intentional security control put in place by whoever manages the host, and you'll need to coordinate with them on whether an exception is appropriate for your specific container's legitimate need to access instance credentials, rather than simply removing the rule yourself.