Spring Boot应用发布到Docker的实现
spring官网上有一篇getting start,介绍了如何使用docker发布spring boot应用,算是比较详细了,不过有些细节没有提及到,而且官网的入门手册是英文版。这里重新整理记录一下,算是给英文不好的小伙伴一个参考,也给自己留个备忘。
准备
需要的工具以及运行环境:
- jdk 1.8 or later
- maven 3.0 +
- 你喜欢的ide或其他文本编辑器
创建工程
首先,你需要创建一个spring boot工程,spring tool suite和intellij idea都自带插件可以创建,还有一种方式是从上创建,推荐使用这种方式。填好表单中的group id
和artifact id
之后,点击generate project按钮就可以生成了,将下载后的工程导入到你喜欢的ide中。
修改pom.xml文件,添加docker-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/xsd/maven-4.0.0.xsd"> <modelversion>4.0.0</modelversion> <groupid>org.matrixstudio.springboot</groupid> <artifactid>docker</artifactid> <version>0.0.1-snapshot</version> <packaging>jar</packaging> <name>docker</name> <description>demo project for spring boot</description> <parent> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-parent</artifactid> <version>1.5.2.release</version> <relativepath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceencoding>utf-8</project.build.sourceencoding> <project.reporting.outputencoding>utf-8</project.reporting.outputencoding> <java.version>1.8</java.version> <docker.image.prefix>springio</docker.image.prefix> </properties> <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> <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>0.4.3</version> <configuration> <imagename>${docker.image.prefix}/${project.artifactid}</imagename> <dockerdirectory>src/main/docker</dockerdirectory> <resources> <resource> <targetpath>/</targetpath> <directory>${project.build.directory}</directory> <include>${project.build.finalname}.jar</include> </resource> </resources> </configuration> </plugin> </plugins> </build> </project>
docker-maven-plugin插件用于将spring boot工程构建为docker镜像:
- imagename表示docker镜像名称,我们使用docker的命名规范,命名为:springio/docker
- dockerdirectory表示dockerfile的路径
- resource表示在构建时需要的资源文件,这些文件和dockerfile放在一起,这里只需要spring boot生成的jar文件即可。
打开dockerapplication.java
文件,修改成如下内容:
package org.matrixstudio.springboot; import org.springframework.boot.springapplication; import org.springframework.boot.autoconfigure.springbootapplication; import org.springframework.web.bind.annotation.requestmapping; import org.springframework.web.bind.annotation.restcontroller; @springbootapplication @restcontroller public class dockerapplication { @requestmapping("/") public string home() { return "hello docker world"; } public static void main(string[] args) { springapplication.run(dockerapplication.class, args); } }
编译并运行
执行如下命令运行spring boot工程:
mvn package && java -jar target/docker-0.0.1-snapshot.jar
打开浏览器,输入http://localhost:8080
,如果出现“hello docker world”说明运行成功。
注:运行上面的命令时,需要从maven官方仓库中下载很多依赖包,国内网络不太稳定,下载速度较慢,可考虑使用第三方提供的镜像站,比如阿里的maven镜像仓库。在pom.xml中加入下面配置:
<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/xsd/maven-4.0.0.xsd"> <modelversion>4.0.0</modelversion> <groupid>org.matrixstudio.springboot</groupid> <artifactid>docker</artifactid> <version>0.0.1-snapshot</version> <packaging>jar</packaging> <!-- dependencies --> ...... <!-- build --> ...... <!-- aliyun repository --> <repositories> <repository> <id>central</id> <name>aliyun</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <releases> <enabled>true</enabled> </releases> </repository> </repositories> </project>
容器化项目
首先要确保你的机器上安装了docker,如果你的docker安装在一台linux服务器上,你需要将上面的spring boot工程上传到该服务器上,下面的步骤假设你是在linux环境上操作。
创建dockerfile
docker使用一个名为dockerfile
的文件来指定image层,所以我们首先需要创建一个dockerfile
文件,执行下面的命令创建dockerfile
文件:
sudo tee src/main/docker/dockerfile <<-'eof' from frolvlad/alpine-oraclejdk8:slim volume /tmp add docker-0.0.1-snapshot.jar app.jar run sh -c 'touch /app.jar' env java_opts="" entrypoint [ "sh", "-c", "java $java_opts -djava.security.egd=file:/dev/./urandom -jar /app.jar" ] eof
大概解释一下上面的命令:
- volume指向了一个/tmp的目录,由于spring boot使用内置的tomcat容器,tomcat默认使用/tmp作为工作目录。效果就是在主机的/var/lib/docker目录下创建了一个临时文件,并连接到容器的/tmp。
- 将项目的jar文件作为app.jar添加到容器
- run表示在新创建的镜像中执行一些命令,然后把执行的结果提交到当前镜像。这里使用touch命令来改变文件的修改时间,docker创建的所有容器文件默认状态都是“未修改”。这对于简单应用来说不需要,不过对于一些静态内容(比如:index.html)的文件就需要一个“修改时间”。
- 为了缩短tomcat的启动时间,我们添加一个java.security.egd的系统属性指向/dev/urandom作为entrypoint。
构建docker镜像
运行下面的命令构建docker镜像:
mvn package docker:build
构建完成后,运行下面的命令查看:
sudo docker images
结果为:
repository tag image id created size
springio/docker latest 7e2ba2f7e81e 2 minutes ago 195 mb
frolvlad/alpine-oraclejdk8 slim 00d8610f052e 4 days ago 167 mb
可以看到我们构建的镜像已经出现了,下一步就是运行该镜像。
运行docker镜像
执行下面的命令来运行上一步构建的docker镜像:
sudo docker run -p 8080:8080 -t springio/docker
如果不出意外,你将看到下面的输出内容:
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: spring boot :: (v1.5.2.release) 2017-03-08 03:34:59.434 info 6 --- [ main] o.m.springboot.dockerapplication : starting dockerapplication v0.0.1-snapshot on 00eed53e6928 with pid 6 (/app.jar started by root in /) 2017-03-08 03:34:59.445 info 6 --- [ main] o.m.springboot.dockerapplication : no active profile set, falling back to default profiles: default 2017-03-08 03:34:59.752 info 6 --- [ main] ationconfigembeddedwebapplicationcontext : refreshing org.springframework.boot.context.embedded.annotationconfigembeddedwebapplicationcontext@4b9af9a9: startup date [wed mar 08 03:34:59 gmt 2017]; root of context hierarchy 2017-03-08 03:35:03.755 info 6 --- [ main] s.b.c.e.t.tomcatembeddedservletcontainer : tomcat initialized with port(s): 8080 (http) 2017-03-08 03:35:03.807 info 6 --- [ main] o.apache.catalina.core.standardservice : starting service tomcat 2017-03-08 03:35:03.821 info 6 --- [ main] org.apache.catalina.core.standardengine : starting servlet engine: apache tomcat/8.5.11 2017-03-08 03:35:04.042 info 6 --- [ost-startstop-1] o.a.c.c.c.[tomcat].[localhost].[/] : initializing spring embedded webapplicationcontext 2017-03-08 03:35:04.043 info 6 --- [ost-startstop-1] o.s.web.context.contextloader : root webapplicationcontext: initialization completed in 4303 ms 2017-03-08 03:35:04.441 info 6 --- [ost-startstop-1] o.s.b.w.servlet.servletregistrationbean : mapping servlet: 'dispatcherservlet' to [/] 2017-03-08 03:35:04.455 info 6 --- [ost-startstop-1] o.s.b.w.servlet.filterregistrationbean : mapping filter: 'characterencodingfilter' to: [/*] 2017-03-08 03:35:04.457 info 6 --- [ost-startstop-1] o.s.b.w.servlet.filterregistrationbean : mapping filter: 'hiddenhttpmethodfilter' to: [/*] 2017-03-08 03:35:04.468 info 6 --- [ost-startstop-1] o.s.b.w.servlet.filterregistrationbean : mapping filter: 'httpputformcontentfilter' to: [/*] 2017-03-08 03:35:04.468 info 6 --- [ost-startstop-1] o.s.b.w.servlet.filterregistrationbean : mapping filter: 'requestcontextfilter' to: [/*] 2017-03-08 03:35:05.110 info 6 --- [ main] s.w.s.m.m.a.requestmappinghandleradapter : looking for @controlleradvice: org.springframework.boot.context.embedded.annotationconfigembeddedwebapplicationcontext@4b9af9a9: startup date [wed mar 08 03:34:59 gmt 2017]; root of context hierarchy 2017-03-08 03:35:05.390 info 6 --- [ main] s.w.s.m.m.a.requestmappinghandlermapping : mapped "{[/]}" onto public java.lang.string org.matrixstudio.springboot.dockerapplication.home() 2017-03-08 03:35:05.402 info 6 --- [ main] s.w.s.m.m.a.requestmappinghandlermapping : mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.modelandview org.springframework.boot.autoconfigure.web.basicerrorcontroller.errorhtml(javax.servlet.http.httpservletrequest,javax.servlet.http.httpservletresponse) 2017-03-08 03:35:05.404 info 6 --- [ main] s.w.s.m.m.a.requestmappinghandlermapping : mapped "{[/error]}" onto public org.springframework.http.responseentity<java.util.map<java.lang.string, java.lang.object>> org.springframework.boot.autoconfigure.web.basicerrorcontroller.error(javax.servlet.http.httpservletrequest) 2017-03-08 03:35:05.512 info 6 --- [ main] o.s.w.s.handler.simpleurlhandlermapping : mapped url path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.resourcehttprequesthandler] 2017-03-08 03:35:05.512 info 6 --- [ main] o.s.w.s.handler.simpleurlhandlermapping : mapped url path [/**] onto handler of type [class org.springframework.web.servlet.resource.resourcehttprequesthandler] 2017-03-08 03:35:05.639 info 6 --- [ main] o.s.w.s.handler.simpleurlhandlermapping : mapped url path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.resourcehttprequesthandler] 2017-03-08 03:35:06.019 info 6 --- [ main] o.s.j.e.a.annotationmbeanexporter : registering beans for jmx exposure on startup 2017-03-08 03:35:06.168 info 6 --- [ main] s.b.c.e.t.tomcatembeddedservletcontainer : tomcat started on port(s): 8080 (http) 2017-03-08 03:35:06.183 info 6 --- [ main] o.m.springboot.dockerapplication : started dockerapplication in 7.893 seconds (jvm running for 8.743) 2017-03-08 03:35:56.728 info 6 --- [nio-8080-exec-1] o.a.c.c.c.[tomcat].[localhost].[/] : initializing spring frameworkservlet 'dispatcherservlet' 2017-03-08 03:35:56.728 info 6 --- [nio-8080-exec-1] o.s.web.servlet.dispatcherservlet : frameworkservlet 'dispatcherservlet': initialization started 2017-03-08 03:35:56.774 info 6 --- [nio-8080-exec-1] o.s.web.servlet.dispatcherservlet : frameworkservlet 'dispatcherservlet': initialization completed in 43 ms
执行以下命令,查看正在运行的docker容器:
sudo docker ps
可以看到已经有一个docker容器在运行了:
container id image command created status ports names 00eed53e6928 springio/docker "sh -c 'java $java..." about a minute ago up about a minute 0.0.0.0:8080->8080/tcp fervent_leavitt
现在输入http://localhost:8080可以查看到“hello docker world”结果。
如果要停止容器,可以执行下面的命令:
sudo docker stop 00e
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
Spring Boot应用发布到Docker的实现
-
spring Boot 应用通过Docker 来实现构建、运行、发布流程
-
Spring Boot应用Docker化的步骤详解
-
使用Docker部署 spring-boot maven应用的方法
-
Spring Boot应用Docker化的步骤详解
-
Spring Boot Gradle发布war到tomcat的方法示例
-
使用Docker部署 spring-boot maven应用的方法
-
Spring boot+redis实现消息发布与订阅的代码
-
Spring Boot 注入外部配置到应用内部的静态变量
-
在Docker中开发Java 8 Spring Boot应用程序的方法