Application containerization
Application containerization: package Java apps so they run the same everywhere.
Containerizing a Java application is easy to start and easy to do badly. The details are memory, configuration, health and shutdown.
The short answer
Application containerization packages an application and its runtime into an image that runs the same on a laptop, in CI and in production. For Java it means a current JDK, a small base image, JVM settings that respect container memory, external configuration and health checks. Ace8 containerizes after the Java upgrade, so the image is built on a supported runtime.
Sequence
Should you containerize before or after upgrading Java?
After, in most cases. Old runtimes handle container memory limits poorly, and an image built on an end-of-life JDK carries its vulnerabilities into every environment. Upgrade first (see Java upgrade), get tests passing, and then package. If the application sits on an app server such as WebLogic, the app server exit usually comes before the image, because you would otherwise package the server and its licence into every container.
Checklist
What has to change in a Java app to run well in a container?
| Area | Typical problem | What we do |
|---|---|---|
| Memory | JVM sized for the host, then killed by the container limit | Use a container-aware JDK and set heap as a percentage of the limit, for example MaxRAMPercentage |
| Configuration | Properties files baked into the image | Read from environment variables, config maps and secrets |
| State on disk | Uploads or temp files written locally | Move to object storage or a volume, or make them disposable |
| Sessions | Sticky sessions in server memory | External session store, or stateless design |
| Logging | Logs written to files | Write to standard output and let the platform collect it |
| Health | No way to tell ready from alive | Add liveness and readiness endpoints |
| Shutdown | Requests cut off when the pod stops | Handle SIGTERM and drain in-flight requests |
| Security | Running as root, full OS in the image | Non-root user, minimal base, scanned image |
Build
How should the image be built?
Use a supported base such as a slim JRE or distroless image rather than a full JDK on a general OS. Build in stages, so build tools stay out of the final image. For Spring Boot, use layered jars so dependencies, which rarely change, sit in a cached layer apart from application code. Cloud Native Buildpacks and Jib build such images without a Dockerfile, and a hand-written Dockerfile is fine when you need control.
Pin base image versions, rebuild on a schedule to pick up patches, and scan every image in the pipeline.
Measure
What should you measure before and after?
Image size and startup time are the two figures that show whether the work was done well. The ranges below are typical and illustrative, not a result from our own runs. They vary with the application, the base image and the JDK.
| Measure | Naive image (illustrative) | Tuned image (illustrative) |
|---|---|---|
| Image size | Around 400 to 600 MB, full JDK on a general OS | Around 150 to 300 MB, slim JRE with layers |
| Startup | Tens of seconds for a large Spring app | Often several seconds shorter with class data sharing and trimmed dependencies |
| Memory behavior | Killed on limit, unpredictable | Stable under a set limit |
Scope
What is containerization, and what is it not?
Containerization is packaging. It does not make an application cloud-native by itself. A monolith in a container is still a monolith, with the same release and scaling limits. That is fine, and often the right first step. Splitting is a separate decision; see monolith to microservices.
The same applies to Kubernetes. Running containers on an orchestrator brings scheduling, networking and configuration questions of its own, covered under Kubernetes replatforming.
Tools
Can tools containerize an application for you?
Some. Assistants can draft Dockerfiles and flag problems like local file writes. Konveyor analyzes applications for container readiness. They give a starting point and miss the behavior that only shows under load, such as memory limits and shutdown. An engineer reviews the output and the application is load tested in the container before it ships. See AI-assisted modernization.
After
Who supports the containers after go-live?
Packaging is the easy half. Running it means patching base images, watching resource use and handling incidents. AceMQ supports the new stack 24/7 after go-live; see supported after migration. Before any of this, the modernization assessment tells you which applications are ready to be packaged, and which need work first. For the full service set, see application modernization services.
It packages an application with its runtime and dependencies into an image that runs the same way in any environment that supports containers.
Upgrade to a supported JDK, build a small image with a slim base and layered jars, read configuration from the environment, log to standard output, add health endpoints and handle SIGTERM.
Usually yes. Older JDKs handle container memory limits poorly and carry known vulnerabilities into the image.
No. Containerization is packaging. A monolith can run in a container. Splitting into services is a separate architectural decision.
No. Containers run on a single host or a managed service. Kubernetes helps when you run many containers and need scheduling and scaling.
Often yes, after removing local file state, sticky sessions and app server dependencies. The assessment lists what blocks each application.
Know the cost before anything moves.
A fixed-price assessment gives you the inventory, the risk score and a phased plan. Scope and cost are fixed before the migration starts.
Book a Fixed-Price AssessmentGet in touch
Talk to a modernization engineer
Tell us what you run today. An engineer, not a sales script, replies within one business day.