Container Security: Shipping Spring Applications to Production

Container security for Java/Spring applications: non-root users, minimal base images, image scanning, secret management, read-only filesystems and deployment discipline.

Dockerfile editor window showing a secure multi-stage Java image

Where does container security begin?

Container security begins not in Kubernetes but on the first line of the Dockerfile: the base image choice, the runtime user and every layer that enters the image define your production attack surface. The good news for Java/Spring applications: secure container practice consists of a small set of clear, automatable rules. This article collects them.

Base images: small surface, few vulnerabilities

Full-OS images carry hundreds of packages your application never uses — along with their vulnerabilities. For Java, the right direction is minimal base images: official JRE-only images or the distroless approach. The second rule is version discipline: reference the base image not as latest but pinned by version + digest — builds become reproducible and image updates become deliberate decisions. Multi-stage builds keep the JDK and build tooling out of the production image.

Non-root user: a one-line change with large effect

Running the application as root inside the container makes an attacker's life easier in container-escape scenarios and filesystem manipulation. Creating a dedicated user in the Dockerfile and switching with USER costs nothing for most applications. Its companions: mounting the root filesystem read-only (with dedicated writable volumes for directories that need writes) and disabling privilege escalation. Spring applications run fine under these constraints; needs like temp directories are defined deliberately.

Secrets: into the runtime, never into the image

Everything that enters image layers is permanent: a password set via ENV in the Dockerfile, an API key in a copied config file — readable by anyone who pulls the image. The rule is strict: secrets never enter the image. They are provided at runtime — the orchestrator's secret mechanism, external vault solutions, or the cloud provider's secret services. Part of the same discipline: never pass secrets as build args, which can also leave traces in image history.

Image scanning: the closing step of CI

Scanning application dependencies is not enough; the base image's OS packages carry vulnerabilities too. Image scanning with tools like Trivy or Grype must be a mandatory CI step, with deployment blocked on critical findings. Its complement is image signing: accepting only CI-built, signed images into production is the container leg of supply chain defense.

The JVM and resource limits: Java at peace with containers

Modern JVMs recognize container resource limits and size memory accordingly; still, the memory limit and JVM heap configuration must be planned together — a container exceeding its limit is terminated by the orchestrator, which is an availability incident even when it is not a security one. Resource limits are also a security control: an unbounded container, once compromised, starves its neighbors.

Network and observability: the final layer

Traffic between containers should not be open by default; network policies should define only the required service-to-service paths. Logs are collected centrally, never kept inside containers. Health/readiness endpoints are exposed to the orchestrator only — the Spring Actuator rules we covered earlier apply unchanged in the container world.

Business impact: deployment discipline produces trust

Enterprise cloud security assessments now ask about image provenance, scanning process and secret management; in regulated sectors these become contract annexes. A vendor that can document signed images, scan reports and a secret policy shortens production-access debates. Container discipline delivers auditability without giving up DevOps speed — this is where velocity and trust are sold together.

Frequently asked questions

Should I use Alpine-based images?

The size advantage is real; but the different C library (musl) can surprise some Java workloads. Minimal JRE images or distroless are usually the more predictable balance for Java.

How often should I rebuild images?

Taking base image updates on a regular cadence (e.g. weekly) plus unscheduled rebuilds on critical advisories is a healthy rhythm; digest pinning turns this into a deliberate process.

Are environment variables safe for secrets?

File-based secret mounts or vault integration expose a smaller leak surface than environment variables (env dumps, error reports). If env vars are used, masking in logging and error reporting is mandatory.

JDK or JRE inside the container?

Production should contain only what is needed to run: a JRE (or a custom runtime built with jlink). The JDK and build tools stay in the first stage of a multi-stage build.

Container security checklist

  1. Minimal base image; pinned by version + digest

  2. Multi-stage build; runtime only in the production image

  3. Non-root user; read-only root filesystem

  4. Secrets outside the image; provided at runtime

  5. Image scanning in CI; deployment blocked on critical findings

  6. Image signing with verification in production

  7. Resource limits and network policies defined

SSH Yazılım provides secure containerization, CI/CD hardening and deployment security consulting for Java/Spring workloads. Let us review your delivery pipeline together.