带Docker的Spring Boot
本指南将指导您构建运行Spring Boot应用程序的Docker镜像的过程。
你要建造什么
Docker是一个具有“社交”方面的Linux容器管理工具包,允许用户发布容器图像并使用其他人发布的容器图像。Docker镜像是运行容器化过程的配方,在本指南中,我们将为简单的Spring启动应用程序构建一个。
你需要什么
-
大约15分钟
-
最喜欢的文本编辑器或IDE
-
JDK 1.8或更高版本
-
您还可以将代码直接导入IDE:
如果您不使用Linux计算机,则需要虚拟化服务器。通过安装VirtualBox,Mac的boot2docker等其他工具可以为您无缝管理。访问VirtualBox的下载站点,选择适合您机器的版本。下载并安装。不要担心实际运行它。
您还需要Docker,它只能在64位计算机上运行。有关为计算机设置Docker的详细信息,请参阅https://docs.docker.com/installation/#installation。在继续之前,请验证您是否可以docker
从shell 运行命令。如果你正在使用boot2docker你需要运行第一。
如何完成本指南
与大多数Spring 入门指南一样,您可以从头开始并完成每个步骤,或者您可以绕过您已熟悉的基本设置步骤。无论哪种方式,您最终都会使用工作代码。
要从头开始,请继续使用Gradle构建。
要跳过基础知识,请执行以下操作:
-
下载并解压缩本指南的源存储库,或使用Git克隆它:
git clone https://github.com/spring-guides/gs-spring-boot-docker.git
-
进入
gs-spring-boot-docker/initial
完成后,您可以根据代码检查结果gs-spring-boot-docker/complete
。
设置一个Spring Boot应用程序
现在您可以创建一个简单的应用程序
src/main/java/hello/Application.java
package hello;
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 Application {
@RequestMapping("/")
public String home() {
return "Hello Docker World";
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
该类被标记为a @SpringBootApplication
和as @RestController
,这意味着它可以由Spring MVC用于处理Web请求。@RequestMapping
映射/
到home()
只发送“Hello World”响应的方法。该main()
方法使用Spring Boot的SpringApplication.run()
方法来启动应用程序。
现在我们可以在没有Docker容器的情况下运行应用程序(即在主机操作系统中)。
如果您使用的是Gradle,请执行:
./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文件格式,用于指定图像的“图层”。那么让我们继续在Spring Boot项目中创建一个Dockerfile:
Dockerfile
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
这个Dockerfile非常简单,但是你需要运行一个没有多余装饰的Spring Boot应用程序:只需要Java和一个JAR文件。项目JAR文件ADDed
作为“app.jar”到容器,然后在ENTRYPOINT
。
我们添加了一个VOLUME 指向“/ tmp”的内容,因为这是Spring Boot应用程序默认为Tomcat创建工作目录的地方。效果是在主机“/ var / lib / docker”下创建一个临时文件,并将其链接到“/ tmp”下的容器。对于我们在此处编写的简单应用程序,此步骤是可选的,但如果需要在文件系统中实际编写,则对于其他Spring Boot应用程序可能是必需的。 |
为了减少Tomcat的启动时间,我们添加了一个指向“/ dev / urandom”的系统属性作为熵源。如果您使用Tomcat(或任何其他Web服务器)的“标准”版本,则对于更新版本的Spring Boot,这不是必需的。 |
为了利用Spring Boot胖jar文件中依赖项和应用程序资源之间的清晰分离,我们将使用稍微不同的Dockerfile实现:
Dockerfile
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG DEPENDENCY=target/dependency
COPY ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY ${DEPENDENCY}/META-INF /app/META-INF
COPY ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","hello.Application"]
这个Dockerfile有一个DEPENDENCY
参数指向我们解压缩胖jar的目录。如果我们做对了,它已经包含一个BOOT-INF/lib
带有依赖项jars的BOOT-INF/classes
目录,以及一个包含应用程序类的目录。请注意,我们正在使用应用程序自己的主类hello.Application
(这比使用胖jar启动器提供的间接更快)。
如果你正在使用boot2docker你需要运行它首先,你与泊坞窗命令行或生成工具(它运行的守护进程来处理你在虚拟机的工作)做任何事情之前。 |
要构建图像,您可以从社区使用Maven或Gradle的一些工具(非常感谢Palantir和Spotify提供这些工具)。
使用Maven构建Docker镜像
在Maven中pom.xml
你应该添加一个这样的新插件(有关更多选项,请参阅插件文档)::
pom.xml
<properties>
<docker.image.prefix>springio</docker.image.prefix>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.3.6</version>
<configuration>
<repository>${docker.image.prefix}/${project.artifactId}</repository>
</configuration>
</plugin>
</plugins>
</build>
配置指定了1个必需的东西:具有图像名称的存储库,最终将在此处作为springio/gs-spring-boot-docker
。
其他一些属性是可选的:
-
胖jar将要解压缩的目录的名称,将Maven配置公开为docker的构建参数。可以使用
<buildArgs/>
插件配置指定它。 -
图像标记,如果未指定则最终为“最新”。它可以用
<tag/>
元素设置,
在继续执行以下步骤(使用Docker的CLI工具)之前,请确保通过键入正确运行Dockerdocker ps 。如果收到错误消息,可能无法正确设置某些内容。用Mac?添加$(boot2docker shellinit 2> /dev/null) 到您的.bash_profile (或类似的环境设置配置文件)的底部并刷新shell以确保配置了正确的环境变量。 |
为确保在创建docker镜像之前解压缩jar,我们为依赖项插件添加一些配置:
pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
您可以使用命令行构建标记的docker镜像,如下所示:
$ ./mvnw install dockerfile:build
你可以将图像推送到dockerhub ./mvnw dockerfile:push
。
您不必将新创建的Docker镜像推送到实际运行它。此外,如果您不是Dockerhub上“springio”组织的成员,“push”命令将失败。将构建配置和命令行更改为您自己的用户名而不是“springio”,以使其实际工作。 |
您可以dockerfile:push 通过将其添加到插件配置来自动运行安装或部署生命周期阶段。 |
pom.xml
<executions>
<execution>
<id>default</id>
<phase>install</phase>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions
使用Gradle构建Docker镜像
如果您使用的是Gradle,则需要添加如下新插件:
build.gradle
buildscript {
...
dependencies {
...
classpath('gradle.plugin.com.palantir.gradle.docker:gradle-docker:0.13.0')
}
}
group = 'springio'
...
apply plugin: 'com.palantir.docker'
task unpack(type: Copy) {
dependsOn bootJar
from(zipTree(tasks.bootJar.outputs.files.singleFile))
into("build/dependency")
}
docker {
name "${project.group}/${bootJar.baseName}"
copySpec.from(tasks.unpack.outputs).into("dependency")
buildArgs(['DEPENDENCY': "dependency"])
}
配置指定了4件事:
-
解压胖jar文件的任务
-
图像名称(或标记)是从jar文件属性设置的,最终将在此处作为
springio/gs-spring-boot-docker
-
解压缩的jar文件的位置,我们可以在其中进行硬编码
Dockerfile
-
docker指向jar文件的构建参数
您可以构建标记的docker镜像,然后使用Gradle将其推送到远程存储库:
$ ./gradlew build docker
推后
“docker push”将失败(除非您是Dockerhub中“springio”组织的一部分),但是如果您更改配置以匹配您自己的docker ID,那么它应该会成功,并且您将有一个新的标记,部署图片。
您不必注册docker或发布任何东西来运行docker镜像。您仍然拥有本地标记的图像,您可以像这样运行它: |
然后可以在http:// localhost:8080上访问该应用程序(访问它并显示“Hello Docker World”)。要确保整个过程真正起作用,请将前缀从“springio”更改为其他内容(例如${env.USER}
),然后再从构建到docker run再次查看。
将Mac与boot2docker一起使用时,通常会在启动时看到类似的内容: 要查看应用程序,您必须访问DOCKER_HOST中的IP地址而不是localhost。在这种情况下,http://192.168.59.103:8080,VM的面向公众的IP。 |
当它运行时,您可以在容器列表中看到,例如:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
81c723d22865 springio/gs-spring-boot-docker:latest "java -Djava.secur..." 34 seconds ago Up 33 seconds 0.0.0.0:8080->8080/tcp goofy_brown
并再次关闭它你可以docker stop
使用上面列表中的容器ID(你的不同):
$ docker stop 81c723d22865
81c723d22865
如果您愿意,也可以在完成后删除容器(它在/var/lib/docker
某个地方保存在您的文件系统中):
$ docker rm 81c723d22865
使用Spring配置文件
使用Spring配置文件运行刚刚创建的Docker镜像就像将环境变量传递给Docker run命令一样简单
$ docker run -e "SPRING_PROFILES_ACTIVE=prod" -p 8080:8080 -t springio/gs-spring-boot-docker
要么
$ docker run -e "SPRING_PROFILES_ACTIVE=dev" -p 8080:8080 -t springio/gs-spring-boot-docker
在Docker容器中调试应用程序
要调试应用程序,可以使用JPDA Transport。所以我们将容器视为远程服务器。要启用此功能,请在JAVA_OPTS变量中传递Java代理设置,并在容器运行期间将代理程序的端口映射到localhost。使用Docker for Mac存在限制,因为我们无法通过IP访问容器而不使用黑魔法。
$ 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-dockerspan>
摘要
恭喜!您刚刚为Spring Boot应用程序创建了一个Docker容器!默认情况下,Spring Boot应用程序在容器内的端口8080上运行,我们使用命令行上的“-p”将其映射到主机上的同一端口。
也可以看看
以下指南也可能有所帮助:
想要撰写新指南或为现有指南做出贡献?查看我们的贡献指南。
所有指南均附有代码的ASLv2许可证,以及Attribution,NoDerivatives创作公共许可证。 |