You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker容器运行Java程序报Scanner异常及MySQL连接问题咨询

Docker部署Java Socket程序异常排查及MySQL接入方案

异常根因

你遇到的客户端java.util.NoSuchElementException: No line found、服务端java.io.EOFException本质是Socket连接建立后被异常断开,两端读取输入流时直接读到流末尾,没有获取到有效数据,具体触发原因有5个:

  • Docker端口配置错误:Dockerfile里的EXPOSE 1000仅做端口声明,不做宿主机和容器的端口映射,启动容器时如果没加端口映射参数,宿主机上的客户端根本访问不到容器内的服务,连接会被直接重置。
  • 容器内网络寻址错误:服务端代码中写死访问localhost:1001~localhost:1005的后端服务,Docker容器内的localhost指向容器自身的内部网络,不是宿主机或其他容器的地址,APIGateway容器根本连不上其他后端服务,导致连接断开。
  • Dockerfile打包逻辑错误:当前Dockerfile注释掉了APIGateway服务端jar包的复制逻辑,实际复制启动的是客户端jar包,容器跑起来根本没有监听1000端口的服务端。
  • 代码逻辑bug:客户端代码中case "5"(上传文件)、case "6"(下载文件)分支末尾没有加break,会出现switch分支穿透,执行完文件传输逻辑后会继续执行后续的退出、默认分支,导致程序异常退出。另外客户端硬编码了Windows绝对路径C:\\Users\\Czarek\\...,跨环境运行会直接找不到文件。
  • 如果把客户端也放在容器中运行,没有加交互式终端参数启动,容器不会分配标准输入,Scanner读取System.in时会直接读到流末尾,触发NoSuchElementException。

修复步骤

  1. 修正服务端Dockerfile配置:
# syntax=docker/dockerfile:1
FROM openjdk:17-alpine
WORKDIR /app
# 复制服务端编译产出的jar包,路径对应你本地out目录下的服务端jar位置
COPY /out/artifacts/Tech_jar/Tech.jar ./app.jar
EXPOSE 1000
ENTRYPOINT ["java", "-jar", "./app.jar"]
  1. 构建镜像并启动服务端容器,必须加端口映射参数将容器1000端口绑定到宿主机1000端口:
docker build -t socket-api-gateway .
docker run -d -p 1000:1000 --name api-gateway socket-api-gateway
  1. 修复服务端内网访问地址:
    • 如果1001~1005端口的后端服务跑在宿主机上,Windows/Mac版Docker直接将代码中所有new Socket("localhost", 端口)的localhost替换为host.docker.internal即可访问宿主机服务;Linux环境启动容器时额外加--add-host=host.docker.internal:host-gateway参数,再替换地址即可。
    • 如果所有后端服务都要容器化部署,先创建自定义Docker网桥:
      docker network create socket-service-net
      
      所有服务启动时都加入这个网桥,代码中直接用服务的容器名作为访问地址即可(比如登录服务容器名叫login-service,就写new Socket("login-service", 1001)),容器间会通过内置DNS自动解析互通,不需要额外映射端口到宿主机。
  2. 修复客户端代码bug:给case "5"、case "6"分支末尾补上break;,删掉硬编码的Windows绝对路径,改用相对路径或启动参数传入文件存储路径。客户端建议直接在本地IntelliJ运行,不需要放到容器里,直接连接localhost:1000即可正常交互;如果一定要容器化运行客户端,启动时必须加-it参数分配交互式终端:
    docker run -it --rm --network socket-service-net 客户端镜像名
    

MySQL接入Docker集群方案

  1. 启动MySQL容器,加入之前创建的自定义网桥,同时挂载数据卷持久化数据,避免容器删除后数据丢失:
docker run -d \
  --name mysql \
  --network socket-service-net \
  -e MYSQL_ROOT_PASSWORD=你设置的数据库root密码 \
  -e MYSQL_DATABASE=你的项目业务库名 \
  -v mysql-persist-data:/var/lib/mysql \
  mysql:8.0

如果需要本地用数据库客户端连接MySQL调试,启动命令额外加-p 3306:3306参数将端口映射到宿主机即可,生产环境不需要映射这个端口。
2. 修改项目中JDBC连接配置:
- 数据库地址不要写localhost,直接写MySQL的容器名mysql,端口保持默认3306
- 连接串示例:jdbc:mysql://mysql:3306/你的项目业务库名?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
- 用户名填root,密码填启动MySQL容器时设置的MYSQL_ROOT_PASSWORD值
3. 重新构建需要连接数据库的业务服务(登录、注册等)镜像,启动时加入socket-service-net网桥,服务即可正常访问MySQL数据库。

内容的提问来源于stack exchange,提问作者LLager

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 06:12:40