Spring Boot + docker-compose + MySQL:连接被拒绝

Raf*_*nto 8 java mysql docker spring-boot docker-compose

我正在尝试设置一个 Spring Boot 应用程序,该应用程序依赖于 docker-compose 中名为teste的 MySQL 数据库。发出docker-compose up 后,我得到:

Caused by: java.net.ConnectException: Connection refused (Connection refused)
Run Code Online (Sandbox Code Playgroud)

我在 Linux Mint 上运行,我的docker-compose 版本是 1.23.2,我的docker 版本是 18.09.0

应用程序属性

# JPA PROPS
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy

spring.datasource.url=jdbc:mysql://db:3306/teste?useSSL=false&serverTimezone=UTC
spring.datasource.username=rafael
spring.datasource.password=password

spring.database.driverClassName =com.mysql.cj.jdbc.Driver
Run Code Online (Sandbox Code Playgroud)

docker-compose.yml

version: '3.5'
services:
  db:
    image: mysql:latest
    environment:
      - MYSQL_ROOT_PASSWORD=rootpass
      - MYSQL_DATABASE=teste      
      - MYSQL_USER=rafael
      - MYSQL_PASSWORD=password
    ports:
      - 3306:3306
  web:
    image: spring-mysql
    depends_on:
      - db
    links:
      - db
    ports:
      - 8080:8080
    environment:
      - DATABASE_HOST=db
      - DATABASE_USER=rafael
      - DATABASE_NAME=teste
      - DATABASE_PORT=3306
Run Code Online (Sandbox Code Playgroud)

和 Dockerfile

FROM openjdk:8
ADD target/app.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
Run Code Online (Sandbox Code Playgroud)

提前致谢!

小智 6

我遇到了同样的问题,如果您不想使用任何自定义脚本,可以使用运行状况检查和依赖项轻松解决此问题。使用这些的示例如下:

services:
  mysql-db:
    image: mysql
    environment:
      - MYSQL_ROOT_PASSWORD=vikas1234
      - MYSQL_USER=vikas
    ports:
      - 3306:3306
    restart: always
    healthcheck:
      test: [ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ]
      timeout: 20s
      retries: 10

  app:
    image: shop-keeper
    container_name: shop-keeper-app
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 8080:8080
    depends_on:
      mysql-db:
        condition: service_healthy
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql-db:3306/shopkeeper?createDatabaseIfNotExist=true
      SPRING_DATASOURCE_USERNAME: root
      SPRING_DATASOURCE_PASSWORD: vikas1234
Run Code Online (Sandbox Code Playgroud)


Han*_*ena 5

Docker compose 始终按依赖顺序或文件中的顺序(如果未给出)启动和停止容器。但 docker-compose 不保证它会等到依赖容器运行。您可以参考这里了解更多详情。所以这里的问题是当你的spring-mysql容器尝试访问数据库时你的数据库还没有准备好。因此,推荐的解决方案是您可以使用wait-for-it.sh或类似的脚本来包装您的spring-mysql应用程序ENTRYPOINT

例如,如果您在 Dockerfile 中使用,wait-for-it.shENTRYPOINT在将上述脚本复制到项目根目录后应更改为以下内容:

ENTRYPOINT ["./wait-for-it.sh", "db:3306", "--", "java", "-jar", "app.jar"]
Run Code Online (Sandbox Code Playgroud)

这里需要考虑的另外两件重要事情是:

  • 不要使用它们已被弃用的链接,您应该使用用户定义的网络。如果您没有明确定义任何网络,docker-compose 文件中的所有服务都将位于单个用户定义的网络中。因此,您只需从撰写文件中删除链接即可。
  • 如果您仅在用户定义的网络中使用 docker 容器,则无需发布它的端口。


gra*_*pes 1

你的配置看起来不错,我只是推荐:

  • 消除links: dbuser-defined bridge它在网络中没有任何价值
  • 除非您想从外部连接,否则删除数据库公开的端口docker-compose- 所有端口都会在网络内部自动公开user-defined bridge

我认为问题在于数据库容器比 Web 需要更多的时间来启动。depends_on只是控制顺序,但不能保证您的数据库准备就绪。如果可能,请设置多次连接尝试或将套接字等待过程放入 Web 容器中。