Container hardening guides¶
Every guide below takes one popular Docker image, grades its default docker run on IronClaw's
seven-dimension containment scale, and shows the exact ironctl scan --fix flags that close the gap.
The numbers are not hand-waved: each comes from a read-only docker inspect of the real image, the
same data behind that image's isolation scorecard. No workload is executed to
produce them.
Two patterns show up across the set:
- Datastores and sandboxes reach grade A. A database or a code sandbox that only its co-located
services talk to can take
--network=noneand hit 100/100. Root, capabilities, and a read-only rootfs are the whole game. - Network services hit an honest ceiling at grade B. A broker, cache, proxy, or secrets server
exists to be connected to, so
--network=nonewould score the last points but break the service. The honest ceiling is 89/100, grade B, with the network dimension held at a WARN and contained with a scoped private network instead. We say so on every page rather than inflate the number.
Reach grade A (100/100)¶
| Service | Default | Hardened | The gap that closes |
|---|---|---|---|
| Postgres | 48/100 D | 100/100 A | root, full caps, writable rootfs |
| MySQL | 48/100 D | 100/100 A | root, full caps, writable rootfs |
| MariaDB | 48/100 D | 100/100 A | root, full caps, writable rootfs |
| MongoDB | 48/100 D | 100/100 A | root, full caps, writable rootfs |
| Redis | 48/100 D | 100/100 A | root, full caps, writable rootfs |
| Cassandra | 48/100 D | 100/100 A | root, full caps, writable rootfs (89/B multi-node) |
| ClickHouse | 48/100 D | 100/100 A | root, full caps, writable rootfs |
| Elasticsearch | 63/100 C | 100/100 A | full caps, writable rootfs (89/B multi-node) |
| InfluxDB | 48/100 D | 100/100 A | root, full caps, writable rootfs (89/B if fleet pushes metrics) |
| Neo4j | 48/100 D | 100/100 A | root, full caps, writable rootfs (89/B if clustered or remote clients) |
| CouchDB | 48/100 D | 100/100 A | root, full caps, writable rootfs (89/B if clustered or remote clients) |
| QuestDB | 48/100 D | 100/100 A | root, full caps, writable rootfs (89/B if a fleet pushes metrics) |
| CockroachDB | 48/100 D | 100/100 A | root, full caps, writable rootfs (89/B if clustered or remote clients) |
| TimescaleDB | 48/100 D | 100/100 A | root, full caps, writable rootfs (89/B with replicas or remote clients) |
| Valkey | 48/100 D | 100/100 A | root, full caps, writable rootfs (89/B as a shared network cache) |
| Loki | 63/100 C | 100/100 A | full caps, writable rootfs (89/B if a fleet pushes logs) |
| Tempo | 63/100 C | 100/100 A | full caps, writable rootfs (89/B if a fleet pushes traces) |
| Meilisearch | 48/100 D | 100/100 A | root, full caps, writable rootfs (89/B if remote clients) |
| YugabyteDB | 48/100 D | 100/100 A | root, full caps, writable rootfs (89/B multi-node cluster) |
| Dragonfly | 48/100 D | 100/100 A | root, full caps, writable rootfs (89/B as a shared network cache) |
| OpenSearch | 63/100 C | 100/100 A | full caps, writable rootfs (89/B multi-node cluster) |
| Qdrant | 48/100 D | 100/100 A | root, full caps, writable rootfs |
| ArangoDB | 48/100 D | 100/100 A | root, full caps, writable rootfs (89/B if clustered or remote clients) |
| Solr | 63/100 C | 100/100 A | full caps, writable rootfs (89/B multi-node cluster or remote clients) |
| VictoriaMetrics | 48/100 D | 100/100 A | root, full caps, writable rootfs (89/B if a fleet pushes metrics) |
| ScyllaDB | 48/100 D | 100/100 A | root, full caps, writable rootfs (89/B multi-node cluster) |
| Dgraph | 48/100 D | 100/100 A | root, full caps, writable rootfs (89/B if clustered or remote clients) |
| Weaviate | 48/100 D | 100/100 A | root, full caps, writable rootfs (89/B if remote clients) |
| RethinkDB | 48/100 D | 100/100 A | root, full caps, writable rootfs (89/B if clustered or remote clients) |
| TiDB | 48/100 D | 100/100 A | root, full caps, writable rootfs (89/B production cluster or remote clients) |
| Untrusted Node.js | 48/100 D | 100/100 A | run untrusted code in a real sandbox |
Honest ceiling: grade B (89/100)¶
These services must accept client connections, so the network dimension holds at a WARN by design.
| Service | Default | Hardened | Why 89 is the ceiling |
|---|---|---|---|
| Kafka | 63/100 C | 89/100 B | broker: producers and consumers must connect |
| RabbitMQ | 48/100 D | 89/100 B | broker: every service connects to the queue |
| Memcached | 63/100 C | 89/100 B | cache: clients read and write over the network |
| nginx | 48/100 D | 89/100 B | proxy: it exists to forward traffic |
| Vault | 48/100 D | 89/100 B | secrets server: apps must reach the API |
| Consul | 48/100 D | 89/100 B | service mesh: peers and clients must connect |
| MinIO | 48/100 D | 89/100 B | object store: S3 clients must reach the API |
| Grafana | 63/100 C | 89/100 B | dashboard: browsers must reach the UI |
| Prometheus | 63/100 C | 89/100 B | metrics: it scrapes targets and serves its API |
| Traefik | 48/100 D | 89/100 B | proxy: it exists to accept and forward traffic |
| Jenkins | 48/100 D | 89/100 B | CI server: agents and browsers must reach it |
| SonarQube | 48/100 D | 89/100 B | code-quality server: scanners and browsers must reach it |
| Keycloak | 48/100 D | 89/100 B | identity provider: every app must reach its endpoints |
| NATS | 48/100 D | 89/100 B | broker: publishers and subscribers must connect |
| Gitea | 48/100 D | 89/100 B | git server: developers and CI must reach it |
| HAProxy | 63/100 C | 89/100 B | load balancer: it exists to accept and forward traffic |
| Typesense | 48/100 D | 89/100 B | search server: your app must reach its query API |
| Immich | 48/100 D | 89/100 B | photo server: browsers and mobile apps must reach it |
| pgAdmin | 63/100 C | 89/100 B | admin console: your browser must reach the UI |
| Redpanda | 63/100 C | 89/100 B | broker: producers and consumers must connect |
| EMQX | 63/100 C | 89/100 B | MQTT broker: publishers and subscribers must connect |
| Kong | 63/100 C | 89/100 B | API gateway: clients and upstreams connect through it |
| Envoy | 48/100 D | 89/100 B | proxy: it exists to accept and forward traffic |
| Pulsar | 63/100 C | 89/100 B | broker: producers and consumers must connect |
| NSQ | 48/100 D | 89/100 B | broker: publishers and subscribers must connect |
The pattern, one command¶
Every grade on this page comes from the same tool. Point it at any running container, a
docker-compose.yml service, or a Kubernetes manifest, and it grades the real thing, then prints the
fixes:
# install (Homebrew)
brew install ironsecco/ironclaw/ironclaw
# grade it, then print the exact hardening flags
ironctl scan my-container
ironctl scan my-container --fix
Want it in CI? The same engine ships as a GitHub Action on the Marketplace that scores every pull request and posts the grade as a sticky comment.
Keep going¶
- Scan any container in 10 seconds →: the full
ironctl scanreference. - Container Isolation Scores →: default-config grades for the most-pulled public images.
- The State of Container Isolation, 2026 →: the survey the whole directory is built from.
- Run untrusted code in a real sandbox →: IronClaw wraps every AI-agent session in a gVisor/Kata boundary with
network=noneby default.