Spring Boot 使用Docker合成时,在基于Sping Boot 的Docker容器启动时应用Liquibase脚本失败

tcomlyy6  于 2023-03-02  发布在  Spring
关注(0)|答案(1)|浏览(113)

我正在尝试使用docker compose在ubuntu(22.04)vm上部署应用程序。应用程序的一部分是Spring Boot映像,用于后端目的。它链接到MySQL数据库容器。在启动Spring Boot应用程序时,应用Liquibase更改日志,其中包含数据库模式和一些数据。
当在我的本地机器(macOS)上运行docker compose时,一切都很好。但是在虚拟机上运行docker compose时,会出现一系列错误消息,这些错误消息与Liquibase无法应用changelog文件有关(据我所知)。我只添加了例外,以节省整个堆栈跟踪。请参见下文。

com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
ConfigServletWebServerApplicationContext : 
Exception encountered during context initialization - 
cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'liquibase' defined in class path resource 
[org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration$LiquibaseConfiguration.class]: 
Invocation of init method failed; 
nested exception is liquibase.exception.DatabaseException: 
com.mysql.cj.jdbc.exceptions.CommunicationsException: 
Communications link failure
org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'liquibase' defined in class path resource 
[org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration$LiquibaseConfiguration.class]: 
Invocation of init method failed; nested exception is liquibase.exception.DatabaseException: 
com.mysql.cj.jdbc.exceptions.CommunicationsException: 
Communications link failure

由于提到他们是一个"通信链接故障",我的第一个想法是,这应该是一个错误的端口Map或一些IP相关的问题之间的Spring Boot容器无法连接到MySQL容器。在后一种情况下,我会想象另一个例外,虽然,提到了一些关于连接无法建立的事情。我在我的/etc/hosts文件中添加了以下行:

172.17.0.1 host.docker.internal

正如在其他帖子中提到的那样,这是"通信链接失败"错误的可能解决方案。然而,错误仍然存在,我最好的猜测是,这与Spring Boot映像缺乏实际的Liquibase更改日志信息有关。我正在尝试将此更改日志信息添加到Dockerfile中,它看起来像这样:

FROM openjdk:17-jdk-slim
WORKDIR /usr/app
ARG JAR_FILE=/build/libs/*.jar
ARG LIQUIBASE=/build/resources/main/db/
COPY $JAR_FILE .
COPY $LIQUIBASE .
ENTRYPOINT ["java", "-jar", "player-pass-backend-0.0.1-SNAPSHOT.jar"]

当运行这个Dockerfile时,在容器的工作目录中会创建一个changelog目录,其中包含liquibase changelog文件。我调整了Spring Boot应用程序的www.example.com中的liquibase类路径url,使其指向这个位置。application.properties文件如下所示:application.properties of the Spring Boot application to point to this location. The application.properties file looks like this:

spring.application.name=player-pass-backend
server.port=3001

spring.datasource.url=jdbc:mysql://host.docker.internal:3306/play_pass_db
spring.datasource.username=someuser
spring.datasource.password=somesecretpassword
spring.liquibase.change-log=classpath:changelog/db.changelog-master.xml

spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect

构建应用程序是通过Docker合成文件完成的:

version: "3"

services:
  player-pass-database:
    container_name: player-pass-db
    image: mysql:8.0.32
    networks:
      - local_net
    env_file:
      - .env-database
    ports:
      - "3306:3306"
    volumes:
      - player-pass-db:/var/lib/mysql
    restart: always
    healthcheck:
      test: ["CMD","mysqladmin","ping","-h","localhost","-uroot","-prootsecretpassword"]
      interval: 5s
      timeout: 5s
      retries: 20

  player-pass-backend:
    container_name: player-pass-backend
    image: jdf90/play-pass-backend
    networks:
      - local_net
    ports:
      - "3001:3001"
    depends_on:
      player-pass-database:
        condition: service_healthy
    restart: on-failure

  player-pass-frontend:
    container_name: player-pass-frontend
    image: jdf90/play-pass
    networks:
      - local_net
    ports:
      - "5173:5173"
    links:
      - player-pass-backend

volumes:
  player-pass-db:

networks:
  local_net:
    name: local_net

我希望有可能将Liquibasechangelog作为SpringBoot应用程序容器启动的一部分来应用。
另一个解决方案是建立一个单独的Liquibase容器,负责应用变更日志,但我更希望尽可能地保持本地环境和虚拟机环境的平衡。

gcmastyq

gcmastyq1#

您应该在container中正确定义数据库的地址。

version: "3"

services:
  # ... other settings
  player-pass-backend:
    container_name: player-pass-backend
    image: jdf90/play-pass-backend
    # ... other settings
    environment:
      - SPRING_DATASOURCE_URL: jdbc:mysql://player-pass-database:3306/play_pass_db

如果上面的方法不起作用,那么就尝试修改你的application.properties,使用如下的默认链接将env变量作为第一个:

spring.datasource.url=${SPRING_DATASOURCE_URL:jdbc:mysql://host.docker.internal:3306/play_pass_db}

有了上面的配置,它应该为您的docker env和mac env都工作。

相关问题