Deploying Java Applications on Kubernetes: From Dockerfile to a Working Service
\n\nModern Java development is unthinkable without containerization and orchestration. Kubernetes (K8s) has become the standard for managing microservices, and the ability to deploy Java applications in a cluster is a mandatory skill for a backend developer. In this article, we will walk through the complete deployment cycle in practice: from building a Docker image with a Java application to configuring load balancing via Ingress.
\n\n1. Preparing the Java Application and Dockerfile
\n\nBefore getting into Kubernetes, your Java application must be packaged into a Docker image. Let's consider a classic case — a Spring Boot application built into a JAR file.
\n\nBuilding the Project
\nSuppose we have a project that is built using Maven. Run the command in the project root:
\nmvn clean package -DskipTests\nAs a result, the file my-app-1.0.0.jar will appear in the target/ folder.
Creating a Dockerfile
\nTo minimize the image size and increase security, we use a multi-stage build.
\n# Stage 1: build\nFROM maven:3.8.6-openjdk-17 AS builder\nWORKDIR /app\nCOPY pom.xml .\nRUN mvn dependency:go-offline -B\nCOPY src ./src\nRUN mvn package -DskipTests\n\n# Stage 2: final image\nFROM openjdk:17-jdk-slim\nWORKDIR /app\nCOPY --from=builder /app/target/my-app-1.0.0.jar app.jar\nEXPOSE 8080\nENTRYPOINT ["java", "-jar", "app.jar"]\n\nBuilding and Publishing the Image
\ndocker build -t my-java-app:1.0.0 .\ndocker tag my-java-app:1.0.0 your-dockerhub/my-java-app:1.0.0\ndocker push your-dockerhub/my-java-app:1.0.0\n\n2. Creating Kubernetes Manifests
\n\nKubernetes uses a declarative approach. We will describe the desired state of the system in YAML files.
\n\nDeployment — Managing Pods
\nCreate a file deployment.yaml:
apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: java-app-deployment\n labels:\n app: java-app\nspec:\n replicas: 3\n selector:\n matchLabels:\n app: java-app\n template:\n metadata:\n labels:\n app: java-app\n spec:\n containers:\n - name: java-app\n image: your-dockerhub/my-java-app:1.0.0\n ports:\n - containerPort: 8080\n resources:\n requests:\n memory: "256Mi"\n cpu: "250m"\n limits:\n memory: "512Mi"\n cpu: "500m"\n livenessProbe:\n httpGet:\n path: /actuator/health\n port: 8080\n initialDelaySeconds: 30\n periodSeconds: 10\n readinessProbe:\n httpGet:\n path: /actuator/health\n port: 8080\n initialDelaySeconds: 20\n periodSeconds: 5\n\nService — Providing Access
\nCreate a file service.yaml:
apiVersion: v1\nkind: Service\nmetadata:\n name: java-app-service\nspec:\n selector:\n app: java-app\n ports:\n - protocol: TCP\n port: 80\n targetPort: 8080\n type: ClusterIP\n\nConfigMap — Externalizing Configuration
\nTo store environment variables, create configmap.yaml:
apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: app-config\ndata:\n SPRING_PROFILES_ACTIVE: "prod"\n DB_URL: "jdbc:postgresql://postgres-service:5432/mydb"\n\n3. Deploying to the Cluster and Verification
\n\nNow let's apply all manifests to the cluster. Make sure you have kubectl configured and are connected to the correct context.
Applying Manifests
\nkubectl apply -f configmap.yaml\nkubectl apply -f deployment.yaml\nkubectl apply -f service.yaml\n\nChecking Status
\nkubectl get pods\nkubectl get deployments\nkubectl get services\nYou should