1. 概述
本教程将重点介绍如何将Spring Boot应用Docker化,使其在隔离环境(即容器)中运行。我们将学习如何创建相互依赖、在虚拟私有网络中互联的容器组合,并了解如何通过单条命令统一管理这些容器。
首先创建一个简单的Spring Boot应用,然后将其运行在轻量级的Alpine Linux基础镜像中。
2. Docker化独立Spring Boot应用
作为示例,我们创建一个名为docker-message-server
的简单Spring Boot应用,它暴露一个接口并返回静态消息:
@RestController
public class DockerMessageController {
@GetMapping("/messages")
public String getMessage() {
return "Hello from Docker!";
}
}
配置正确的Maven文件后,创建可执行jar包:
$> mvn clean package
启动Spring Boot应用:
$> java -jar target/docker-message-server-1.0.0.jar
现在可通过localhost:8888/messages
访问该应用。
要Docker化应用,首先创建Dockerfile
文件:
FROM openjdk:17-jdk-alpine
MAINTAINER baeldung.com
COPY target/docker-message-server-1.0.0.jar message-server-1.0.0.jar
ENTRYPOINT ["java","-jar","/message-server-1.0.0.jar"]
该文件包含以下信息:
- FROM:使用已安装Java的Alpine Linux作为基础镜像
- MAINTAINER:镜像维护者
- COPY:将jar文件复制到镜像中
- ENTRYPOINT:容器启动时执行的命令(必须使用JSON数组格式)
通过docker build
创建镜像:
$> docker build --tag=message-server:latest .
最后运行容器:
$> docker run -p8887:8888 message-server:latest
应用将在Docker中启动,可通过主机localhost:8887/messages
访问。注意端口映射(主机8887 → 容器8888),如果端口被占用需更换可用端口。
以分离模式运行容器时,可使用以下命令管理:
$> docker inspect message-server
$> docker stop message-server
$> docker rm message-server
2.1. 更换基础镜像
可轻松更换基础镜像以使用不同Java版本。例如改用Amazon Corretto发行版:
FROM amazoncorretto:17-alpine-jdk
MAINTAINER baeldung.com
COPY target/docker-message-server-1.0.0.jar message-server-1.0.0.jar
ENTRYPOINT ["java","-jar","/message-server-1.0.0.jar"]
也可使用自定义基础镜像(后文详述)。
3. Docker化复合应用
Docker命令和Dockerfile适合创建单个容器,但当需要管理多个隔离应用组成的网络时,容器管理会变得混乱。
解决方案是Docker Compose,它使用YAML格式的构建文件,更适合管理多容器。例如:
- 单条命令启动/停止服务组合
- 合并多个服务的日志输出到伪终端
3.1. 第二个Spring Boot应用
构建两个在不同Docker容器中运行的应用示例。它们将相互通信,并作为"单一单元"呈现给主机系统。创建第二个应用docker-product-server
:
@RestController
public class DockerProductController {
@GetMapping("/products")
public String getMessage() {
return "A brand new product";
}
}
构建和启动方式与message-server
相同。
3.2. Docker Compose文件
将两个服务的配置合并到docker-compose.yml
:
version: '2'
services:
message-server:
container_name: message-server
build:
context: docker-message-server
dockerfile: Dockerfile
image: message-server:latest
ports:
- 18888:8888
networks:
- spring-cloud-network
product-server:
container_name: product-server
build:
context: docker-product-server
dockerfile: Dockerfile
image: product-server:latest
ports:
- 19999:9999
networks:
- spring-cloud-network
networks:
spring-cloud-network:
driver: bridge
配置说明:
- version:指定格式版本(必填),此处使用新版(旧版为'1')
- services:定义服务(容器)对象(必填)
- build:从Dockerfile构建镜像
- context:构建目录(Dockerfile所在路径)
- dockerfile:自定义Dockerfile名称
- image:镜像名称(构建时使用)或从库/远程仓库拉取
- networks:使用的网络标识符(需在networks部分定义)
- build:从Dockerfile构建镜像
- networks:定义可用网络
- 此处创建名为
spring-cloud-network
的bridge类型网络 - 若设置
external: true
则使用现有网络
- 此处创建名为
先检查语法错误:
$> docker-compose config
然后构建镜像、创建容器并启动:
$> docker-compose up --build
这将同时启动message-server
和product-server
。
停止容器并移除相关网络:
$> docker-compose down
3.3. 服务扩缩容
Docker Compose的服务扩缩容功能很实用。例如运行3个message-server
和2个product-server
容器。
但需先移除docker-compose.yml
中的container_name
(让Docker自动命名),并修改端口配置避免冲突:
ports:
- 18800-18888:8888
使用修改后的yml文件启动服务:
$> docker-compose --file docker-compose-scale.yml up -d --build --scale message-server=1 --scale product-server=1
扩缩容命令:
$> docker-compose --file docker-compose-scale.yml up -d --build --scale message-server=3 --scale product-server=2
此命令将启动额外2个message-server和1个product-server(不停止已运行容器)。
4. 自定义基础镜像
之前使用的基础镜像(openjdk:17-jdk-alpine
)包含预装JDK 17的Alpine系统。也可基于Alpine或其他系统构建自定义基础镜像。
创建基于Alpine的Dockerfile并安装JDK:
FROM alpine:edge
MAINTAINER baeldung.com
RUN apk add --no-cache openjdk17
指令说明:
- FROM:指定构建基础镜像(本地不存在时从DockerHub搜索)
- MAINTAINER:镜像作者邮箱
- RUN:在目标系统执行shell命令(使用Alpine包管理器apk安装OpenJDK 17)
构建镜像并存储到本地库:
docker build --tag=alpine-java:base --rm=true .
⚠️ --tag
指定镜像名,--rm=true
成功构建后删除中间镜像,末尾点表示构建目录。
现在可用alpine-java:base
替代openjdk:17-jdk-alpine
。
5. Spring Boot 2.3的Buildpacks支持
Spring Boot 2.3新增了buildpacks支持。简单说,无需自行编写Dockerfile,只需执行:
$ mvn spring-boot:build-image
或Gradle项目:
$ ./gradlew bootBuildImage
前提:已安装并运行Docker
其核心理念是提供类似Heroku或Cloud Foundry的统一部署体验。只需运行build-image
目标,平台自动处理构建和部署。
此外,它能帮助我们更高效地构建Docker镜像。只需修改或调优buildpacks镜像构建器,无需在多个项目中修改Dockerfile。
除易用性和开发体验外,效率更高:
- 构建分层Docker镜像
- 使用jar文件的解压版本
执行命令后查看镜像列表:
docker image ls -a
将看到新创建的镜像:
docker-message-server 1.0.0 b535b0cc0079
镜像名和版本与Maven/Gradle配置一致,哈希值为镜像短哈希。
启动容器:
docker run -it -p9099:8888 docker-message-server:1.0.0
同样需要端口映射使应用可从外部访问。
6. 总结
本文学习了如何:
- 构建自定义Docker镜像
- 将Spring Boot应用作为Docker容器运行
- 使用docker-compose创建容器组合
更多构建文件细节可参考官方文档:
本文源代码见GitHub仓库。