0%

Spring Boot 在 Docker 上部署

最近在初步了解Docker,想把 Spring Boot 项目构建成镜像。先介绍下Docker的基本情况。

Docker是什么

Docker是一种开源的应用引擎,使用Go语言开发的。开发人员利用 Docker 可以消除协作编码时“在我的机器上可正常工作”的问题。目前,Docker可以在容器内部快速自动化部署应用,并可以通过内核虚拟化技术(namespaces及cgroups等)来提供容器的资源隔离与安全保障等。由于Docker通过操作系统层的虚拟化实现隔离,所以Docker容器在运行时,不需要类似虚拟机(VM)额外的操作系统开销,提高资源利用率,并且提升诸如IO等方面的性能。
Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。它是目前最流行的 Linux 容器解决方案。Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker,就不用担心环境问题。

Spring Boot部署到docker

一个简单的springboot项目

创建springboot项目可以去官网入口上直接创建一个项目,或者在idea上面从创建,如果没有该选项,去idea设置里面插件里面去勾线,在重启idea。

在pom.xml中添加web依赖的jar包。

1
2
3
4
5
6
7
8
9
10
11
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

创建一个Controller.

1
2
3
4
5
6
7
8
@RestController
public class DockerController {

@RequestMapping("/docker")
public String docker(){
return "Hello Docker!";
}
}

启动项目的启动项,在浏览器中访问:http://localhost:8080/docker,如果返回: Hello Docker! 则项目成功了。

SpringBoot中添加Docker支持

spring boot 支持两种打镜像的方式,一种是Dockerfile,另外一种是直接通过插件构建镜像。除了这两种方式,谷歌提供了一个插件: jib,这种方式也是直接通过插件构建镜像,不过这种方式自己还没构建成功过,看国内的教程比较少。

Dockerfile

在pom.xml文件中,新增docker的依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<properties>
<docker.image.prefix>springboot</docker.image.prefix>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- Docker maven plugin -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
<dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
<!-- Docker maven plugin -->
</plugins>
</build>

添加Dockerfile,文件在main文件下面新增docker文件,入图所示:

在文件中添加以下内容

1
2
3
4
5
6
FROM java:8
VOLUME /tmp
ADD springboot-0.0.1-SNAPSHOT.jar app.jar
RUN bash -c 'touch /app.jar'
ENV JAVA_OPTS=""
ENTRYPOINT [ "sh""-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]

简单解释下

  • FROM,使用Java8为基础,如果本地没有镜像,就从DockerHub拉取
  • VOLUME,VOLUME 指向了一个/tmp的目录,由于 Spring Boot 使用内置的Tomcat容器,Tomcat 默认使用/tmp作为工作目录。这个命令的效果是:在宿主机的/var/lib/docker目录下创建一个临时文件并把它链接到容器中的/tmp目录
  • ADD,拷贝文件并且重命名
  • ENTRYPOINT,为了缩短 Tomcat 的启动时间,添加java.security.egd的系统属性指向/dev/urandom作为 ENTRYPOINT

这样就把项目依赖Docker的配置弄完了。

直接插件构建镜像

这种是直接依赖pom.xml里面的插件,直接构建镜像的。jib 插件和这中方式类似,可以看它GitHub上的使用文档。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- Docker maven plugin -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.1.1</version>
<configuration>
<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
<baseImage>java:8</baseImage>
<entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
<!-- Docker maven plugin -->

这样就可以在本地docker 镜像里面看到这个新的镜像了,不过个人感觉在基于Java8为基础镜像打成的项目镜像,感觉镜像大小有点大,好几百M的大小。

搭建服务器

按照docker

服务器需要先按照Java8,maven,然后下载docker

1
yum install Docker

按照后启动dockerservice docker start

部署项目

把项目拷贝到你的服务器上面,我是把本地项目上传到GitHub上面,服务器上直接拉取项目

1
2
3
4
5
6
#进入项目
cd springboot
#打包
mvn package
#启动
java -jar target/springboot-0.0.1-SNAPSHOT.jar

启动项目验证是否可以运行项目是否可以在服务器上面运行,然后使用dockerfile构建镜像

1
mvn package docker:build

构建成功后,使用docker images查看服务器上面是否有该镜像,最后运行镜像。

1
docker run -p 8081:8081 -t springboot/springboot

在浏览器上面访问地址就可以了。

springboot部署到docker是遇到的问题

一开始我项目的名字是SpringBoot,在创建jar什么的时候都没有问题,但是在mvn clean package docker:build是就报错

1
500 Internal Server Error

网上找了下,感觉说的都是牛头不对马嘴,没有定位到什么问题,最后在GitHub上面找到了问题的原因,问题地址,是说不支持项目的大小写,你需要是小写或者数字,而不是大写字母。原来高了老半天,是大小的问题,涨知识了。

Reference

纯洁微笑
Docker中国官网
Docker系列之一:入门介绍

代码

GitHub源码

客官,赏一杯coffee嘛~~~~