Spring Boot项目打包成docker镜像

如何完成这篇教程

像大多数的Spring系列教程  Getting Started guides ,你可以从头开始,完成每一步,也可以跳过已经熟悉的基本構建步骤。 无论哪种方式,你都可以成功。

使用maven构建

首先你得安装构建脚本. 你可以使用你喜欢的构建系统去构建Spring应用,你可以前往 Maven官网 来指导你安装。 如果你对 Maven 不熟悉,请参阅 使用Maven构建Java项目 .

创建目录结构

在你当前项目工作目录中,创建如下子目录:
1
2
3
4
└── src
          └── main
                      └── java
                                  └── 应用包名
如在Linux系统下使用 mkdir -p src/main/java/ 应用包名 来创建。
pom.xml
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";  
  3.     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd";>  
  4.     <modelVersion>4.0.0</modelVersion>  
  5.     <groupId>org.springframework</groupId>  
  6.     <artifactId>gs-spring-boot-docker</artifactId>  
  7.     <version>0.1.0</version>  
  8.     <parent>  
  9.         <groupId>org.springframework.boot</groupId>  
  10.         <artifactId>spring-boot-starter-parent</artifactId>  
  11.         <version>1.5.4.RELEASE</version>  
  12.     </parent>  
  13.     <properties>  
  14.         <java.version>1.8</java.version>  
  15.     </properties>  
  16.     <dependencies>  
  17.         <dependency>  
  18.             <groupId>org.springframework.boot</groupId>  
  19.             <artifactId>spring-boot-starter-web</artifactId>  
  20.         </dependency>  
  21.         <dependency>  
  22.             <groupId>org.springframework.boot</groupId>  
  23.             <artifactId>spring-boot-starter-test</artifactId>  
  24.             <scope>test</scope>  
  25.         </dependency>  
  26.     </dependencies>  
  27.     <build>  
  28.         <plugins>  
  29.             <plugin>  
  30.                 <groupId>org.springframework.boot</groupId>  
  31.                 <artifactId>spring-boot-maven-plugin</artifactId>  
  32.             </plugin>  
  33.         </plugins>  
  34.     </build>  
  35. </project>  


下面是我的理解和项目截图:



Spring Boot maven插件  提供了很多便捷的功能:
  • 它集中了classpath下的所有jar,并构建一个可运行的“uber-jar”,这样可以更方便地执行和发布服务。
  • 它查找public static void main()方法并标记该类为可执行类。
  • 它提供了一个内置的依赖解析器,将应用与Spring Boot依赖的版本号进行匹配。你可以修改(override)成你希望的版本,但它默认为Spring Boot选择的版本。

使用你的IDE构建

创建一个Spring Boot应用程序

现在你可以创建一个简单的Spring Boot应用程序。
src/main/java/hello/Application.java
[java]   view plain   copy
  print ?
  1. package hello;  
  2. import org.springframework.boot.SpringApplication;  
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;  
  4. import org.springframework.web.bind.annotation.RequestMapping;  
  5. import org.springframework.web.bind.annotation.RestController;  
  6. @SpringBootApplication  
  7. @RestController  
  8. public class Application {  
  9.     @RequestMapping("/")  
  10.     public String home() {  
  11.         return "Hello Docker World";  
  12.     }  
  13.     public static void main(String[] args) {  
  14.         SpringApplication.run(Application.class, args);  
  15.     }  
  16. }  
这个类使用 @SpringBootApplication 注解和 @RestController 注解标记,表示这个类已经准备好使用Spring MVC来处理web请求。 @RequestMapping 映射 / home() 方法上,這個方法返回 Hello Docker World 的响应。 main() 方法调 SpringApplication.run() 方法来启动应用程序。
现在你可以在没有Docker的情况下运行该应用程序。
如果你使用gradle构建的Spring Boot应用程序,执行:
./gradlew build && java -jar build/libs/gs-spring-boot-docker-0.1.0.jar
如果你使用maven构建的,执行:
./mvnw package && java -jar target/gs-spring-boot-docker-0.1.0.jar
然后访问 localhost:8080 就可以看见 Hello Docker World 字样。

使你的应用程序容器化

Docker有一个 Dockerfile 文件格式的文件,并且使用指定的镜像作为基础镜像。接下来我们去创建一个Dockerfile在Spring Boot应用程序中。
Dockerfile
1
2
3
4
5
FROM openjdk: 8 -jdk-alpine
VOLUME /tmp
ADD target/gs-spring-boot-docker-0.1.0.jar app.jar
ENV JAVA_OPTS=""
ENTRYPOINT exec java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar

下面是我的理解和项目截图:


这Dockerfile很简单,但是已经包含了你运行这个Spring Boot应用程序的所有东西并且没有多余的东西:仅仅只有Java和一个Jar文件。应用程序的jar文件(文件名为app.jar)被添加到容器中,执行  ENTRYPOINT
我们增加了一个 VOLUME 指向”/tmp”,因为那是Spring Boot应用程序为Tomcat创建的默认工作目录。作用是在你的主机”/var/lib/docker”目录下创建一个临时的文件,并且链接到容器中的”/tmp”目录。对于简单程序这一步是可选的,但是对于其他想要真实写入文件系统的Spring Boot应用程序又是必选的。
我们增加了一个指向”/dev/urandom”的Tomcat系统属性来缩小Tomcat的启动时间。
如果你使用的是boot2docker,在你使用Docker命令或者使用构建工具构建(它运行在守护进程,在虚拟机上为你工作)之前,你必须先启动它。
构建Docker镜像,你可以使用一些诸如Gradle或Maven的工具或者借助社区(强烈感谢 Transmode Spotify 提供这些工具)。

使用Maven构建Docker镜像

在Maven的 pom.xml 中,你应该增加一个插件,如下。(参阅 the plugin documentation 获取更多信息)。
pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
< properties >
< docker.image.prefix > springio </ docker.image.prefix >
</ properties >
< build >
< plugins >
< plugin >
< groupId > com.spotify </ groupId >
< artifactId > dockerfile-maven-plugin </ artifactId >
< version > 1.3.4 </ version >
< configuration >
< repository > ${docker.image.prefix}/${project.artifactId} </ repository >
</ configuration >
</ plugin >
</ plugins >
</ build >
配置指定了两个东西:
  • 镜像名字,最终会在springio/gs-spring-boot-docker
  • 可选,镜像的标签,未指定默认为latest,如果有需要的话,也可以指定artifact id
继续下面的步骤之前(使用Docker CLI工具),输入 docker ps 确保正常运行,如果有错误信息,大概因为没有设置其他什么信息。如果使用的Mac,在 .bash_profile (或者是类似env-setting配置文件)最后增加 $(boot2docker shellinit 2> /dev/null) 并刷新你的shell,确保更改生效。
你可以使用下面的命令来构建Docker的镜像:
1
$ ./mvnw install dockerfile:build
你可以使用 ./mvnw dockerfile:push 命令发布镜像到 Docker 镜像中心去。
你不用着急发布你刚刚制作的镜像,如果你不是”springio”组织的成员 push 命令会失败。改变构建的配置和命令行中的用户名为自己的而不是”springio”就可以正常工作。
你可以让 dockerfile:push 自动运行在安装或部署生命周期阶段,通过将其添加到插件配置中。
pom.xml
1
2
3
4
5
6
7
8
9
10
< executions >
< execution >
< id > default </ id >
< phase > install </ phase >
< goals >
< goal > build </ goal >
< goal > push </ goal >
</ goals >
</ execution >
</ executions >

发布之后

对你来说”Docker镜像发布”会失败(除非你在Dockerhub中是”springio”组织的一员),但是如果你修改配置符合你自己的docker ID之后同样会成功,你会有一个新的标签,并且部署镜像。
如果你没有注册docker,或者没有发布任何docker镜像。但是你有一个本地的镜像,你可以像这样让它运行起来:
1
2
3
4
$ docker run -p 8080:8080 -t springio/gs-spring-boot-docker
....
2015-03-31 13:25:48.035 INFO 1 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2015-03-31 13:25:48.037 INFO 1 --- [ main] hello.Application : Started Application in 5.613 seconds (JVM running for 7.293)
然后应用程序可以在 http://localhost:8080/ 访问(访问可以看到”Hello Docker World”)。确保它是真的在工作,把”springio”前缀改成其他(比如 ${env.USER} 并且重新构建运行)。
如果你使用mac的boot2docker,你通常在启动时可以看到这样的事情:
1
2
3
4
Docker client to the Docker daemon, please set :
export DOCKER_CERT_PATH=/Users/gturnquist/.boot2docker/certs/boot2docker-vm
export DOCKER_TLS_VERIFY=1
export DOCKER_HOST=tcp://192.168.59.103:2376
查看应用程序,你必须访问Docker主机而不是本地主机的ip(localhost),在这种情况下, http://192.168.59.103:8080/ ,对于VM来说就是开发的ip。
当它正在运行,你可以在容器列表中看到:
1
2
3
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
81c723d22865 springio/gs-spring-boot-docker:latest "java -jar /app.jar" 34 seconds ago Up 33 seconds 0.0.0.0:8080->8080/tcp goofy_brown
你可以使用 docker stop 加上容器的id来关闭它。
1
2
$ docker stop 81c723d22865
81c723d22865
当然你喜欢你也可以删除容器(它们都保存在 /var/lib/docker 文件目录下)。
1
$ docker rm 81c723d22865

使用Spring Profiles

运行你新制作的镜像使用Spring Profiles,和运行docker命令传入一个环境变量一样简单。
1
$ docker run -e "SPRING_PROFILES_ACTIVE=prod" -p 8080:8080 -t springio/gs-spring-boot-docker
1
$ docker run -e "SPRING_PROFILES_ACTIVE=dev" -p 8080:8080 -t springio/gs-spring-boot-docker

在Docker容器中调试应用程序

使用 JPDA Transport可以调试应用程序,所以我们可以视容器为一个服务器,启用此功能通过java设置JAVA_OPTS变量和代理的端口映射到本地主机在一个容器中运行。对于 Docker for Mac由于有限制,我们不能通过IP访问容器因为没有 black magic usage.
1
$ docker run -e "JAVA_OPTS=-agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n" -p 8080:8080 -p 5005:5005 -t springio/gs-spring-boot-docker

总结

恭喜你!刚刚为Spring Boot应用程序创建了Docker容器!Spring Boot应用程序在容器中运行默认端口8080映射到相同的宿主机端口使用”-p”参数。

另请参阅

以下教程也可能是有用的:

项目结构如下:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值