JavaRush /Java 博客 /Random-ZH /我们实现应用程序部署——《Java项目从A到Z》
Roman Beekeeper
第 35 级

我们实现应用程序部署——《Java项目从A到Z》

已在 Random-ZH 群组中发布
大家好。我们将继续撰写有关编写项目的系列文章。 “Java 项目从头到尾”:实施应用程序部署 - 1

对分支进行排序

重要的是,为了不迷失分支及其在存储库中的顺序,我决定通过添加STEP_{number}前缀来重命名它们。例如,除了主分支之外,我们还有三个分支:
  • JRTB-0
  • JRTB-2
  • JRTB-3
你不会立即明白应该先哪个。所以我将它们重命名如下:
  • STEP_1_JRTB-0 - 第一步
  • STEP_2_JRTB-2 - 第二步
  • STEP_3_JRTB-3 - 第三步
下一篇文章以此类推。要重命名分支,请转到存储库页面,找到分支框,然后按照它操作:“Java 项目从头到尾”:实施应用程序部署 - 2在每个分支下,单击铅笔并重命名分支:“Java 项目从头到尾”:实施应用程序部署 - 3结果我们得到:“Java 项目从头到尾”:实施应用程序部署 - 4顺便说一句,订阅我的电报频道的每个人都发现我立即重命名了分支机构。

关于 Docker 的一些知识

什么是 Docker?简而言之,它是一个工具,您可以使用它快速、安全地部署(部署)应用程序,为它们创建一个仅对它们来说必要的封闭基础设施。还是很难,我理解。总的来说,Docker可以理解为一个可以快速高效工作的开发平台。Docker可以理解为运行在服务器上的程序。该程序能够存储带有应用程序的容器。什么是容器?这是一个独立的基础设施,您可以在其中添加所需的一切。例如,对于Java应用程序,我们需要一个JRE来运行应用程序,容器将有这个,我们将需要一些其他软件 - 我们可以添加这个。或者也许我们需要 Linux 和 Tomcat servlet 容器。这也是可以做到的。容器是基于镜像创建的:也就是说,这是一个特定的模板,其中包含创建 Docker 容器所需的所有内容。如何创建这个图像?在我们的例子中,我们需要在项目的根目录创建一个 Dockerfile 来描述容器中应该包含的内容。由于我们不想在任何地方公开机器人的令牌,因此每次要部署应用程序时都必须传递它。您可以在此处此处阅读有关此主题的更多信息。

我们写JRTB-13

我们需要为我们的应用程序设置一个快速且简单的部署过程到服务器。也就是说,对于一台 24/7 工作的机器。让我们以 Docker 为基础。但我们的列表中没有任务负责添加此功能。不知何故,我在创建它时错过了它。没问题,我们现在就创建它。转到GitHub 上的问题创建选项卡,然后选择功能请求:“Java 项目从头到尾”:实施应用程序部署 - 5添加任务描述、接受标准,设置此问题属于哪个项目,然后您可以创建新问题:“Java 项目从头到尾”:实施应用程序部署 - 6现在,显示任务已被接受对于工作,将任务的状态从“进行中”更改为“待办事项”:“Java 项目从头到尾”:实施应用程序部署 - 7这将是一篇困难的文章。如果有任何问题,请在评论中写下:我会尽力监控并解答。这将是一个小型的客户支持:D

创建 Dockerfile

什么是 dockerfile?对于 Docker,这是一个关于如何为 Docker 容器创建映像的脚本(分步说明)。为了让我们的应用程序正常工作,我们需要 JDK 版本 11。也就是说,我们需要找到 JDK 11 docker 镜像并将其添加到我们的镜像中。这类似于我们向内存添加依赖项的方式。Docker为此提供了DockerHub。要在本地下载图像,您需要在那里注册。注册完成后,我们去寻找JDK11。根据我的发现,这是容器:adoptopenjdk/openjdk11。该容器的描述包含 dockerfile 所需的内容:
FROM adoptopenjdk/openjdk11:ubi
RUN mkdir /opt/app
COPY japp.jar /opt/app
CMD ["java", "-jar", "/opt/app/japp.jar"]
让我们修复从中获取 jar 文件的文件夹。运行 mvn package maven 任务后,我们将其放在目标文件夹中。在完成这一切之前,基于更新的主分支,我们为我们的任务创建一个新分支:STEP_4_JRTB-13。现在你可以工作了。在项目的根目录中,创建一个不带Dockerfile扩展名的文件,并在其中添加以下内容:
FROM adoptopenjdk/openjdk11:ubi
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
第一行是镜像所基于的内容 - 采用openjdk/openjdk11。第二行是向名为 JAR_FILE 的映像添加一个参数,该映像位于目标文件夹中。此外,当前文件夹是由 Dockerfile 的位置确定的。第三行 - 将我们项目的 jar 复制到 docker 镜像中。最后一行本质上包含一个根据终端中的命令创建的数组,该数组以空格分隔。也就是说,最终将执行以下命令:“java -jar /app.jar” 为了使机器人令牌保密,在启动容器时,我们需要传递两个变量 - 机器人的名称及其令牌。为此,我们将编写一个查询,该查询应该使用变量启动我们的项目。以及如何做呢?你需要谷歌它:这是第一个带有正常描述的链接。我们想做什么?我们在 application.properties 文件中定义了两个变量:
  • 机器人用户名
  • 机器人令牌
我想运行一个 docker 容器并每次都将我的值传递到那里,这样就没有人可以看到这些值。我知道在SpringBoot中,jar项目启动时设置的环境变量将优先于application.properties文件中的环境变量。要在请求中传递变量,您需要添加以下结构:-D{变量名称}=”{变量值}”。我们不添加大括号;)我们将收到一个请求,该请求将使用预定义值启动我们的应用程序 - 机器人的名称和令牌: java -jar -Dbot.username=”test.javarush.community_bot” -Dbot。 token=”dfgkdjfglkdjfglkdjfgk” *.jar 现在我们需要在 docker 容器内传递这些变量。这是一个环境变量。为了确保将来我们的数据库顺利运行并且我们的应用程序不会出现问题,我们将使用 docker-compose。这是一个单独的工具,您可以在其中组织容器之间的工作、启动和依赖关系。换句话说,它是 Docker 之上的一个附加组件,用于管理一个基础设施的容器。另外,在运行 docker-compose 之前,我们需要确保已从服务器中提取所有代码更改、构建应用程序并停止旧版本。为此,我们将使用 bash 脚本。哇...这听起来很困难,我同意。但设置应用程序部署始终是一个乏味且复杂的过程。因此,我们有一个非常好的方案:
  1. 让我们运行 bash 脚本。
  2. bash 脚本运行 docker-compose。
  3. Docker-compose 使用我们的应用程序启动一个 docker 容器。
  4. Docker 容器运行我们的应用程序。
现在我们需要确保两个变量 - 机器人的名称及其令牌 - 从点 1 到点 4。以便在启动我们的 java 应用程序时使用这两个变量。让我们从结尾到开头。我们已经知道需要执行什么命令来启动 jarnik。因此,我们将配置 Dockerfile,以便它学习接受两个变量并将它们传递给请求。为此,我们将 Dockerfile 简化为以下形式:
FROM adoptopenjdk/openjdk11:ubi
ARG JAR_FILE=target/*.jar
ENV BOT_NAME=test.javarush_community_bot
ENV BOT_TOKEN=1375780501:AAE4A6Rz0BSnIGzeu896OjQnjzsMEG6_uso
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-Dbot.username=${BOT_NAME}", "-Dbot.token=${BOT_TOKEN}", "-jar", "/app.jar"]
您可以看到我们添加了两行并更新了 ENTRYPOINT。线路:
ENV BOT_NAME=test.javarush_community_bot
ENV BOT_TOKEN=1375780501:AAE4A6Rz0BSnIGzeu896OjQnjzsMEG6_uso
在编码器文件中声明变量。默认情况下,它们有一个指定的值。如果从这个dockerfile创建镜像时,传递了这样名字的环境变量,那么值就会不同。在 ENTRYPOINT 中,我们添加了更多元素来读取这些环境变量:
"-Dbot.username=${BOT_NAME}", "-Dbot.token=${BOT_TOKEN}"
在这里您可以看到,在该行内部,使用 ${} 构造,将传递 BOT_NAME 和 BOT_TOKEN 的值。接下来,我们需要教授如何接收这些变量并将其传递给 docker-compose。

创建 docker-compose.yml

你最好单独阅读 YAML 格式,否则这篇文章已经突飞猛进了。对于我们来说,这只是 .properties 类型变量的另一种描述。仅在属性中,它是通过点编写的,但在 YAML 中,这样做得更漂亮一些。例如,像这样。.properties 中的两个变量: javarush.telegram.bot.name=ivan javarush.telegram.bot.token=pupkin 但在 .yaml 中(与 .yml 相同)它将是这样的:
javarush:
	telegram:
		bot:
		  name: ivan
		  token: pupkin
第二种选择更美观、更容易理解。空格应完全如上所示。让我们以某种方式翻译我们的 application.properties 和 application.yml 。首先您需要创建它。在项目的根目录中,创建一个文件docker-compose.yml并在其中写入以下内容:
version: '3.1'

services:
 jrtb:
   build:
     context: .
   environment:
     - BOT_NAME=${BOT_NAME}
     - BOT_TOKEN=${BOT_TOKEN}
   restart: always
第一行是 docker-compose 版本。 services:表示此后的所有以下行(将被转移)引用我们正在配置的服务。到目前为止,我们只有其中一个 - 一个名为jrtb的 Java 应用程序。在它的下面已经是它的所有设置。例如,构建:上下文:。表示我们将在与 docker-compose.yml 相同的目录中查找 Dockerfile。但环境:部分将负责确保我们将必要的环境变量传递给 Dockerfile。正是我们所需要的。因此,我们在下面传递变量。Docker-compose 会在服务器运行环境变量中寻找它们。让我们将它们添加到 bash 脚本中。

创建 bash 脚本

最后一步是创建 bash 脚本。在项目的根目录中创建一个名为 start.sh 的文件,并在其中写入以下内容:
#!/bin/bash

# Pull new changes
git pull

# Prepare Jar
mvn clean
mvn package

# Ensure, that docker-compose stopped
docker-compose stop

# Add environment variables
export BOT_NAME=$1
export BOT_TOKEN=$2

# Start new deployment
docker-compose up --build -d
所有 bash 脚本都需要第一行:没有它它将无法工作。然后 - 只需在终端中执行一组命令即可。我在每个命令中添加了注释,因此应该很清楚。我唯一想解释的是$1和$2是什么意思。这是启动 bash 脚本时将传递的两个变量。使用导出命令,它们将被添加到服务器变量中并在 docker-compose 中读取。这适用于 Ubuntu,可能不适用于 Windows,但我不确定。现在您需要添加 stop.sh 脚本,这将停止工作。它将包含几行:
#!/bin/bash

# Ensure, that docker-compose stopped
docker-compose stop

# Ensure, that the old application won't be deployed again.
mvn clean
在这里,我们停止 docker-compose 并清理项目 jarnik,该项目自上次构建以来一直存在。我们这样做是为了确保我们的项目能够准确地重建。有先例,这就是我添加的原因)结果,我们最终得到了 4 个新文件:
  • Dockerfile - 用于创建应用程序映像的文件;
  • docker-compose.yml - 一个文件,其中包含我们如何启动容器的设置;
  • start.sh - 用于部署我们的应用程序的 bash 脚本;
  • stop.sh 是一个用于停止我们的应用程序的 bash 脚本。
我们还将应用程序的版本从 0.2.0-SNAPSHOT 更新到 0.3.0-SNAPSHOT。让我们向 RELEASE_NOTES 添加新版本的描述,并稍微重构一下其中的内容:
# 发行说明 ## 0.3.0-SNAPSHOT * JRTB-13:向项目添加部署过程 ## 0.2.0-SNAPSHOT * JRTB-3:实现用于处理 Telegram Bot 命令的命令模式 ## 0.1.0-SNAPSHOT * JRTB -2:添加存根电报机器人 * JRTB-0:添加 SpringBoot 骨架项目
在自述文件中,我们将添加一个新段落来描述如何部署我们的应用程序:
## 部署 部署过程尽可能简单: 所需软件: - 用于运行 bash 脚本的终端 - docker - docker-compose 部署应用程序,切换到所需分支并运行 bash 脚本: $ bash start.sh ${bot_username} ${bot_token } 就这样。
当然,一切都是用英文写的。像往常一样,在我们新创建的分支 STEP_4_JRTB-13 中,我们创建一个名为:JRTB-13 的新提交:通过 docker 实现部署过程并推送它。我不再详细讨论我在之前的文章中已经描述过的事情。我不认为重复同样的事情有什么意义。再说了,那些自己想出来并做过的人不会有任何疑问。这是我谈论如何创建新分支,如何创建提交,如何将提交推送到存储库。

底线

今天,我展示了大量新信息,需要仔细考虑并通过额外阅读进行扩展。最重要的事情:在一个(!!!)命令的帮助下,部署我们的应用程序所需的一切都将完成。这太酷了,我什至无法告诉你。是的,我必须在 Docker 文档中花费大量时间来了解如何正确转发变量。从现在开始,电报机器人将始终在分支的最新版本上运行。 链接到电报机器人。 今天,将不再有适合阅读的材料链接:责任在于您。你需要学会搜索信息。每个订阅我的电报频道的人几乎立即就了解到了机器人的部署。朋友们,你们喜欢这个项目吗?给他一颗星星!这样它就会变得更受欢迎,更多的人能够了解它并从中学习。 像往常一样,我建议在 GitHub 上注册并关注我的帐户,以关注本系列以及我在那里从事的其他项目。 现在我们准备连接数据库了。下一篇文章会更长,我们将在其中完成使用数据库所需的一切。所有描述均在JRTB-1中。

该系列所有材料的列表位于本文开头。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION