Back to Blog

Container Security Best Practices: A Complete Guide

Will

August 17, 202614 min read

Container Security Best Practices: A Complete Guide

Make container security best practices part of your team's workflow, instead of just getting attention when something goes wrong: a critical vulnerability in a production environment turning up in a scan, an audit flagging a container running as root, or a compromised container making it all the way to a customer-facing service.

This guide helps you improve your container security, with specific practices that apply to any container, from the image you build to the network policy that contains a breach, as well as dedicated sections on the details specific to Docker and to cloud environments.

Some of this you can start today with a config change; some changes need a scanning tool or a small addition to your CI/CD pipeline, while a couple need buy-in from whoever owns your infrastructure decisions.

What are container security best practices?

Container security best practices are the specific configurations, tools, and habits applied across the container lifecycle – covering build, ship, and run – that reduce your attack surface and catch host or container vulnerability issues before they become incidents.

Here's one structural fact about containers: every container on a host system shares that host's kernel. A gap in any one layer, whether that's the image, the runtime configuration, or the network, doesn't stay contained to that layer and can expose the host system and every other container running on it.

The operating system underneath your containers needs the same attention as the containers themselves, as host and container vulnerabilities usually show up together, not as separate problems to solve one at a time.

A traditional security tool designed for long-lived servers or virtual machines assumes a stable target you patch, monitor, and move on from.

Containers, by comparison, are ephemeral, built and torn down constantly, and a single application might run across dozens of short-lived instances in a day.

To apply container security effectively, you need to adapt your existing security measures to that pace, not just run the same checks less often.

In this guide, we run through the key components of the container security model – image integrity, runtime restrictions, network segmentation, and access control – along with Docker-specific and cloud-specific details that change depending on where you deploy.

Build and secure your container images

Every layer of container security you add later is compensating for problems that could have been avoided when you built your container images in the first place. How you apply container security in practice depends on your setup, but a smaller, cleaner image is the right starting point regardless of container architecture.

Start from minimal base images

A full operating system base image ships with a package manager, shell utilities, and operating system packages your application will never touch – every one of which is something a container vulnerability scanner has to check and something an attacker could potentially use once they're inside.

Minimal base images, distroless images, or a self-contained executable image built from a language runtime like Go strip that surface down to what the application genuinely needs.

Use multi-stage builds

Compiling code and installing package management tools needs a full build environment, but none of that belongs in the image you actually deploy.

A multi-stage Dockerfile keeps the build tools in an early stage and copies only the finished artifact into a minimal final image:

FROM golang:1.22 AS build

WORKDIR /src

COPY . .

RUN CGO_ENABLED=0 go build -o /app

FROM gcr.io/distroless/static-debian12

COPY --from=build /app /app

USER nonroot:nonroot

ENTRYPOINT ["/app"]

The final image here has no shell, no package manager, and no build tools left inside it, only the compiled binary and a non-root user to run it.

Sign your images and verify image signatures

A container image base distribution pulled from a compromised registry, or intercepted over a remote network connection, can carry malicious code without any visible difference from a clean image.

Image signing, using a tool such as Sigstore's cosign and a loaded private key at build time, attaches a cryptographic signature to an image.

Verify that signature before deployment to confirm the image actually came from your pipeline and wasn't tampered with along the way, as this will prevent attacks that try to overwrite remote trust data.

Scan images at every stage, not just once

Container image scanning that happens once, at build time, catches known issues in that moment, but new container vulnerabilities get disclosed in operating system packages and dependencies long after an image has already shipped.

Continuous scanning is worth the effort: the Sysdig 2026 Cloud-Native Security and Usage Report found that the share of running container images carrying a known, exploited vulnerability dropped nearly 75% year over year.

Sysdig 2026 Cloud-Native Security and Usage Report chart

Run a container image scan again before a registry push, once again before deployment, and periodically against images already running in production, so tools that analyze container images can catch existing and future vulnerabilities rather than just the ones known on day one.

Together, these four practices are what it takes to secure container images before they ever reach a production environment.

Integrate code scanning tools into the software development lifecycle

You scan a container image after code is packaged, but you can catch problems before they ever reach a Dockerfile if you act a layer earlier in the software development lifecycle (SDLC).

What static application security testing catches

Static application security testing (SAST) analyzes your own source code for potentially exploitable code: SQL injection risks, hardcoded credentials, insecure deserialization, and similar issues that a manual review can miss under deadline pressure.

Integrating code scanning tools into your existing CI/CD pipeline means every pull request gets checked automatically, rather than depending on someone remembering to run a scan before a release.

Why dependency scanning is a separate step

Most applications pull in far more third-party code than they write themselves. Dependency scanning checks those packages against known vulnerability databases, helping you detect vulnerable components before they end up compiled into a running image.

SAST and dependency scanning cover different risks. One looks at code you wrote; the other looks at code you didn't write but are still responsible for running.

Run both container scanning tools and code-level checks on every commit, rather than treating either as a one-off audit.

Fixing a flagged issue at this stage costs a few minutes and a code review comment. Fixing the same issue after it's shipped, been scanned, and turned into one of the security incidents your team has to write up costs considerably more – in time, in resources, in trust, and sometimes in the scope of the breach itself.

Restrict container privileges and lock down the security context

A vulnerability that gets past image scanning and code review still has to be exploited once it's running.

Restricting container privileges limits how much damage a container can cause even if an attacker gets code execution inside it.

Run as non-root and drop unneeded capabilities

To restrict user access, start by not running your application as root inside the container. Pair that with dropping Linux capabilities your container doesn't need, since a default container often gets more capabilities than it will ever use.

A security context that denies privilege escalation, drops all capabilities by default, and only adds back what's genuinely required cuts off one of the more common paths to a container escape:

securityContext:

  runAsNonRoot: true

  allowPrivilegeEscalation: false

  capabilities:

    drop: ["ALL"]

  readOnlyRootFilesystem: true

That same configuration sets a read-only root filesystem: a simple default that blocks a whole category of runtime tampering for application containers that don't need to write to their own filesystem.

Use standard kernel security mechanisms

Beyond the container configuration itself, standard kernel security mechanisms add another layer at the operating system level.

Seccomp profiles restrict which system calls a container's process is allowed to make, blocking entire classes of exploit that rely on syscalls a typical web application never needs.

AppArmor or SELinux, depending on your host operating system, add mandatory access control on top of that, restricting what files and resources a process can access regardless of what the container image itself allows.

Set resource limits

Resource limiting CPU usage and memory isn't only a stability measure. An unbounded, compromised container can be used to exhaust a host system's CPU and hardware virtualization resources, starving other containers or acting as a base for further attacks like cryptomining.

Setting explicit CPU and memory limits on every container keeps one misbehaving container from taking the rest of the host system down with it.

Runtime security and continuous monitoring

Everything covered so far happens before or at the moment a container starts. Runtime security covers what happens once running containers are actually live and handling real traffic.

Detect behavior, not just known vulnerabilities

A compromised container doesn't always look different from the outside.

Image scanning can catch known vulnerabilities, but runtime security tools watch what a running container actually does – which processes it spawns, which files it touches, which network connections it opens – and flag behavior that doesn't match what that container should be doing.

If a web server suddenly starts spawning a shell or scanning your internal network, it's a signal no static scan would have caught ahead of time. The image itself might have looked clean.

Watch for configuration drift

Continuous monitoring also covers configuration, not just behavior.

A secure container environment that started out locked down can drift back toward a default insecure configuration over time: a capability re-added to unblock a feature, a network rule loosened to fix a connectivity issue and never tightened again.

Runtime visibility has become mainstream for exactly this reason: more than 70% of organizations now use behavior-based detection, per the same Sysdig report cited above.

Sysdig 2026 Cloud-Native Security and Usage Report stateful detections chart

Regular audits against your own baseline, backed by automated runtime monitoring, catch this kind of drift before it becomes the gap an attacker finds first.

Treat runtime alerts as part of the pipeline, not a side channel

A runtime alert that only reaches a security team's dashboard, with no path back to the engineers who own the service, tends to sit unresolved.

Feeding runtime findings back into the same tracking and CI/CD pipeline used for other bugs keeps them from becoming a permanent backlog nobody owns.

Network policies and role-based access control

Image and runtime controls protect a single container. Network policies and access controls protect everything around it, governing what a container can reach and who can change it.

Default to blocking unnecessary network traffic

Most container platforms default to open networking: any container can reach any other container unless you say otherwise. That default favors convenience over security.

Network policies that block unnecessary network traffic by default, and only allow the specific connections a service genuinely needs, prevent a compromised container from moving laterally to whatever else happens to be reachable.

Combine this default setup with deployment checks that block unsafe containers from ever starting in the first place, rather than relying on someone catching a bad configuration during a manual review.

Set the allow list up per service rather than as a blanket rule you have to remember to tighten later.

Apply role-based access control everywhere it's relevant

Role-based access control (RBAC) governs who can deploy a service, view logs, manage a registry, or touch production secrets, scoped to what someone's actual role requires rather than an all-or-nothing account.

Running containers safely, adhering to the principle of least privilege, is just as relevant to internal access as it is to the containers themselves. A contractor with full production access because nobody scoped their permissions down is a security and compliance risk, even if every container involved is perfectly configured.

Keep an audit trail

Access controls only tell you who's allowed to do something.

A record of deployments, permission changes, and access to sensitive data gives you something to review during a routine check and something to work from if you ever do need to investigate an incident.

Docker container security best practices

The practices above apply across container technologies, but Docker has its own tooling and configuration details to be aware of.

Benchmark your setup against the CIS Docker Benchmark

The Center for Internet Security (CIS) publishes a Docker Benchmark: a documented container runtime benchmark control set covering host configuration, the Docker daemon, container images, and runtime settings.

Docker Bench for Security is an open-source script that checks a host system against that benchmark automatically, giving you a concrete list of configuration or protection measures to fix rather than a vague sense that something might be off.

Harden the Docker daemon itself

The Docker daemon, which manages the container runtime on a given host, runs with more privilege than any single container it manages, making it a high-value target.

Keep it patched, avoid exposing the Docker socket over the network without authentication, and consider rootless Docker mode, which runs the daemon and containers under an unprivileged user instead of root. 

That one change removes a large proportion of what a container escape could actually reach on the host system.

Move from Docker Content Trust to Cosign or Notation

Docker Content Trust was Docker's own implementation of the image-signing practice we covered earlier. When enabled, it enforced signature verification at pull time, so a pull of an unsigned image simply failed.

However, Docker has retired the feature, with the underlying Notary v1 service shutting down on December 8, 2026, and the feature itself removed on April 1, 2027.

If you have DOCKER_CONTENT_TRUST=1 set anywhere in your environment or CI pipelines, remove it now – leaving it in place will cause image pulls to fail.

For signing going forward, the ecosystem has settled on two OCI-native tools: Sigstore's Cosign and the Notary Project's Notation.

Both store signatures alongside the image in any compliant registry, with no separate trust infrastructure to run. Cosign supports keyless signing tied to CI identities, which makes it a popular choice for automated pipelines, while Notation suits teams that prefer managing their own certificates. Either way, you get the same guarantee Docker Content Trust offered – verified, tamper-free images – built on tooling that's actively maintained.

Watch registry configuration specifically

A private registry that's misconfigured, whether public read access has been left on by accident or credentials have been shared more broadly than they should be, undoes a lot of the other Docker container security best practices in one fell swoop.

Treat registry access with the same rigor as production infrastructure access. Essentially, it is production infrastructure access.

Cloud container security best practices

Running containers on a cloud platform adds a layer that doesn't exist when you're managing your own hardware: a shared responsibility model that splits security work between you and the provider.

Know where the shared responsibility line sits

Under the shared responsibility model, a cloud provider typically secures the physical infrastructure, the host virtualization layer, and the managed control plane of any container service you use.

Everything above that remains your responsibility: your image contents, your runtime configuration, your network policies, and your access controls.

Misreading that division is one of the more common sources of cloud container security and compliance risks, since teams sometimes assume a managed service handles more than it actually does.

Self-hosting shifts more onto you

Self-hosting on your own server or VPS moves that line further in your direction. You're also responsible for the host operating system, keeping it patched, and configuring the container runtime itself, rather than inheriting that layer from a provider.

Don't avoid self-hosting for this reason, but be conscious that it means that container security best practices for a fully managed platform and for a self-hosted setup aren't the same.

Use cloud-native scanning and identity tools

Most cloud providers offer native registry scanning and identity and access management (IAM) roles that can be scoped tightly to a single service rather than an entire account.

Using these vulnerability scanners alongside the practices covered earlier, rather than instead of them, closes gaps that a generic scanner running outside the cloud platform might miss, like an overly permissive default network rule in a managed Kubernetes service.

Don't assume defaults are secure

Cloud platforms are built for ease of use first and foremost, which means plenty of useful configuration or protection measures exist but aren't switched on by default. Review default network rules, storage permissions, and IAM policies against your own baseline, rather than assuming the provider's defaults already reflect a secure container environment.

Benchmarks and vulnerability scanning tools

As well as implementing the security best practices above, you can use benchmarks and scanning tools to check whether you are actually doing it consistently, across every container you run.

What a benchmark actually checks

The National Institute of Standards and Technology (NIST) SP 800-190 and the CIS Benchmarks each define a documented set of configuration checks covering the image, the registry, the container orchestrator, and the host system.

Rather than a general best-practices opinion, these are specific, testable controls:

  • Is the container running as root?
  • Is an API exposed without authentication?
  • Is a capability present when it shouldn't be?

Testing your setup against these questions gives you a concrete pass or fail list instead of a guess.

Where a vulnerability scanner fits in

A container vulnerability scanner checks images and running containers against known vulnerability databases, flagging anything with a matching CVE. It's a verification tool, not a replacement for the practices covered earlier.

A scanner will tell you an image has a known issue, but it won't restrict container privileges, segment your network, or enforce RBAC for you. Treat scanning as the audit layer sitting on top of everything else, catching what slipped through and confirming what didn't.

Incident response basics

Even a well-configured container environment eventually deals with a flagged vulnerability or a suspicious container. How well that goes usually comes down to preparation you do before the incident, not decisions you make during it.

Write the runbook before you need it

Decide in advance which container images get rebuilt rather than patched live when a vulnerability is confirmed. A container is meant to be immutable, and patching a running one tends to create more uncertainty than it resolves.

A short, specific runbook that says who gets notified, who has authority to isolate a container, and where the rebuilt image gets deployed from saves time.

Review access logs as a standing habit

Don't wait for an incident to look at your access logs. Reviewing them on a regular schedule, not just after something's gone wrong, surfaces a misconfigured role or an unused, over-permissioned account before it causes an investigation to take longer than it should.

Test the plan

Test your runbook through the response steps against a simulated compromised container, even briefly, to surface the gap between what the plan assumes and what actually happens when someone's paged about a security incident in the middle of the night.

Where Dokploy fits into your container security strategy

A deployment platform doesn't replace any of the scanning or runtime tools covered above, but it does determine how much of the access-control and configuration work happens by default versus needing a separate policy engine bolted on.

Dokploy's role-based access control scopes who can deploy, access a server, or view project data down to individual projects and environments, which covers a meaningful share of the access-control practices above without extra tooling.

Environments isolate a project's staging and production services from each other, and environment variables are kept separate from build-time secrets by design, so a credential doesn't end up baked into an image layer by accident.

On Dokploy Enterprise, audit logs add the access trail covered in the RBAC section above, and a container registry integration lets you connect to any Docker registry once, at the organization level, and reuse those credentials across every project and server instead of storing them locally on each machine.

None of that replaces a vulnerability scanner or a runtime threat-detection tool, and it isn't meant to. Instead, it removes a layer of manual setup from the practices that are mostly about configuration and access, so the tools you add on top are working on top of a reasonably secure container environment instead of compensating for a missing one.

Conclusion

Container security best practices aren't a single checklist you finish once. They're a set of habits spread across the image you build, the privileges a container runs with, the network it can reach, and the access controls around all of it, checked continuously.

Get the fundamentals right and everything downstream gets easier:

  • Images that are minimal, signed, and scanned on a schedule.
  • Containers that run with only the privileges they actually need.
  • Network rules that assume nothing should reach anything else by default.
  • Access controls that make it obvious who did what.

If you want a foundation that handles a meaningful share of that access-control and configuration work by default, you can sign up for Dokploy and see how it scopes RBAC, isolates environments, and keeps secrets out of your image layers for every project you deploy.

Container security best practices FAQs

How often should you scan container images?

Scan at build time, again before a registry push, and on a recurring schedule for anything already running in a production environment, since new vulnerabilities get discovered in existing operating system packages long after an image has shipped. A weekly scan of production images is a reasonable minimum for most teams. Scan anything handling sensitive data daily.

Do container security best practices differ for Kubernetes versus standalone Docker?

The core practices, like minimal images, non-root containers, network segmentation, and resource limits, apply to both.

Kubernetes container security best practices include the layer it adds on top – including pod security standards, namespace-level RBAC, and cluster-wide network policies – that don't have a direct equivalent in a standalone Docker setup running a handful of containers on one server.