原创

Dockerizing Spring Boot应用程序

温馨提示:
本文最后更新于 2022年11月16日,已超过 20 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

1.概述

在本教程中,我们将重点介绍如何对 Spring Boot应用程序 在一个孤立的环境中运行,也称为。 容器.

我们将学习如何创建容器的组合,这些容器相互依赖,并在虚拟专用网络中相互链接。我们还将看到如何使用单个命令来管理它们。

让我们首先创建一个简单的SpringBoot应用程序,然后在运行的轻量级基础映像中运行 Alpine Linux.

2.Dockerize是一个独立的Spring Boot应用程序

作为一个可以dockerize的应用程序示例,我们将创建一个简单的Spring Boot应用程序, docker-message-server公开一个端点(endpoint)并返回静态消息:

@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

现在我们有了一个工作的Spring Boot应用程序可以访问 localhost:8888/messages。

要对接应用程序,我们首先创建一个名为 Dockerfile文件内容如下:

FROM openjdk:8-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:我们让 Docker 将我们的jar文件复制到镜像中。
  • ENTRYPOINT:这将是容器启动时要启动的可执行文件。我们必须将它们定义为 JSON数组 因为我们将使用 ENTRYPOINTCMD 作为某些应用程序参数。

要通过 Dockerfile文件创建一个镜像,我们需要像以前一样执行 'docker build'

$> docker build --tag=message-server:latest .

最后,我们可以从镜像中运行容器:

$> docker run -p8887:8888 message-server:latest

这将在Docker中启动我们的应用程序,我们可以在 localhost:8887/messages这里定义端口映射,它将主机(8887)上的端口映射到Docker内的端口(8888). 这是我们在Spring Boot应用程序的属性中定义的端口。

注意:端口8887可能在我们启动容器的机器上不可用。在这种情况下,映射可能不起作用,我们需要选择一个仍然可用的端口。

如果我们在分离模式下运行容器,我们可以检查其详细信息,停止它,然后使用以下命令将其删除:

$> docker inspect message-server
$> docker stop message-server
$> docker rm message-server

2.1.更改基础图像

为了使用不同的Java版本,我们可以轻松地更改基础映像。例如,如果我们想使用亚马逊的Corretto发行版,我们可以简单地更改 Dockerfile文件:

FROM amazoncorretto:11-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.在Composite中的Dockerize应用程序

Docker 命令和 Dockerfiles文件 特别适用于创建单独的容器。然而,如果我们想 在独立应用程序的网络上运行,容器管理很快变得混乱。

为了解决这个问题, Docker公司提供了一个名为 Docker Compose的工具. 此工具在中附带了自己的构建文件 YAML 格式,更适合管理多个容器。例如,它能够在一个命令中启动或停止服务的组合,或者将多个服务的日志输出合并输出到一个 伪终端(pseudo-tty).

3.1.第二个Spring Boot应用程序

让我们构建一个在不同Docker容器中运行的两个应用程序的示例。它们将相互通信,并作为“单个单元”呈现给主机系统。作为一个简单的示例,我们将创建第二个SpringBoot应用程序 docker-product-server:

@RestController
public class DockerProductController {
    @GetMapping("/products")
    public String getMessage() {
        return "A brand new product";
    }
}

我们可以使用相同的方式创建和启动它作为我们的 消息服务器.

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:如果给定, docker-compose 能够从 Dockerfile文件创建一个镜像
      • context:如果给定, 他指定了构建目录,并且在其中查找 Dockerfile文件
      • dockerfile:如果给定,他设置一个备用名称给Dockerfile。
    • image:告诉我们 Docker 当使用构建功能时,它应该给镜像起什么名字。否则,它将在 库 或 远程注册表 中搜索此镜像。
    • networks:这是要使用的命名网络的标识符。给定的名称-值必须列在网络部分
  • networks:在本节中,我们将指定 网络可用于我们的服务. 在这个例子中,我们让 docker-compose 创建命名的 network 类型的 “桥” 。如果选项 external 设置为 true,它将使用具有给定名称的现有文件。

在继续之前,我们将检查构建文件中的语法错误:

$> docker-compose config

然后我们可以构建我们的图像,创建定义的容器,并在一个命令中启动它:

$> docker-compose up --build

这将启动 消息服务器产品服务器 一气呵成。

要停止容器,并删除Docker 与 网络 的连接。为此,我们可以使用相反的命令:

$> docker-compose down

有关详细介绍 docker-compose, 我们可以阅读我们的文章 Docker Compose简介.

3.3.缩放服务

一个很好的功能 docker-compose扩展服务的能力.例如,我们可以用 Docker 运行三个容器 消息服务器(message-server) 和两个容器 产品服务器(product-server).

然而,为了使其正常工作,我们必须删除 容器名称 来自我们的 docker-compose.yml所以 Docker 可以选择名称,并更改 暴露端口配置以避免冲突。

对于端口,我们可以告诉Docker将主机上的一系列端口映射到Docker中的一个特定端口:

ports:
    - 18800-18888:8888

之后,我们可以这样扩展我们的服务(请注意,我们使用的是修改的 yml文件):

$> docker-compose --file docker-compose-scale.yml up -d --build --scale message-server=1 product-server=1

此命令将启动单个 消息服务器(message-server) 和一个 产品服务器(product-server).

要扩展我们的服务,我们可以运行以下命令:

$> docker-compose --file docker-compose-scale.yml up -d --build --scale message-server=3 product-server=2

此命令将启动 其他邮件服务器和 其他产品服务器。正在运行的容器不会停止。

4.自定义基础镜像

基本镜像(openjdk:8-jdk-alpine)到目前为止,我们使用的是已经安装了JDK 8的Alpine操作系统发行版。或者,我们可以构建自己的基础镜像(基于Alpine或任何其他操作系统)。

为此,我们可以使用Dockerfile文件以Alpine为基础镜像,并安装我们选择的JDK:

FROM alpine:edge
MAINTAINER baeldung.com
RUN apk add --no-cache openjdk8
  • FROM:关键字 FROM告诉 Docker 使用带有标记的给定镜像作为构建基础。如果此镜像不在本地库中,请在线搜索 DockerHub或在任何其他配置的远程注册表上执行。
  • MAINTAINER:通常是一个电子邮件地址,用于标识镜像的作者。
  • RUN:使用 run 命令,我们正在目标系统中执行shell命令行。我们正在利用 Alpine Linux的 包管理器apk安装 Java 8 OpenJDK。

要最终构建镜像并将其存储在本地库中,我们必须运行:

docker build --tag=alpine-java:base --rm=true .

注意: 这个 -tag选项将给出镜像的名称,并且 -rm=true 将在构建成功后移除其中的镜像. 这个脚本最后的字符是一个点, 作为构建目录的参数

现在我们可以使用创建的镜像而不是 openjdk:8-jdk-alpine.

5.Spring Boot 2.3中的Buildpacks支持

Spring Boot 2.3增加了对内置包支持,简单地说,不需要创建我们自己的Dockerfile并使用类似 docker build,我们只需发出以下命令:

$ mvn spring-boot:build-image

同样,在Gradle:

$ ./gradlew bootBuildImage

为此,我们需要安装并运行Docker。

buildpacks背后的主要动机是创建一些知名云服务(如Heroku或cloud Foundry)已经提供了一段时间的部署体验。我们只是运行 生成镜像然后平台本身负责构建和部署工件。

此外,它可以帮助我们改变现状 更有效地构建Docker图像我们不需要对不同项目中的许多Dockerfile应用相同的更改,只需要更改或调整buildpacks图像生成器。

除了易于使用和更好的整体开发人员体验之外,它还可以更高效。例如,buildpacks方法将创建一个分层Docker图像,并使用Jar文件的分解版本。

让我们看看运行上述命令后会发生什么。

当我们列出可用的docker图像时:

docker image ls -a

我们看到我们刚刚创建的图像的一行:

docker-message-server 1.0.0 b535b0cc0079

这里,图像名称和版本与我们在Maven或Gradle配置文件中定义的名称和版本相匹配。哈希代码是图像哈希的简短版本。

然后,要启动我们的容器,我们可以简单地运行:

docker run -it -p9099:8888 docker-message-server:1.0.0

与我们构建的映像一样,我们需要映射端口,以便从Docker外部访问Spring Boot应用程序。

6.结论

在本文中,我们学习了如何构建自定义 Docker 图像,运行 Spring Boot应用程序 作为一个 Docker 容器,并使用 docker-compose.

有关构建文件的更多信息,请参阅官方 Docker reference 和 docker-compse.yml参考.

与往常一样,可以找到本文的源代码 在GitHub上.

正文到此结束