Error response from daemon: Ports are not available: exposing port TCP 0.0.0.0:3306 -> 127.0.0.1:0: listen tcp 0.0.0.0:3306: bind: An attempt was made to access a socket in a way forbidden by its access permissions. PS D:\react\admin-react>
这个错误信息
Ports are not available: ... bind: An attempt was made to access a socket in a way forbidden by its access permissions 表明 端口 3306 已经被你 Windows 主机上的另一个程序占用或被操作系统保留。Docker 无法绑定到该端口。
解决方案
你可以采取以下任一方法解决此问题:
方法一:查找并终止占用端口的程序(推荐)
最常见的原因是你的 Windows 主机上已经安装并运行了本地 MySQL/MariaDB 服务、XAMPP、WAMP 或另一个 Docker 容器。
-
以管理员权限 打开 Command Prompt (CMD) 或 PowerShell。
-
运行以下命令来查找使用 3306 端口的进程 ID (PID): bash
netstat -ano | findstr :3306请谨慎使用此类代码。
-
输出将显示类似
TCP 0.0.0.0:3306 0.0.0.0:0 LISTENING <PID>的行。记下<PID>(进程 ID)。 -
打开 任务管理器 (Ctrl+Shift+Esc)。
-
转到"详细信息"选项卡(Processes Tab),找到对应的 PID。
-
右键点击该进程,选择"结束任务"以停止该程序。例如,如果它是
mysqld.exe或httpd.exe,请结束它。 -
终止程序后,再次尝试运行你的 Docker 命令: bash
docker-compose up -d请谨慎使用此类代码。
方法二:修改 Docker 容器使用的主机端口
如果你不想停止主机上正在运行的程序,可以修改 docker-compose.yml 文件,让 Docker 容器使用不同的本地主机端口(例如 3307)。
在 docker-compose.yml 文件中,找到数据库服务的 ports 配置,并将其更改为:
yaml
services:
your-db-service-name:
# ... other configurations
ports:
- "3307:3306" # 将主机端口从 3306 改为 3307
# ...
请谨慎使用此类代码。
保存文件后,重新运行:
bash
docker-compose up -d
请谨慎使用此类代码。
方法三:重启 Windows NAT 服务 (winnat)
在 Windows 上,有时端口会被一个名为 winnat 的网络地址转换服务"保留"而无法使用,即使当前没有程序在使用它。
注意: 这会暂时中断你的网络连接。
-
以 管理员权限 打开 Command Prompt (CMD) 或 PowerShell。
-
运行以下命令停止
winnat服务:bash
net stop winnat请谨慎使用此类代码。
-
停止服务后,立即运行你的 Docker 命令: bash
docker-compose up -d请谨慎使用此类代码。
-
Docker 容器成功启动后,重新启动
winnat服务:bash
net start winnat请谨慎使用此类代码。
顺带记录一下,docker停止指定容器或者重新构建镜像--build
步骤一:停止并删除指定的容器(不删除镜像和卷)
首先,停止并删除 java 和 react 服务的容器。docker compose stop 命令只会停止容器,而 docker compose rm 命令会删除停止状态的容器。
在 docker-compose.yml 文件所在的目录中运行以下命令:
bash
docker compose stop java react
docker compose rm -f java react
请谨慎使用此类代码。
stop: 停止指定的容器。rm -f: 强制删除指定的容器(无需确认)。
步骤二:手动删除指定的镜像
docker compose 命令没有直接提供只删除特定服务关联镜像的选项(docker compose down --rmi 会尝试删除所有服务的镜像)。因此,需要使用标准的 Docker CLI 命令 docker rmi 来删除 Java 和 React 服务的本地镜像。
首先,获取这两个服务的确切镜像名称或 ID。您可以在 docker-compose.yml 文件中查找,或者使用 docker images 命令列出所有本地镜像。
假设您的 Java 服务镜像名为 my-java-image,React 服务镜像名为 my-react-image。运行以下命令删除它们:
bash
docker rmi my-java-image my-react-image
请谨慎使用此类代码。
docker rmi: 删除指定的镜像。
步骤三:重新构建并启动服务
删除旧镜像后,使用 docker compose up -d 命令重新构建并启动所有服务。对于 Java 和 React 服务,由于它们的本地镜像已被删除,Docker Compose 将被迫根据 docker-compose.yml 文件中的定义(例如 build 指令)重新构建新镜像或从远程仓库拉取新镜像。对于数据库服务,由于其镜像未被删除,Docker 将重用现有的镜像和(如果配置了)数据卷。
bash
docker compose up -d --build
请谨慎使用此类代码。
-d: 在后台运行容器。--build: 在启动容器前强制构建新的镜像。
总结
完整的流程命令如下:
bash
# 在包含 docker-compose.yml 的目录中执行
docker compose stop java react
docker compose rm -f java react
docker rmi my-java-image my-react-image # 替换为实际的镜像名称/ID
docker compose up -d --build