spring boot, docker, kubernetes

In previous post, I’ve started a working Minikube on laptop. But the deployment used a prebuilt Node.js echo server image.

Here I will go through webapp built by Spring Boot, Docker image, and Kubernetes deployment/service configured via YAML.

First, make a simple webapp by Spring Boot. Any app would do. Here I just paste my sample app.

<!--pre class="wp-block-syntaxhighlighter-code brush: groovy; notranslate"-->plugins {
	id 'org.springframework.boot' version '2.1.6.RELEASE'
	id 'java'
	id 'io.freefair.lombok' version '3.8.0'
}

apply plugin: 'io.spring.dependency-management'

group = 'org.weidongxu.app'
version = '1.0.0'
sourceCompatibility = '1.8'

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}<!--/pre-->
<!--pre class="wp-block-syntaxhighlighter-code brush: java; notranslate"-->package org.weidongxu.app.codesharingapi;

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@SpringBootApplication
@RestController
public class CodeSharingApiApplication {

	public static void main(String[] args) {
		SpringApplication.run(CodeSharingApiApplication.class, args);
	}

	@GetMapping(
			value = "/",
			produces = MediaType.APPLICATION_JSON_VALUE
	)
	public List<CodeBlock&gt; get() {
		List<CodeBlock&gt; blocks = new ArrayList<&gt;(codeBlocks.values());
		blocks.sort((CodeBlock o1, CodeBlock o2) -&gt; Long.compare(o1.getModifiedTsMs(), o2.getModifiedTsMs()));
		return blocks;
	}

	@PostMapping(
			value = "/",
			consumes = MediaType.APPLICATION_JSON_VALUE,
			produces = MediaType.APPLICATION_JSON_VALUE
	)
	public CodeBlock post(@RequestBody CodeBlock codeBlock) {
		codeBlocks.put(codeBlock.getId(), codeBlock);
		return codeBlock;
	}

	@PostConstruct
	private void postConstruct() {
		CodeBlock codeBlock = new CodeBlock("print [0..]");
		codeBlocks.put(codeBlock.getId(), codeBlock);
	}

	private final ConcurrentMap<String, CodeBlock&gt; codeBlocks = new ConcurrentHashMap<&gt;();

	private static class CodeBlock {
		@Getter @Setter private String id;
		@Getter @Setter private String code;
		@Getter @Setter private long version;
		@Getter @Setter private long modifiedTsMs;

		public CodeBlock() {
			this.id = UUID.randomUUID().toString();
			this.version = 1L;
			this.modifiedTsMs = Instant.now().toEpochMilli();
			this.code = "";
		}

		public CodeBlock(String code) {
			this();
			this.code = code;
		}

		public CodeBlock(String id, String code, long version, long modifiedTsMs) {
			this.id = id;
			this.code = code;
			this.version = version;
			this.modifiedTsMs = modifiedTsMs;
		}
	}
}<!--/pre-->

Build it.

./gradlew build

Note Spring Boot uses port 8080 by default (it can be modified in application.properties).

Second, create Docker image for the webapp. Make sure docker command line is installed.

I will reuse docker daemon within Minikube VM. Before creating Docker image, start Minikube and source its docker env.

minikube start --image-mirror-country cn
eval $(minikube docker-env)

Create a Dockerfile for the webapp.

FROM openjdk:8-jre
VOLUME /tmp
COPY build/libs/*.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

Build Docker image.

docker build -t org.weidongxu.app/code-sharing-api:v1 .

Finally, create deployment and service on Kubernetes. This time I use YAML configuration file.

<!--pre class="wp-block-syntaxhighlighter-code brush: plain; notranslate"-->apiVersion: apps/v1
kind: Deployment
metadata:
  name: code-sharing-api
  labels:
    app: code-sharing-api
spec:
  replicas: 2
  selector:
    matchLabels:
      app: code-sharing-api
  template:
    metadata:
      labels:
        app: code-sharing-api
    spec:
      containers:
      - name: code-sharing-api
        image: org.weidongxu.app/code-sharing-api:v1
        imagePullPolicy: Never
        ports:
        - containerPort: 8080<!--/pre-->

Note that I am using docker daemon inside Minikube VM, hence imagePullPolicy: Never.

<!--pre class="wp-block-syntaxhighlighter-code brush: plain; notranslate"-->apiVersion: v1
kind: Service
metadata:
  name: code-sharing-api
  labels:
    app: code-sharing-api
spec:
  type: NodePort
  selector:
    app: code-sharing-api
  ports:
  - protocol: TCP
    nodePort: 30001
    port: 8080
    targetPort: 8080<!--/pre-->

And call kubecrl to create the deployment and service.

kubectl create -f k8s-deployment.yaml
kubectl create -f k8s-service.yaml
Advertisements
This entry was posted in Cloud, Computer and Internet and tagged . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s