Docker¶
The image is vpcatlas/vpcatlas on Docker Hub. It carries the whole tool: the command line and the dashboard.
Tags and platforms¶
Each release tag v<major>.<minor>.<patch> publishes the image for linux/amd64 and linux/arm64 under:
| Tag | Meaning |
|---|---|
<major>.<minor>.<patch> (for example 0.1.0) |
That exact release. Pin this in production. |
<major>.<minor> |
The latest patch of that minor version. |
latest |
The latest release. |
The Lambda image is a separate repository, vpcatlas/vpcatlas-lambda; see lambda.md.
Entrypoint and default command¶
The entrypoint is the vpcatlas command and the default command is
serve --host 0.0.0.0 --port 8080. So with no arguments the container runs the dashboard, and any other
command of the CLI is the argument list:
docker run --rm -p 8080:8080 vpcatlas/vpcatlas:0.1.0 # the dashboard
docker run --rm vpcatlas/vpcatlas:0.1.0 --version
docker run --rm vpcatlas/vpcatlas:0.1.0 serve --help
The image runs as the unprivileged user atlas (uid and gid 10001, home /home/atlas), exposes port 8080,
and runs one worker: the snapshot lives in the memory of the process. To scale out, share state with
VPCATLAS_SNAPSHOT_URI instead of adding workers (see the dashboard).
Environment set by the image:
| Variable | Value | Why |
|---|---|---|
VPCATLAS_REFRESH_SECONDS |
0 |
One scan at start, then manual refreshes only. Set it (for example 900) to rescan periodically. |
PORT |
8080 |
Read by the health check only, to find the port. The server listens on --port. |
AWS_STS_REGIONAL_ENDPOINTS |
regional |
Session tokens from the global STS endpoint are not valid in opt-in Regions. |
PYTHONUNBUFFERED |
1 |
Logs appear immediately. |
The image has a HEALTHCHECK that runs python -m vpcatlas.dashboard.healthcheck every 30 seconds (it requests
/healthz on the loopback address).
Run the dashboard¶
docker run --rm -p 8080:8080 \
-e VPCATLAS_REFRESH_SECONDS=900 \
-e VPCATLAS_REGIONS=eu-west-1,eu-central-1 \
-e AWS_PROFILE=audit \
-v "$HOME/.aws:/home/atlas/.aws:ro" \
vpcatlas/vpcatlas:0.1.0
Open http://127.0.0.1:8080. -p 8080:8080 publishes the port on every interface of the host; use
-p 127.0.0.1:8080:8080 unless you mean to expose it, and read authentication
first. The settings are the VPCATLAS_* variables described in the dashboard page.
Credentials in the container¶
The container resolves credentials with the standard AWS chain. Pick the way that fits where it runs:
- On AWS (ECS, EKS, EC2). Use the task role, the pod role (IAM roles for service accounts) or the instance role. Nothing is mounted or passed. This is the preferred way; see ecs.md and kubernetes.md.
- Environment variables. Pass
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEYand, for temporary credentials,AWS_SESSION_TOKENwith-e NAME(no value, so the secret is copied from your shell and never appears on the command line or in the image):
docker run --rm -p 127.0.0.1:8080:8080 \
-e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN -e AWS_REGION \
vpcatlas/vpcatlas:0.1.0
Short-lived credentials from an SSO profile can be exported for this:
eval "$(aws configure export-credentials --profile my-audit --format env)".
- Shared credentials and config files. Mount ~/.aws read-only at /home/atlas/.aws and name the profile with
AWS_PROFILE or VPCATLAS_PROFILE. A credential_process profile needs its helper binary, which the image does not contain.
An SSO profile works from the token cache in the mount until that token expires (the mount is read-only, so a refreshed
token is not written back); for a long run, export short-lived credentials instead. On Linux the mounted files must be readable by uid 10001, or run the container with
--user "$(id -u):$(id -g)" and -e HOME=/home/atlas.
- Another account through a role. Set VPCATLAS_ROLE_ARN (comma separated for several) and, if the trust policy
has one, VPCATLAS_EXTERNAL_ID. The identity from the sources above assumes the role. See iam.md.
Secret keys are not command-line options anywhere in vpcatlas; do not write them in the docker run line as
-e AWS_SECRET_ACCESS_KEY=... either, because they end up in the shell history and in docker inspect.
Run other CLI commands¶
Use the same image with a different command, and a volume for the output:
docker run --rm \
-v "$HOME/.aws:/home/atlas/.aws:ro" \
-v "$PWD/out:/data" \
vpcatlas/vpcatlas:0.1.0 \
discover --profile audit --regions eu-west-1 --output-dir /data
The mounted output directory must be writable by uid 10001 (on Linux, chown 10001:10001 out or pass --user).
vpcatlas iam-policy prints the auditor policy, so you can create the role without cloning the repository:
docker run --rm vpcatlas/vpcatlas:0.1.0 iam-policy > auditor-policy.json
Volumes¶
| Mount | Use |
|---|---|
/home/atlas/.aws (read-only) |
Shared credentials and config files. Optional. |
/data (or any path you choose) |
Output of discover, inventory and diagram. |
A directory for VPCATLAS_SNAPSHOT_URI=file:///... |
Snapshots and history, if you do not use S3. Must be writable by uid 10001. |
/tmp as a tmpfs |
Needed when the root file system is read-only, as in the shipped Compose, ECS and Kubernetes manifests. |
Resource needs¶
The dashboard is light while idle and busy during a scan, which makes parallel API calls and builds the diagrams in memory. The shipped manifests give a feel for the sizes:
- Kubernetes: request
100mCPU and256Mi, limit1CPU and1Gi. - ECS Fargate:
512CPU units and1024MiB, which is enough for a typical account. If a scan of a very large estate is killed (exit code 137), raise memory to2048and CPU to1024. - Lambda:
2048MB and a 15-minute timeout; see lambda.md.
Scanning fewer Regions (VPCATLAS_REGIONS) or lowering VPCATLAS_CONCURRENCY reduces both time and peak memory.
The scan makes read-only calls to the AWS APIs, so the container needs outbound HTTPS (443) to them, and to
viewer.diagrams.net only in the browsers that open the dashboard, not in the container.
Build it yourself¶
From the repository root:
make docker-build # docker build -f deploy/Dockerfile -t <image>:<version> .
deploy/Dockerfile is a multi-stage build on python:3.12-slim: the package is installed into a virtual
environment, and only that environment is copied into the runtime stage. Next: compose.md runs it
locally with a hardened configuration.