解决项目容器启动时MySQL端口检测的问题

要解决容器启动时MySQL端口检测的问题,用脚本轮询并检测端口可用性是完全可行的。将下面的示例脚本替代Dockerfile或启动脚本中原来的sleep 15命令即可。

方案一:使用 netcat (nc) 命令轮询(推荐)

nc 是最常用且最可靠的工具。如果容器中没有,可以在构建镜像时安装。

  1. 检查端口脚本

    将以下脚本保存到容器内(例如 /wait-for-mysql.sh)并赋予执行权限:

    bash 复制代码
    #!/bin/sh
    # wait-for-mysql.sh
    
    host="$1"
    port="$2"
    shift 2
    cmd="$@"
    
    echo "正在等待 MySQL ($host:$port) 启动..."
    
    while ! nc -z $host $port; do
      sleep 3
    done
    
    echo "MySQL 已就绪,启动应用..."
    exec $cmd
  2. 在启动命令中使用

    修改你的Docker启动命令,替换掉原来的sleep 15

    bash 复制代码
    # 原命令 (使用睡眠):
    # CMD nginx; echo "Waiting for MySQL to start..."; sleep 15; java -jar /app/api/app.jar ...
    
    # 新命令 (使用轮询):
    CMD nginx; /wait-for-mysql.sh mysql 3306 java -jar /app/api/app.jar --spring.profiles.active=prod --spring.datasource.url="jdbc:mysql://${DB_HOST}:${DB_PORT:-3306}/${DB_NAME}?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true" --spring.datasource.username=${DB_USER} --spring.datasource.password=${DB_PASS} --sa-token.is-concurrent=${SA_TOKEN_IS_CONCURRENT:-false} --sa-token.jwt-secret-key=${SA_TOKEN_JWT_SECRET_KEY}

    脚本逻辑 :脚本会在 while 循环中每隔 sleep 3 秒,使用 nc -z 尝试连接 mysql:3306。成功后,再执行后面的Java启动命令 (exec $cmd)。

方案二:使用 bash 内置的 /dev/tcp(无需额外工具)

如果容器环境(如Alpine基础镜像)没有安装 nc,并且不便安装,可以利用bash内置的 /dev/tcp 伪设备。

  1. 检查端口脚本

    将以下脚本保存到容器内:

    bash 复制代码
    #!/bin/bash
    # wait-for-mysql-tcp.sh
    
    host="$1"
    port="$2"
    shift 2
    cmd="$@"
    
    echo "正在等待 MySQL ($host:$port) 启动..."
    
    until bash -c "(echo > /dev/tcp/$host/$port) >/dev/null 2>&1"; do
        sleep 3
    done
    
    echo "MySQL 已就绪,启动应用..."
    exec $cmd
  2. 启动命令

    修改启动命令,调用这个脚本,用法与方案一相同。

关键点说明

特性/方案 使用 netcat (nc) 使用 /dev/tcp
原理 使用网络工具 nc-z 参数进行端口扫描。 利用 bash 的 /dev/tcp 伪文件系统进行 TCP 连接。
依赖 需要安装 netcat-openbsdnmap-ncat 包。 仅依赖 bash(多数镜像已包含)。
优点 语法标准,功能明确,最常用。 无需额外安装任何包,脚本简洁。
潜在缺点 部分极简基础镜像可能未预装。 需要 Bash 环境,若容器使用 sh 可能不支持。

实施建议

  1. 选择方案 :如果你的镜像基于 alpine,建议使用方案二(/dev/tcp) ,因为安装 nc 会增加镜像大小。如果是 ubuntudebian 等较完整的镜像,两个方案都可行,使用 nc 的命令更直观。

  2. 修改 Dockerfile :确保将上述脚本复制到镜像中,并在 CMD 指令中使用。

    dockerfile 复制代码
    # 以方案一为例,需在Dockerfile中安装nc并复制脚本
    FROM your-base-image
    # 安装netcat (例如在基于Debian的镜像中)
    RUN apt-get update && apt-get install -y netcat-openbsd && rm -rf /var/lib/apt/lists/*
    # 复制等待脚本
    COPY wait-for-mysql.sh /usr/local/bin/
    RUN chmod +x /usr/local/bin/wait-for-mysql.sh
    # 修改启动命令
    CMD ["sh", "-c", "nginx; wait-for-mysql.sh mysql 3306 java -jar /app/api/app.jar ..."]

这个方案能精确控制等待时机,解决了固定时间可能过长或过短的问题。如果你需要根据特定基础镜像(例如Alpine)调整Dockerfile的安装步骤,可以告诉我,我能提供更具体的修改建议。

相关推荐
wjhx19 小时前
QT中对蓝牙权限的申请,整理一下
java·数据库·qt
冰暮流星20 小时前
javascript之二重循环练习
开发语言·javascript·数据库
万岳科技系统开发20 小时前
食堂采购系统源码库存扣减算法与并发控制实现详解
java·前端·数据库·算法
冉冰学姐20 小时前
SSM智慧社区管理系统jby69(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·管理系统·智慧社区·ssm 框架
杨超越luckly20 小时前
HTML应用指南:利用GET请求获取中国500强企业名单,揭秘企业增长、分化与转型的新常态
前端·数据库·html·可视化·中国500强
斯普信专业组20 小时前
构建基于MCP的MySQL智能运维平台:从开源服务端到交互式AI助手
运维·mysql·开源·mcp
Elastic 中国社区官方博客21 小时前
Elasticsearch:Workflows 介绍 - 9.3
大数据·数据库·人工智能·elasticsearch·ai·全文检索
仍然.21 小时前
MYSQL--- 聚合查询,分组查询和联合查询
数据库
一 乐21 小时前
校园二手交易|基于springboot + vue校园二手交易系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端
啦啦啦_999921 小时前
Redis-0-业务逻辑
数据库·redis·缓存