Note
Do NOT use MetaDock in production. It is for local development environments only.
MetaDock provides a lightweight Go implementation of a subset of the AWS Instance Metadata Service (IMDSv2)
for the purpose of providing session credentials only.
It is designed to run inside a Docker container and can be included in a docker-compose setup to
provide AWS credentials to other services, effectively emulating an EC2 environment locally.
Instead of retrieving credentials from AWS, the emulator loads them from the host, via the mounted
${HOME}/.aws directory, and then exposes them through the same API paths that would normally be
available inside an EC2 instance:
/latest/api/token/latest/meta-data/iam/security-credentials/latest/meta-data/iam/security-credentials/{role-name}
MetaDock responds with the same metadata format as a real EC2 instance, enabling AWS SDKs and CLI
commands inside containers to authenticate transparently.
It relies on the developer obtaining AWS credentials on the host machine before running the metadock
service. If long-lived (static) credentials are found, the service will generate session credentials,
with a default expiry of 12 hours.
- AWS CLI v2 installed and configured (
aws configure,aws sso login, or equivalent) - AWS configuration profile with valid credentials.
- Docker and
docker-compose - Task for running development tasks
aws configureOr
aws sso login [--profile profile-name]The MetaDock service can be used in one of the following ways.
-
Using the provided
compose.metadock.ymlfile.- Use an
includedirective to include thecompose.metadock.ymlfile. - Add the
metadocknetwork to the services which need IMDS.
See
compose.example.ymlfor an example configuration. - Use an
-
Adding the
metadockservice and configure theAWS_EC2_METADATA_SERVICE_ENDPOINTenvironment variable.Edit your compose file, add the
metadockservice and configure services which need IMDS.services: metadock: image: "ghcr.io/virtualstaticvoid/metadock:latest" command: "${AWS_PROFLE:-default}" volumes: - "${HOME}/.aws:/root/.aws:ro" your_service: image: "..." env: AWS_EC2_METADATA_SERVICE_ENDPOINT: http://metadock/
Optionally, from within the respective services (using the docker exec command).
-
If
curlis installed in the container, check if theMetaDockservice is issuing credentials.TOKEN=$(curl -X PUT "http://metadock/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") curl -H "X-aws-ec2-metadata-token: $TOKEN" http://metadock/latest/meta-data/iam/security-credentials/metadock # => {"AccessKeyId":"...", ...}
See Use the Instance Metadata Service to access instance metadata documentation for details.
-
If the
awsCLI tool is installed in the container, check by running thests get-caller-identityCLI command.aws sts get-caller-identity --no-cli-pager # => {"UserId": "...", ...}
This project uses Task to manage common development workflows.
task buildtask testtask cleanAlternatively, you can run it directly on the host.
go build -o metadock .
PORT=8080 ./metadock <profile-name>And connect, via localhost with the configured PORT.
TOKEN=$(curl -X PUT "http://localhost:8080/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://localhost:8080/latest/meta-data/iam/security-credentials/metadock
# => {"AccessKeyId":"...", ...} MIT License. Copyright (c) 2025 Chris Stefano. See LICENSE for details.