使用容器进行开发

预计阅读时间:9分钟

先决条件

“将图像作为容器运行”中完成构建图像并将其作为容器化应用程序运行的步骤。

介绍

在本模块中,我们将逐步为在先前模块中构建的应用程序建立本地开发环境。我们将使用Docker来构建映像,并使用Docker Compose来简化所有工作。

在容器中运行数据库

首先,我们将研究如何在容器中运行数据库,以及如何使用卷和网络来持久化数据并允许我们的应用程序与数据库进行通讯。然后,我们将所有内容汇总到一个Compose文件中,该文件使我们可以使用一个命令来设置和运行本地开发环境。最后,我们将看一下如何将调试器连接到在容器内运行的应用程序。

我们可以使用MySQL的Docker Official Image并在容器中运行它,而无需下载MySQL,安装,配置然后运行MySQL数据库作为服务。

在容器中运行MySQL之前,我们将创建几个卷,Docker可以管理这些卷来存储我们的持久数据和配置。让我们使用Docker提供的托管卷功能,而不是使用绑定安装。您可以在我们的文档中阅读有关使用卷的所有信息。

现在创建卷。我们将为数据创建一个,为MySQL配置创建一个。

$ docker volume create mysql
$ docker volume create mysql_config

现在,我们将创建一个网络,我们的应用程序和数据库将使用该网络互相通信。该网络称为用户定义的桥接网络,它为我们提供了很好的DNS查找服务,可在创建连接字符串时使用该服务。

$ docker network create mysqlnet

现在,让我们在容器中运行MySQL,并将其附加到上面创建的卷和网络上。Docker从Hub提取映像并在本地运行。

$ docker run -it --rm -d -v mysql_data:/var/lib/mysql \
-v mysql_config:/etc/mysql/conf.d \
--network mysqlnet \
--name mysqlserver \
-e MYSQL_USER=petclinic -e MYSQL_PASSWORD=petclinic \
-e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=petclinic \
-p 3306:3306 mysql:8.0.23

好的,现在我们有了一个正在运行的MySQL,让我们更新Dockerfile来激活应用程序中定义的MySQL Spring配置文件,并从内存中的H2数据库切换到我们刚刚创建的MySQL服务器。

我们只需要添加MySQL配置文件作为CMD定义的参数即可。

CMD ["./mvnw", "spring-boot:run", "-Dspring-boot.run.profiles=mysql"]

让我们树立形象

$ docker build --tag java-docker .

现在,让我们运行容器。这次,我们需要设置MYSQL_URL环境变量,以便我们的应用程序知道要使用哪个连接字符串来访问数据库。我们将使用docker run命令来执行此操作。

$ docker run --rm -d \
--name springboot-server \
--network mysqlnet \
-e MYSQL_URL=jdbc:mysql://mysqlserver/petclinic \
-p 8080:8080 java-docker

让我们测试一下我们的应用程序已连接到数据库并能够列出兽医。

$ curl  --request GET \
  --url http://localhost:8080/vets \
  --header 'content-type: application/json'

您应该从我们的服务中收到以下json。

{"vetList":[{"id":1,"firstName":"James","lastName":"Carter","specialties":[],"nrOfSpecialties":0,"new":false},{"id":2,"firstName":"Helen","lastName":"Leary","specialties":[{"id":1,"name":"radiology","new":false}],"nrOfSpecialties":1,"new":false},{"id":3,"firstName":"Linda","lastName":"Douglas","specialties":[{"id":3,"name":"dentistry","new":false},{"id":2,"name":"surgery","new":false}],"nrOfSpecialties":2,"new":false},{"id":4,"firstName":"Rafael","lastName":"Ortega","specialties":[{"id":2,"name":"surgery","new":false}],"nrOfSpecialties":1,"new":false},{"id":5,"firstName":"Henry","lastName":"Stevens","specialties":[{"id":1,"name":"radiology","new":false}],"nrOfSpecialties":1,"new":false},{"id":6,"firstName":"Sharon","lastName":"Jenkins","specialties":[],"nrOfSpecialties":0,"new":false}]}

使用Compose进行本地开发

在本节中,我们将创建一个Compose文件以java-docker使用单个命令启动我们的数据库和MySQL数据库。我们还将设置Compose文件以java-docker在调试模式下启动应用程序,以便我们可以将调试器连接到正在运行的Java进程。

petclinic在您的IDE或文本编辑器中打开,然后创建一个名为的新文件docker-compose.dev.yml。将以下命令复制并粘贴到文件中。

version: '3.8'
services:
  petclinic:
    build:
      context: .
    ports:
      - 8000:8000
      - 8080:8080
    environment:
      - SERVER_PORT=8080
      - MYSQL_URL=jdbc:mysql://mysqlserver/petclinic
    volumes:
      - ./:/app
    command: ./mvnw spring-boot:run -Dspring-boot.run.profiles=mysql -Dspring-boot.run.jvmArguments="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000"

  mysqlserver:
    image: mysql:8.0.23
    ports:
      - 3306:3306
    environment:
      - MYSQL_ROOT_PASSWORD=
      - MYSQL_ALLOW_EMPTY_PASSWORD=true
      - MYSQL_USER=petclinic
      - MYSQL_PASSWORD=petclinic
      - MYSQL_DATABASE=petclinic
    volumes:
      - mysql_data:/var/lib/mysql
      - mysql_config:/etc/mysql/conf.d
volumes:
  mysql_data:
  mysql_config:

这个Compose文件非常方便,因为我们不必键入所有参数即可传递给docker run命令。我们可以使用Compose文件声明性地做到这一点。

我们公开端口8000并声明JVM的调试配置,以便我们可以附加调试器。

使用Compose文件的另一个非常酷的功能是我们设置了服务解析以使用服务名称。因此,我们现在可以mysqlserver在连接字符串中使用。我们使用mysqlserver它的原因是因为这就是我们在Compose文件中命名的MySQL服务的名称。

现在,启动我们的应用程序并确认其运行正常。

$ docker-compose -f docker-compose.dev.yml up --build

我们传递该--build标志,以便Docker将编译我们的映像,然后启动容器。如果成功运行,您应该会看到类似的输出:

Java Compose输出

现在让我们测试我们的API端点。运行以下curl命令:

$ curl  --request GET \
  --url http://localhost:8080/vets \
  --header 'content-type: application/json'

您应该收到以下回复:

{"vetList":[{"id":1,"firstName":"James","lastName":"Carter","specialties":[],"nrOfSpecialties":0,"new":false},{"id":2,"firstName":"Helen","lastName":"Leary","specialties":[{"id":1,"name":"radiology","new":false}],"nrOfSpecialties":1,"new":false},{"id":3,"firstName":"Linda","lastName":"Douglas","specialties":[{"id":3,"name":"dentistry","new":false},{"id":2,"name":"surgery","new":false}],"nrOfSpecialties":2,"new":false},{"id":4,"firstName":"Rafael","lastName":"Ortega","specialties":[{"id":2,"name":"surgery","new":false}],"nrOfSpecialties":1,"new":false},{"id":5,"firstName":"Henry","lastName":"Stevens","specialties":[{"id":1,"name":"radiology","new":false}],"nrOfSpecialties":1,"new":false},{"id":6,"firstName":"Sharon","lastName":"Jenkins","specialties":[],"nrOfSpecialties":0,"new":false}]}

连接调试器

我们将使用IntelliJ IDEA附带的调试器。您可以使用此IDE的社区版本。在IntelliJ IDEA中打开您的项目,然后转到“运行”菜单>“编辑配置”。添加类似于以下内容的新的远程JVM调试配置:

Java连接调试器

让我们设置一个断点

打开以下文件,src/main/java/org/springframework/samples/petclinic/vet/VetController.java并在showResourcesVetList函数内部添加断点,例如,第54行。

开始您的调试会话,运行菜单,然后调试NameOfYourConfiguration

调试菜单

现在,您应该在Compose应用程序的日志中看到该连接。

撰写日志文件

现在,我们可以调用服务器端点了。

$ curl --request GET --url http://localhost:8080/vets

您应该已经在第54行看到了代码中断,现在您可以像平常一样使用调试器了。您还可以检查和监视变量,设置条件断点,查看堆栈跟踪以及执行其他操作。

调试器代码断点

您还可以激活SpringBoot Dev Tools提供的实时重载选项。请查看SpringBoot文档,以获取有关如何连接到远程应用程序的信息。

下一步

在本模块中,我们看了如何创建一个通用开发映像,该映像可以像正常命令行一样使用。我们还设置了Compose文件以暴露调试端口,并将Spring Boot配置为实时重新加载我们的更改。

在下一个模块中,我们将看一下如何在Docker中运行单元测试。看

运行测试

反馈

通过提供您的反馈帮助我们改善此主题。通过在Docker Docs GitHub存储库中创建问题,让我们知道您的想法。或者,创建PR以建议更新。

Java本地开发运行