Skip to content
Securely manage Docker, Swarm, Kubernetes and Podman clusters in the cloud, on-premise, and in the data center.
Secure app deployment and device management for your Industrial IoT, IoT and Edge devices.
Let Portainer's Managed Platform Services accelerate your containerization journey.
A fully integrated, multi-cluster Kubernetes platform that’s scalable, secure and supported.
Deployment scenarios
Partner Solutions (Hybrid Cloud)
Onboard, manage and deploy workloads across hundreds of devices securely with Portainer.
Deployment scenarios
Partner Solutions (Edge/IIoT)
Portainer teamApril 22, 20254 min read

Migrating a JVM-Based SOA App from VMs to Containers (and Then Orchestrating with Kubernetes)

So, you have a legacy Java-based application running on aging virtual machines, and you want to move it into containers and deploy it on Kubernetes. You're not alone.

We’re helping a customer do exactly that: transitioning a sprawling, service-oriented Java application into a modern, containerized environment orchestrated by Kubernetes. This is more than a technical refresh; it's a full operational and architectural shift.

If you're planning a similar journey, here are the high-level steps we're following, including insights from our DevOps transformation work and containerization readiness checklist.


Step 1: Understand the Existing Application

Before you write a single line of Dockerfile, you need a full understanding of how each service works.

Document:

  • How each service starts, runs, and shuts down

  • All runtime dependencies (files, databases, queues, other services)

  • Communication methods (HTTP, gRPC, shared libraries, IPs, FQDNs)

  • Environment assumptions (ports, paths, memory settings)

  • State management (what state exists, where it's stored)

Build a clean inventory of your service-oriented architecture so you can scope and sequence the transformation.


Step 2: Create Dockerfiles for Each Service

Encapsulate each service's runtime environment using a Dockerfile. Consistency matters.

For Spring Boot apps:

FROM eclipse-temurin:17-jdk
WORKDIR /app
COPY ./target/my-service.jar app.jar
CMD ["java", "-jar", "app.jar"]

For WAR/EAR apps, you'll need appropriate base images (such as Tomcat or WebLogic) and custom entrypoints.

Use official base images or vendor-supported options. Avoid unmaintained or custom community images.


Step 3: Externalize Configuration

Hardcoded values are a container anti-pattern. Externalize settings like DB credentials, API endpoints, and feature flags using environment variables or mounted config files.

Design your containers to read from their environment. This ensures portability and prepares them for ConfigMaps and Secrets in Kubernetes.


Step 4: Build and Test Locally

Test each container in isolation and with others using docker-compose. Validate:

  • Clean startup and shutdown

  • Dependency connectivity

  • Statelessness and restart behavior

  • Logging to stdout/stderr

  • Runtime configuration injection

This gives you confidence before layering on orchestration.


Step 5: Handle State Properly

Containers are ephemeral. If your services write to disk, re-architect them to use mounted volumes or external storage.

Watch for legacy behaviors like sticky sessions or shared directories. Kubernetes will not tolerate them well.


Step 6: Create Kubernetes Manifests

For each service, create:

  • Deployment to define replicas and rolling updates

  • Service to enable internal discovery

  • Ingress to expose endpoints externally

  • ConfigMap or Secret to provide externalized settings

  • Probes for health and readiness

This is where you codify your deployment model. If you're using GitOps, this is your source of truth.


Step 7: Deploy to Kubernetes

Push images to a container registry. Deploy manifests into a Kubernetes cluster. Start small:

  • Deploy one or two services

  • Verify behavior, connectivity, and logs

  • Scale incrementally

Use kubectl to monitor pods, logs, and deployments. Tools like Portainer can simplify visibility and governance.


Step 8: Configure Probes for Health Management

Enable Kubernetes to self-heal and manage availability.

  • Liveness probes restart crashed containers

  • Readiness probes gate traffic until services are ready

Use endpoints like /actuator/health or custom health checks.


Step 9: Scale and Operate

With your services running in Kubernetes:

  • Use Horizontal Pod Autoscaler for demand-based scaling

  • Use rolling updates for zero-downtime deployments

  • Integrate CI/CD pipelines for continuous rollout

  • Use observability tools such as OpenTelemetry, Grafana, and Portainer for full visibility

You are no longer maintaining pets. You are managing cattle: scalable, reproducible, and observable units of compute.


Step 10: Update CI/CD and DevOps Practices

Migrating to containers and Kubernetes is also a cultural and workflow shift. Your CI/CD and DevOps processes need to evolve to support the new reality.

  • Replace manual deployments with Git-based automation and GitOps workflows
  • Break down large, brittle pipelines into modular build, test, scan, and deploy stages
  • Use container-native CI pipelines to build, test, and scan images consistently
  • Integrate security tools such as SAST, DAST, and container scanning into the pipeline
  • Shift infrastructure configuration and deployment logic into source-controlled repositories.

Step 11: Revisit Git and Branching Strategy

Legacy version control patterns often don't translate well to modern, CI-driven workflows.

  • Use short-lived feature branches with automated PR checks and approvals
  • Establish clear naming conventions and branching policies
  • Protect mainline branches with merge checks, approvals, and quality gates
  • Encourage trunk-based development wherever feasible for fast feedback and reduced merge debt

A clean, scalable Git strategy is foundational to everything from automation to auditability.


Key Readiness Items to Keep in Mind

As part of our containerization readiness checklist, ensure:

  • Dockerfiles use supported base images and multi-stage builds

  • Configuration is externalized

  • Logging is standardized

  • CI/CD pipelines are integrated

  • Secrets are handled securely

  • Containers are stateless

  • Probes are defined and tuned


Need Help?

This is a bird’s eye view of the journey. We’ve helped organizations modernize ERP systems, Java SOA estates, and everything in between.

If you're looking to skip the trial and error and accelerate with confidence, the Portainer Managed Services team is here to help. We bring the tools, templates, and experience needed to modernize your apps and get them production-ready on Kubernetes.

Let’s talk.

 

avatar

Portainer team

Portainer Team

COMMENTS

Related articles