Dockerfile Explained

Detailed breakdown of each instruction and how it fits as the final “container packaging” step in your Azure AKS deployment workflow.

Java 21 Spring Boot Container Image AKS

Dockerfile

Purpose: package target/app.jar into a runnable container
FROM eclipse-temurin:21-jre
WORKDIR /app
COPY target/app.jar /app/app.jar
EXPOSE 9087
ENTRYPOINT ["java","-jar","/app/app.jar"]

AKS Deployment Steps (bottom section)

Container Packaging Step

In an AKS workflow, everything before this produces the application artifact (app.jar). This Dockerfile is the final step that turns that artifact into a deployable container image.

Precondition
This Dockerfile assumes you already built the boot jar: mvn clean install produces target/app.jar.

Why it matters:
  • Docker image builds are deterministic only if the jar exists.
  • CI/CD pipelines typically run Maven first, Docker second.
  • Missing jar → build fails at COPY.
Build the image
Creates a local container image containing your application runtime + jar.
docker build -t aks-demo-ui:1.0 .
Output: an image tagged aks-demo-ui:1.0 on your machine (Docker Desktop).
Run locally (smoke test)
Validates the container starts and listens on the expected port.
docker run --rm -p 9087:9087 --name aks-demo-ui aks-demo-ui:1.0
If you can browse the UI and hit /actuator/health, the image is ready to push and deploy.

Line-by-line deep dive

Selects the container base image. This one provides a production-grade Java 21 runtime (JRE), which is enough to run your Spring Boot executable jar.

Why JRE (not JDK)?
You’re not compiling inside the container. The jar is already built by Maven, so the container only needs the runtime to execute java -jar.
Operational implication
Smaller image footprint than a full JDK image (typically), faster pull time, and less surface area than development toolchains.
Version alignment matters
Your POM compiles with Java 21. Using a Java 21 base image ensures runtime compatibility. A mismatch (e.g., build with 21 but run with 17) can crash at startup.

Sets the default working directory inside the image. All following file operations and commands use /app unless explicitly overridden.

Why it’s useful
  • Keeps application files organized under one directory.
  • Makes subsequent Dockerfile lines shorter and consistent.
  • Matches common conventions used in CI/CD and Kubernetes manifests.

Copies the built jar from your local build context (your project directory) into the container filesystem. This line is the “hand-off” between Maven output and the runnable container image.

Where it comes from
Your Maven build sets <finalName>app</finalName>, producing target/app.jar.
Common failure mode
If target/app.jar doesn’t exist, the Docker build fails at this step. Always run Maven first.
Why this is AKS-friendly
AKS runs containers, not jars. This line makes the jar portable as a container image that can be stored in ACR and pulled by Kubernetes nodes.

Declares that the containerized application listens on port 9087. This is primarily documentation/metadata for humans and tooling.

Important nuance
EXPOSE does not publish the port by itself. Publishing happens when you run: docker run -p hostPort:containerPort, and in Kubernetes via containerPort + Service/Ingress.
In AKS, this maps to: Deployment.containerPort: 9087 and a Service that targets that port.

Defines the default process executed when the container starts. Here, the container runs Java in “exec form” (JSON array), which is the recommended form for predictable signal handling and argument parsing.

Why exec-form matters
  • Signals (e.g., SIGTERM) reach the Java process properly.
  • Kubernetes can stop pods gracefully.
  • No shell interpolation surprises.
AKS shutdown behavior
When AKS terminates a pod, it sends termination signals; proper entrypoint helps Spring Boot shut down cleanly within the grace period.
What runs inside the container
One main process: java -jar /app/app.jar. Logs go to stdout/stderr, which is what Kubernetes expects for centralized log collection.

Recap

What this Dockerfile does
Takes a Spring Boot executable jar built by Maven and packages it into a runnable Java 21 container image.
Why it belongs at the bottom of AKS steps
AKS deploys images. This is the final transformation from “code + jar” into “deployable unit”.