本文讲述如何在Docker和Kubernetes中部署 SpringBoot 应用。
创建 SpringBoot 应用
使用idea创建一个简单的SpringBoot应用。
package com.wyk.k8sDemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
在其中添加一个简单的web页面。
package com.wyk.k8sDemo.web;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/")
public String index() {
return "Hello Kubernetes";
}
}
本地运行,查看程序是否有问题。访问 http://localhost:8080 。

添加 Docker 支持
修改项目的pom.xml,添加docker插件 dockerfile-maven-plugin。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wyk</groupId>
<artifactId>k8sdemo</artifactId>
<version>1.0-SNAPSHOT</version>
<name>A custom project </name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.10</version>
<configuration>
<repository>${project.artifactId}</repository>
<contextDirectory>./</contextDirectory>
<tag>${project.version}</tag>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>
这里需要注意的是需要将com.spotify添加到Maven的配置文件setting.xml的白名单值中才可以使用。
<pluginGroups>
<pluginGroup>com.spotify</pluginGroup>
</pluginGroups>
添加 Dockerfile
在SpringBoot应用的根目录下创建文件Dockerfile并添加如下内容。
# 基础镜像
FROM openjdk:8-jdk-alpine
# 对应pom.xml文件中的dockerfile-maven-plugin插件buildArgs配置项JAR_FILE的值
ARG JAR_FILE
# 复制打包完成后的jar文件到/opt目录下
COPY ${JAR_FILE} /opt/app.jar
# 启动容器时执行
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/opt/app.jar"]
# 使用端口8080
EXPOSE 8080
文件的大致含义为:本镜像基于openjdk:8-jdk-alpine镜像创建,然后获取pom.xml中的JAR_FILE参数,即生成的jar包文件名),并将该jar包拷贝至/opt/app.jar,然后在容器启动时执行java命令启动jar包。最后暴露8080端口,用于后面进行映射,访问SpringBoot应用。
部署SpringBoot 应用至 Docker
启动Docker Quick Start Terminal打开Docker,等待容器启动成功。需要注意的是Docker虚拟机的IP,后面访问应用会用到。

将目录切换到SpringBoot应用的根目录,执行如下命令。
mvn clean package docker:build
这里如果没有修改前面的maven配置文件,就会运行失败,报错如下。
[ERROR] No plugin found for prefix 'docker' in the current project and in the plugin groups...
改了之后,还是报错。。。
[ERROR] ... Exception caught: Must specify baseImage if dockerDirectory is null -> [Help 1]
好像是找不到Dockerfile的意思,这里修改命令如下。
mvn clean package dockerfile:build
终于运行成功了,这两个命令有什么区别暂时还不太清楚。
命令执行成功后即生成了Docker镜像。运行命令查看镜像。
$ docker images
REPOSITORY TAG IMAGE ID CREATED
VIRTUAL SIZE
k8sdemo 1.0-SNAPSHOT 2ea0d58678e0 8 hours ago
121.5 MB
openjdk 8-jdk-alpine bba097ee5ee1 5 months ago
104.8 MB
启动镜像。
$ docker run -idt -p 2345:8080 --name k8sdemo k8sdemo:1.0-SNAPSHOT
cdf8e84534331a10d037e073ed55a1703c8dca7b9b7248714fa0ed0d71f71494
查看镜像是否启动成功。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
cdf8e8453433 k8sdemo:1.0-SNAPSHOT "java -Djava.security" 2 seconds ag
o Up 4 seconds 0.0.0.0:2345->8080/tcp k8sdemo
本镜像已启动成功,可以看到8080端口映射到了Docker虚拟机的2345端口。
如果未启动成功可以通过docker ps -a 命令查看所有容器。然后通过docker logs -t --since=30m k8sdemo命令查看日志查找启动失败原因。
访问 http://192.168.99.105:2345 ,可以看到网页内容。

部署 SpringBoot 集群至 Kubernetes
下面以minikube为例介绍如何在Kubernetes中部署SpringBoot应用。
ps:本部分为了区分命令行的输入和输出我在所有输入前添加了$ ,其实Windows命令行下不会显示这个符号
启动 minikube
使用管理员权限打开命令提示符并启动 minikube。
$ minikube start
将 docker daemon 切换成 minikube 的。
$ minikube docker-env
SET DOCKER_TLS_VERIFY=1
SET DOCKER_HOST=tcp://192.168.99.107:2376
SET DOCKER_CERT_PATH=C:\Users\015422343\.minikube\certs
REM Run this command to configure your shell:
REM @FOR /f "tokens=*" %i IN ('minikube docker-env') DO @%i
根据提示运行命令。
$ @FOR /f "tokens=*" %i IN ('minikube docker-env') DO @%i
上传镜像至 minikube
然后打包镜像至minikube。
$ mvn clean package docker:build
这时候报了一个错误。
[ERROR] No plugin found for prefix 'docker' in the current project and in the pl
ugin groups [org.apache.maven.plugins, org.codehaus.mojo] available from the rep
ositories [local (C:\Users\015422343\.m2\repository), central (https://repo.mave
n.apache.org/maven2)] -> [Help 1]
错误原因是插件不在maven配置文件settings.xml中pluginGroups的白名单里面。
修改用户目录下.m2目录中的setting.xml文件(没有则需要添加),在<pluginGroups>节点中添加
<pluginGroup>com.spotify</pluginGroup>
然后运行,又报错了。。。
[ERROR] Failed to execute goal com.spotify:docker-maven-plugin:1.2.1:build (defa
ult-cli) on project k8sdemo: Exception caught: Must specify baseImage if dockerD
irectory is null -> [Help 1]
这个错误是没找到镜像,研究了很久没明白,从网上看到一个方案,修改了下命令,将docker:build修改为dockerfile:build,dockerfile:build是dockerfile-maven-plugin插件的命令,二者具体有什么不同还是没太明白,后续还需研究。
$ mvn clean package dockerfile:build
构建镜像成功后进行验证。
$ docker images
REPOSITORY
TAG IMAGE ID CREATED VIRTUAL SIZE
k8sdemo
1.0-SNAPSHOT sha256:9fa31 41 seconds ago 121.5 MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver
v1.16.0 sha256:b3055 6 weeks ago 217.1 MB
...
部署 SpringBoot 集群
接下来编写部署的yaml文件k8sdemo-deployment.yaml。
apiVersion: apps/v1
kind: Deployment
metadata:
name: k8sdemo-deployment
labels:
app: k8sdemo
spec:
replicas: 3
selector:
matchLabels:
app: k8sdemo
template:
metadata:
labels:
app: k8sdemo
spec:
containers:
- name: k8sdemo
image: k8sdemo:1.0-SNAPSHOT
ports:
- containerPort: 8080
接下来运行命令部署应用集群。
$ kubectl apply -f k8sdemo-deployment.yaml
Warning: kubectl apply should be used on resource created by either kubectl crea
te --save-config or kubectl apply
deployment.apps/k8sdemo-deployment configured
检查创建好的Pod。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
k8sdemo-deployment-7c76b4bf8f-8bn2n 1/1 Running 1 21h
k8sdemo-deployment-7c76b4bf8f-fnwfv 1/1 Running 1 21h
k8sdemo-deployment-7c76b4bf8f-v5wz6 1/1 Running 1 21h
如果创建的Pod存在问题,建议使用minikube logs查看一下相关日志。
访问SpringBoot集群
暴露集群的端口。
$ kubectl expose deployment k8sdemo-deploymen
t --type=NodePort
service/k8sdemo-deployment exposed
然后获取访问的URL。
$ minikube service k8sdemo-deployment --url
* http://192.168.99.107:30947
在浏览器中访问相关URL。

网友评论