本指南将引导您完成构建用于运行Spring Boot应用程序的Docker映像的过程。
你会建立什么
你需要什么
-
约15分钟
-
最喜欢的文本编辑器或IDE
-
JDK 1.8或更高版本
-
您还可以将代码直接导入到IDE中:
如果您不使用Linux机器,则需要一个虚拟服务器。通过安装VirtualBox,其他工具(如Mac的boot2docker)可以为您无缝管理它。访问VirtualBox的下载站点,并为您的计算机选择版本。下载并安装。不用担心实际运行它。
您还需要仅在64位计算机上运行的Docker 。有关为您的机器设置Docker的详细信息,请参见https://docs.docker.com/installation/#installation 。在继续之前,请确认您可以运行docker
从外壳命令。如果你正在使用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
。
用Gradle构建
用Gradle构建
首先,您设置一个基本的构建脚本。在使用Spring构建应用程序时,可以使用任何喜欢的构建系统,但是此处包含使用Gradle和Maven所需的代码。如果您都不熟悉,请参阅使用Gradle 构建Java项目或使用Maven构建Java项目 。
创建目录结构
在您选择的项目目录中,创建以下子目录结构;例如, mkdir -p src/main/java/hello
在* nix系统上:
└── src └── main └── java └── hello
创建一个Gradle构建文件
以下是最初的Gradle构建文件 。
build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.1.6.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
bootJar {
baseName = 'gs-spring-boot-docker'
version = '0.1.0'
}
repositories {
mavenCentral()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
testCompile("org.springframework.boot:spring-boot-starter-test")
}
Spring Boot gradle插件提供了许多方便的功能:
-
它收集类路径上的所有jar,并构建一个可运行的单个“über-jar”,这使执行和传输服务更加方便。
-
它搜索
public static void main()
标记为可运行类的方法。 -
它提供了一个内置的依赖项解析器,用于设置版本号以匹配Spring Boot依赖项 。您可以覆盖所需的任何版本,但是它将默认为Boot选择的一组版本。
用Maven构建
用Maven构建
创建目录结构
在您选择的项目目录中,创建以下子目录结构;例如, mkdir -p src/main/java/hello
在* nix系统上:
└── src └── main └── java └── hello
pom.xml
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>gs-spring-boot-docker</artifactId>
<version>0.1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</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>
</plugins>
</build>
</project>
Spring Boot Maven插件提供了许多方便的功能:
-
它收集类路径上的所有jar,并构建一个可运行的单个“über-jar”,这使执行和传输服务更加方便。
-
它搜索
public static void main()
标记为可运行类的方法。 -
它提供了一个内置的依赖项解析器,用于设置版本号以匹配Spring Boot依赖项 。您可以覆盖所需的任何版本,但是它将默认为Boot选择的一组版本。
使用您的IDE进行构建
使用您的IDE进行构建
-
阅读如何将本指南直接导入Spring Tool Suite中 。
-
在IntelliJ IDEA中阅读如何使用本指南。
设置一个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);
}
}
该类被标记为@SpringBootApplication
并且作为@RestController
,这意味着Spring MVC已准备好使用它来处理Web请求。 @RequestMapping
地图/
到home()
仅发送“ Hello World”响应的方法。的main()
方法使用Spring Boot的SpringApplication.run()
启动应用程序的方法。
现在,我们可以在没有Docker容器的情况下(即在主机OS中)运行应用程序。
如果您使用的是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
指向我们已将胖子罐解压缩的目录的参数。如果我们做对了,它已经包含一个BOOT-INF/lib
目录中包含依赖项jar,以及一个BOOT-INF/classes
目录中包含应用程序类。请注意,我们正在使用应用程序自己的主类hello.Application
(这比使用胖子启动器提供的间接调用要快)。
如果你使用,你需要你的泊坞窗命令行或构建工具做任何事情之前, 先运行它boot2docker(它运行的守护进程来处理你在虚拟机的工作)。 |
使用Maven构建Docker映像
在行家中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.4.9</version>
<configuration>
<repository>${docker.image.prefix}/${project.artifactId}</repository>
</configuration>
</plugin>
</plugins>
</build>
该配置指定1项强制性的内容:具有映像名称的存储库,它将在此处最终显示为springio/gs-spring-boot-docker
。
其他一些属性是可选的:
-
将要解开胖子jar的目录的名称,将Maven配置作为docker的构建参数公开。可以使用
插件配置。 -
图像标签,如果未指定,则最终显示为“最新”。可以用
元件,
在继续执行以下步骤(使用Docker的CLI工具)之前,请通过键入以下内容确保Docker正常运行docker ps 。如果收到错误消息,则可能未正确设置某些内容。使用Mac?加$(boot2docker shellinit 2> /dev/null) 到你的底部.bash_profile (或类似的env-setting配置文件)并刷新您的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文件属性中设置的,最终将显示为
springio/gs-spring-boot-docker
-
解压缩的jarfile的位置,我们可以在其中进行硬编码
Dockerfile
-
docker指向jar文件的构建参数
您可以构建标记的docker映像,然后使用Gradle在一个命令中将其推送到远程存储库:
$ ./gradlew build docker
推后
“ docker push”将为您失败(除非您是Dockerhub的“ springio”组织的一部分),但是如果您更改配置以匹配您自己的docker ID,那么它将成功,并且您将拥有一个新的已标记的部署图片。
您不必在docker上注册或发布任何内容即可运行docker映像。您仍然有一个本地标记的图像,可以像这样运行它: $ 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}
),然后从构建到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。使用Mac的Docker存在局限性,因为如果不使用黑魔法 ,我们不能通过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-docker
摘要
恭喜你!您刚刚为Spring Boot应用程序创建了Docker容器!Spring Boot应用程序默认在容器内的端口8080上运行,我们在命令行上使用“ -p”将其映射到主机上的同一端口。
也可以看看
以下指南也可能会有所帮助:
是否要编写新指南或为现有指南做出贡献?查看我们的贡献准则 。
所有指南均以代码的ASLv2许可证和写作的Attribution,NoDerivatives创作共用许可证发布 。 |