Securing Your Container
Most container security comes down to a handful of habits: ship a small image, run as a non-privileged user, keep secrets out of the build, and gate the ingress. This article is a practical checklist you can work through for any workload you deploy.
Most container security comes down to a handful of habits: ship a small image, run as a non-privileged user, keep secrets out of the build, and gate the ingress. This article is a practical checklist you can work through for any workload you deploy.
Build a minimal, current image
- Start from a minimal base. A smaller base image carries fewer packages, which means fewer things to patch and a smaller attack surface. Slim, distroless, or Alpine-style bases are good starting points.
- Install only what you run. Drop build tools, compilers, and debug utilities from the final image. Use a multi-stage build so the runtime stage carries only your application and its direct dependencies.
- Keep images updated. A base image that was current at build time drifts as vulnerabilities are disclosed. Rebuild and redeploy on a regular cadence so you pick up upstream fixes, and rebuild promptly when a dependency you rely on is patched.
Run as a non-root user
Do not let your process run as root inside the container. Create an unprivileged user in your image and switch to it:
RUN adduser --disabled-password --gecos "" app
USER appIf your application is ever compromised, running as an ordinary user limits what the attacker can do inside the container.
Keep secrets out of the image
Never COPY credentials in, set them with a build-time ENV, or hard-code them in source. Anything baked into the image travels everywhere the image goes. Store sensitive values in the vault and inject them at runtime instead — they are encrypted at rest and only decrypted at deploy time. See Secrets and vault best practices.
Give the platform a health check
Point your container at a health-check endpoint so the platform can tell a healthy instance from a broken one and route around failures. An unhealthy region is removed from rotation rather than served to users. See Health checks.
Gate the ingress
For HTTP containers, Bahriya applies three controls at the ingress — before a request ever reaches your application:
- Rate limiting caps how many requests a single client IP can make per minute or per hour, blunting abuse and brute-force attempts.
- IP allow-list restricts a container to a known set of addresses — useful for internal services, office-only tools, and webhook receivers with published source ranges.
- IP deny-list blocks a specific set of addresses while keeping the container open to everyone else.
They combine, and the order matters: deny-list, then allow-list, then rate limiting, then basic auth. Because rate limiting runs before basic auth, it throttles credential-guessing before the credential is even checked. See Rate limiting and IP rules.
Put basic auth on internal endpoints
For staging environments, dashboards, and internal tools that lack their own login, require HTTP basic authentication at the ingress. You can add up to 10 credentials per container; passwords are encrypted at rest and can never be read back — if someone forgets theirs, you set a new one. See Basic authentication.
When you tighten an allow-list on a live container, confirm your own IP is on the list first. It is easy to lock yourself out, and the change rolls out on the next deployment cycle.
Constrain what the container can reach
If a workload should only talk to a known set of destinations, attach a network policy with egress rules. Adding any egress rule switches outbound traffic to deny-by-default, so only the domains and ranges you list get through. Prefer domain rules over IP ranges for third-party services. See Private networking.
Checklist
[ ] Minimal base image, multi-stage build, no build tools in runtime
[ ] Runs as a non-root user
[ ] No secrets in the image — vault + runtime injection
[ ] Health-check endpoint configured
[ ] Rate limiting enabled
[ ] IP allow/deny rules where appropriate
[ ] Basic auth on non-public endpoints
[ ] Egress constrained with a network policy where needed
[ ] Rebuild/redeploy cadence to pick up patchesRelated
From the blog