使用Docker将现有应用程序推送到某些容器中

我终于回过头来学习如何在不使用Docker的情况下了解如何使用Docker。 这是我尝试使用Docker的第一篇文章,可能是我每次启动新项目(无论如何针对Java或Kotlin)时所指的内容。

这将是一篇简短的文章,它采用一个现有项目(来自我的其他文章之一)并对其进行更改,以便可以在容器内部运行。 我怀疑这篇文章是否会包含任何令人印象深刻的内容,但我知道它将对将来有所帮助,也许现在会对您有所帮助。

在开始之前,让我们看一下现有项目。 这里是代码链接和相应的博客文章 。 该博客文章涵盖了有关代码的所有信息。 这是快速的总结,因此我们可以继续这篇文章。 旧项目是一个带有MongoDB数据库和ActiveMQ消息队列的Spring Boot应用程序。 所有这些成分都是集装箱化的主要饲料。

码头工人

对于本文的内容,最后一句话是,我假设您已经安装了Docker或可以自己弄清楚如何安装。

转换Spring App

首先,是Spring Boot应用程序。

这是包含我们的代码的项目的唯一部分。 剩下的只是从别人的存储库下载的图像。 要开始将此应用程序移到在容器中运行,我们需要创建一个Dockerfile来指定图像的内容:

FROM openjdk:8-jdk-alpine
LABEL maintainer="Dan Newton"
ADD target/spring-boot-jms-tutorial-1.0.0.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app.jar"]

这获取了openjdk:8-jdk-alpine的基础图像,这是应用程序的一个很好的起点,添加了从应用程序代码构建的Jar(将其命名为app.jar ),并公开了容器之间进行通信的端口。 最后一行定义了在容器中运行映像时执行的命令。 这就是启动Spring应用程序的原因。

要从Dockerfile构建映像, Dockerfile运行以下命令(假设您已经构建了应用程序代码):

docker build -t spring-boot-jms-tutorial .

现在有一个名为spring-boot-jms-tutorial的映像( -t让我们定义名称)。 现在,可以使用它来创建一个容器,该容器执行包装在图像Jar中的代码:

docker run --name application -p 4000:8080 spring-boot-jms-tutorial

这将创建并运行一个由spring-boot-jms-tutorial镜像构建的容器。 它命名了容器application ,并且-p属性允许本地计算机上的端口映射到容器内的端口。 要访问容器的端口8080 ,我们只需要在我们自己的计算机上使用端口4000

如果我们停止了该容器并想再次运行它,则应使用以下命令:

docker start application

其中application是我们之前创建的容器的名称。 如果再次使用docker run ,它将创建另一个新容器,而不是重用现有容器。 实际上,由于我们为容器提供了名称,因此从较早版本运行相同的run命令将导致错误。

现在,Spring应用程序已在容器中成功运行,但是日志看起来不太好。 让我们快速浏览一下,以便我们知道下一步需要做什么。

MongoDB连接失败:

Exception in monitor thread while connecting to server mongocontainer:27017

com.mongodb.MongoSocketException: mongocontainer: Name does not resolve
    at com.mongodb.ServerAddress.getSocketAddress(ServerAddress.java:188) ~[mongodb-driver-core-3.6.4.jar!/:na]
    at com.mongodb.connection.SocketStreamHelper.initialize(SocketStreamHelper.java:59) ~[mongodb-driver-core-3.6.4.jar!/:na]
    at com.mongodb.connection.SocketStream.open(SocketStream.java:57) ~[mongodb-driver-core-3.6.4.jar!/:na]
    at com.mongodb.connection.InternalStreamConnection.open(InternalStreamConnection.java:126) ~[mongodb-driver-core-3.6.4.jar!/:na]
    at com.mongodb.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:114) ~[mongodb-driver-core-3.6.4.jar!/:na]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_171]
Caused by: java.net.UnknownHostException: mongocontainer: Name does not resolve
    at java.net.Inet4AddressImpl.lookupAllHostAddr(Native Method) ~[na:1.8.0_171]
    at java.net.InetAddress$2.lookupAllHostAddr(InetAddress.java:928) ~[na:1.8.0_171]
    at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1323) ~[na:1.8.0_171]
    at java.net.InetAddress.getAllByName0(InetAddress.java:1276) ~[na:1.8.0_171]
    at java.net.InetAddress.getAllByName(InetAddress.java:1192) ~[na:1.8.0_171]
    at java.net.InetAddress.getAllByName(InetAddress.java:1126) ~[na:1.8.0_171]
    at java.net.InetAddress.getByName(InetAddress.java:1076) ~[na:1.8.0_171]
    at com.mongodb.ServerAddress.getSocketAddress(ServerAddress.java:186) ~[mongodb-driver-core-3.6.4.jar!/:na]
    ... 5 common frames omitted

ActiveMQ也不存在:

Could not refresh JMS Connection for destination 'OrderTransactionQueue' - retrying using FixedBackOff{interval=5000, currentAttempts=1, maxAttempts=unlimited}. 
Cause: Could not connect to broker URL: tcp://activemqcontainer:61616. 
Reason: java.net.UnknownHostException: activemqcontainer

我们将在下一部分中对这些内容进行整理,以便应用程序可以完整地工作。

在我们着眼于Mongo和ActiveMQ之前,还有最后一件事。

dockerfile-maven-plugin也可以用于帮助上述工作,该工作是在运行mvn install过程中构建容器的。 我选择不使用它,因为无法使其与docker-compose一起正常工作。 以下是使用插件的快速示例:

<build>
    <plugins>
        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>dockerfile-maven-plugin</artifactId>
            <version>1.4.4</version>
            <executions>
                <execution>
                    <id>default</id>
                    <goals>
                        <goal>build</goal>
                        <goal>push</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <!-- Names the image: spring-boot-jms-tutorial -->
                <repository>${project.artifactId}</repository>
                <buildArgs>
                    <JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
                </buildArgs>
            </configuration>
        </plugin>
    </plugins>
</build>

然后,这使我们可以替换Dockerfile的几行:

FROM openjdk:8-jdk-alpine
LABEL maintainer="Dan Newton"
ARG JAR_FILE 
ADD target/${JAR_FILE} app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app.jar"]

此处添加了一行,更改了一条现有行。 JAR_FILE参数替换了插件从pom.xml插入的Jar的原始名称。 进行这些更改,然后运行mvn install和bam,您的容器将使用所有必需的代码构建。

使用MongoDB映像

MongoDB映像已准备就绪,正在等待我们使用。 它的理想名称是mongo …您还期望什么? 我们需要做的就是run图像,并为其命名一个容器:

docker run -d --name mongocontainer mongo

添加-d将在后台运行容器。 容器的名称不仅是为了方便起见,因为Spring应用程序以后将需要它来连接到Mongo。

到ActiveMQ映像上

设置ActiveMQ就像Mongo一样简单。 运行以下命令:

docker run -d --name activemqcontainer -p 8161:8161 rmohr/activemq

这里的8161端口是从容器映射到运行它的计算机,从而允许从容器外部访问管理控制台。

绑在一起

如果您在阅读mongocontainer文章时一直在运行所有这些命令,则您会注意到application容器实际上还无法看到mongocontaineractivemqcontainer 。 这是因为它们不在同一网络中运行。 让他们进行交流并不困难,并且只需采取一些额外的步骤。

默认情况下,Docker在进行设置时无需任何额外配置即可创建网桥网络。 以下是操作方法:

docker network create network

现在已经创建了网络(名为network ),需要更改先前运行的命令以创建将连接到网络的容器。 以下是前几节中用于创建容器的3个命令,每个命令都进行了更改以加入网络。

docker run -d --name mongocontainer --network=network mongo
docker run -d --name activemqcontainer -p 8161:8161 --network=network rmohr/activemq
docker run --name application -p 4000:8080 --network=network spring-boot-jms-tutorial

一旦所有这些都运行,整个应用程序现在就可以运行了。 每个容器可以看到对方。 允许application容器在各自的容器中连接到MongoDB和ActiveMQ。

至此,一切正常。 它的运行方式与我记得自己在笔记本电脑上完成所有设置后就可以运行一样。 但是,这次,本地没有任何设置……除了Docker!

Docker组成

我们可能已经在这里停了下来,但是下一节将使一切运行变得更加容易。 Docker Compose使我们能够有效地将之前运行的所有命令集中在一起,并在一个命令中启动所有容器及其网络。 显然,还有更多的设置,但是最后,我认为键入的数量实际上减少了。

为此,我们需要创建一个docker-compose.yml文件:

version: '3'
services:
  appcontainer:
    build:
      context: .
      args:
        JAR_FILE: /spring-boot-jms-tutorial-1.0.0.jar
    ports:
    - "4000:8080"
  activemqcontainer:
    image: "rmohr/activemq"
    ports:
    - "8161:8161"
  mongocontainer:
image: "mongo"

与此版本的Dockerfile

FROM openjdk:8-jdk-alpine
LABEL maintainer="Dan Newton"
ARG JAR_FILE 
ADD target/${JAR_FILE} app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app.jar"]

这几乎是需要做的所有事情。

appcontainer是根据项目代码构建的Spring应用程序容器。 容器的build属性告诉Docker根据项目根目录中找到的项目Dockerfile构建映像。 它将JAR_FILE参数传递给JAR_FILEDockerfile将一些配置移入该文件。

其他两个容器不需要太多设置。 与前面的命令一样,它们的生成映像已指定, activemqcontainer在其映射端口周围添加了配置。

最后的配置发生在后台。 创建一个网络,并将所有容器添加到其中。 这样就无需手动创建网络。

剩下要做的就是运行up命令:

docker-compose up

这将构建并运行所有容器。 如有必要,将构建应用程序代码映像。 运行此确切命令会将所有容器日志输出到控制台,为此在后台添加-d标志:

docker-compose up -d

这样做之后,我们可以查看创建的容器和网络。 运行:

docker ps -a --format "table {{.Image}}\t{{.Names}}"

显示给我们:

IMAGE                          NAMES
mongo                          spring-boot-jms_mongocontainer_1
spring-boot-jms_appcontainer   spring-boot-jms_appcontainer_1
rmohr/activemq                 spring-boot-jms_activemqcontainer_1

和网络:

docker network ls

产生:

NETWORK ID          NAME                      DRIVER              SCOPE
163edcfe5ada        spring-boot-jms_default   bridge              local

容器和网络的名称在项目名称之前。

结论

这就是全部内容……无论如何,对于一个简单的设置,我敢肯定Docker之神还可以做更多的事情,但我不是其中之一...然而。

最后,我们采用了一个我编写的现有应用程序,以便在计算机上本地工作,并将所有内容都放入了几个容器中。 这意味着我们从一台需要进行所有设置的机器开始,同时安装了MongoDB和ActiveMQ。 取而代之的是,一台可以通过使用容器而只需要安装Docker即可跳过所有这些操作的机器。 Docker然后为我们管理所有依赖项。

我们研究了如何将应用程序的每个部分移动到一个容器中,然后将它们与Docker Compose捆绑在一起。 最后,只剩下一条命令就可以让我们从绝对的工作转移到运行该应用程序所需的一切。

这篇文章中使用的代码可以在我的GitHub上找到

如果您认为这篇文章有帮助,可以在Twitter上@LankyDanDev关注我,以跟上我的新文章。

翻译自: https://www.javacodegeeks.com/2018/09/docker-existing-application-containers.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值