背景:

1.阿里云学生免费轻量级云服务上有Nginx、springboot、redis,但是没有mysql(因为尝试过阿里云两核1G运行内存会炸,有可能因为部署的mysql是latest版本的,要求比较高),你想在云服务器上的可以连接上mysql。

2.尝试云服务器连接本地PC的mysql。(倒反天罡)
3.前置要求:你需要有配置正常的Nginx容器、redis容器、springboot容器(显示图1)
方案:SSH反向隧道(推荐)
1. 本地PC安装SSH客户端
(1)Windows 系统
方法一:启用内置OpenSSH(推荐)
-
打开 PowerShell(管理员权限),运行:
# 安装SSH客户端 Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0 # 验证安装 ssh -V
-
如果输出类似
OpenSSH_8.1p1
表示成功。
-
方法二:安装Git Bash(含SSH)(我本地有git bash所以用了这种)
-
下载 Git for Windows,安装时勾选 "Use Git and optional Unix tools in the Windows Command Prompt"。
2. 生成SSH密钥对(免密码登录)
在 本地PC 上执行:
# 生成密钥对(默认保存在 ~/.ssh/cloud_mysql)
ssh-keygen -t ed25519 -f ~/.ssh/cloud_mysql -N ""
-
一路回车即可(不用设置密码)。
将公钥上传到云服务器:
# 替换为你的云服务器IP和用户名
ssh-copy-id -i ~/.ssh/cloud_mysql.pub root@你的云服务器IP
-
输入云服务器密码后,后续连接不再需要密码。
3. 建立SSH反向隧道(本地PC → 云服务器)
在 本地PC 上执行:
重点:在云服务器上的3306会转发到本地PC的3306;
# 命令结构
ssh -fN -R 云服务器端口:localhost:本地MySQL端口 用户名@云服务器IP
# 示例:将本地MySQL 3306映射到云服务器的3306端口
ssh -fN -R 3306:localhost:3306 root@你的云服务器IP
参数说明:
参数 | 作用 |
---|---|
-f | 后台运行 |
-N | 不执行远程命令(仅做端口转发) |
-R | 反向隧道(远程端口→本地端口) |
3306 | 云服务器上开放的端口(可自定义) |
localhost:3306 | 本地MySQL的地址和端口 |
4. 验证隧道是否成功
在 云服务器 上执行:
# 检查端口是否监听
netstat -tulnp | grep 3306
# 测试连接本地MySQL(通过隧道)
mysql -h 127.0.0.1 -P 3306 -u root -p
-
如果连接成功,说明隧道已建立!
5. 保持隧道稳定(可选)
(1)用autossh自动重连
在本地PC安装 autossh
(Linux/macOS):
# Ubuntu/Debian
sudo apt install autossh
# CentOS/RHEL
sudo yum install autossh
# 启动守护进程
autossh -M 0 -fN -R 3306:localhost:3306 root@云服务器IP
(2)Windows设为开机启动
-
创建脚本
mysql_tunnel.ps1
:ssh -fN -R 3306:localhost:3306 root@云服务器IP
-
通过任务计划程序设置为开机启动。
6. 关闭隧道
在本地PC找到SSH进程并终止:
# Linux/macOS
ps aux | grep ssh
kill -9 <进程ID>
# Windows
taskkill /F /IM ssh.exe
最后的话,连接成功。
可能遇到的问题
Q1:连接不上。
1.ssh -i ~/.ssh/cloud_mysql root@云服务器ip 能登录但是需要输入密码
2.云服务器连接不上本地mysql
A:阿里云默认不允许密钥认证。私钥文件权限问题,SSH 对私钥文件的权限要求非常严格。如果私钥文件的权限设置不正确,SSH 客户端会拒绝使用它。
1.检查和修复权限:
# 确保私钥文件只有用户自己可读写
chmod 600 ~/.ssh/cloud_mysql
# 确保 .ssh 目录的权限正确
chmod 700 ~/.ssh
2. 私钥文件与公钥不匹配
确保您使用的私钥文件(~/.ssh/cloud_mysql
)与远程服务器上的公钥匹配。
验证步骤:
-
在本地检查私钥对应的公钥:
ssh-keygen -y -f ~/.ssh/cloud_mysql
这将输出私钥对应的公钥内容。
-
在远程服务器上检查授权的公钥文件:
-
cat ~/.ssh/authorized_keys
确保输出的内容包含本地生成的公钥。
如果不匹配:
将正确的公钥添加到远程服务器的 ~/.ssh/authorized_keys
文件中:
# 在本地生成公钥(如果尚未生成)
ssh-keygen -y -f ~/.ssh/cloud_mysql > ~/.ssh/cloud_mysql.pub
# 将公钥复制到远程服务器
ssh-copy-id -i ~/.ssh/cloud_mysql.pub root@远程服务器ip地址
3. SSH 配置问题
远程服务器可能未正确配置以允许密钥认证。
如果发现某些配置项不正确,可以使用文本编辑器(如 nano
或 vim
)修改文件。
使用 nano
编辑文件
sudo nano /etc/ssh/sshd_config
找到并修改以下配置项:
// 把no 改成yes
PubkeyAuthentication yes
保存并退出:
-
在
nano
中,按Ctrl+O
保存,按Ctrl+X
退出。 -
在
vim
中,按Esc
键,输入:wq
保存并退出。
4. 重启 SSH 服务
修改完配置文件后,需要重启 SSH 服务以使更改生效:
sudo systemctl restart sshd
5.成功连接,不需要密码即可连接上云服务器
Q2:如何验证 SSH 隧道是否正常工作?
1. 检查云服务器上的端口监听状态
在云服务器上运行以下命令,确认 127.0.0.1:3306
是否被监听:
sudo netstat -tuln | grep 3306
输出应类似于:
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN
如果没有看到类似输出,则说明 SSH 隧道未正确建立,请重新运行 SSH 命令。
2. 在云服务器上测试连通性
使用 telnet
或 nc
测试云服务器的 127.0.0.1:3306
是否可用:
telnet 127.0.0.1 3306
如果连接成功,您可能会看到类似以下输出:
Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'.
如果您看到类似输出,说明云服务器的 127.0.0.1:3306
已正确转发到本地 PC 的 MySQL 服务。
如果连接失败(如 Connection refused
),请检查以下内容:
-
SSH 隧道是否正确建立。
-
本地 PC 的 MySQL 服务是否正在运行并监听
3306
端口。
3. 检查本地 PC 的 MySQL 服务
确保本地 PC 的 MySQL 服务正在运行,并监听 3306
端口。
(1) 检查 MySQL 服务状态
在 Windows 上,可以通过服务管理器检查 MySQL 服务是否正在运行:
-
按下
Win + R
,输入services.msc
,然后按回车。 -
在服务列表中找到
MySQL
或类似的条目。 -
确保其状态为“正在运行”。如果没有运行,右键单击并选择“启动”。
sudo systemctl start mysql
(2) 检查 MySQL 是否监听 3306
端口
在本地 PC 上运行以下命令,确认 MySQL 是否监听 3306
端口:
netstat -ano | findstr :3306
输出应类似于:
TCP 127.0.0.1:3306 0.0.0.0:0 LISTENING 1234
如果没有看到类似输出,请检查 MySQL 配置文件(如 /etc/mysql/my.cnf
或 /etc/my.cnf
),确保 bind-address
设置为 127.0.0.1
或 0.0.0.0
:
bind-address = 127.0.0.1
修改后重启 MySQL 服务:
sudo systemctl restart mysql
4. 使用 MySQL 客户端测试连接
在云服务器上尝试通过 MySQL 客户端连接到本地 PC 的 MySQL 服务:
mysql -h 127.0.0.1 -P 3306 -u root -p
如果连接成功,说明 SSH 隧道和 MySQL 服务均正常工作。
如果连接失败,请检查以下内容:
-
用户权限:确保本地 MySQL 的
root
用户允许从远程主机访问。 -
密码:输入正确的密码。
Q3:把本地的3306端口暴露(仅做测试作用,实战完成可以把防火墙修改回去)
(1)确保 MySQL 用户具有远程访问权限。
- 查看用户权限
SELECT host, user FROM mysql.user;
- 添加远程访问权限:
使用以下命令为用户授予远程访问权限:
-- 创建用户并设置密码
CREATE USER 'root'@'你的远程服务器ip' IDENTIFIED BY '1234';
-- 授予所有权限
GRANT ALL PRIVILEGES ON *.* TO 'root'@'你的远程服务器ip';
-- 刷新权限
FLUSH PRIVILEGES;
这里的 '%' 表示允许所有主机连接。如果你只想允许特定主机(例如云服务器的 IP 地址),可以将 '%' 替换为具体 IP,例如 '192.168.1.100'。
(2) 检查防火墙和网络配置
确保云服务器和本地 PC 的防火墙允许相关流量通过。
-
云服务器防火墙: 允许
3306
端口的流量:sudo ufw allow 3306/tcp
-
本地 PC 防火墙: 允许来自云服务器的流量。例如:
- 打开“控制面板” > “系统和安全” > “Windows Defender 防火墙” > “高级设置”。
- Windows:在 Windows 防火墙中添加入站规则,允许
3306
端口。
- 防火墙没问题的话就会显示:
Q3:时间久了,可能连接会断。(网络连接不稳定、)
解决办法:
在本地PC的git bash再次输入:
ssh -i ~/.ssh/cloud_mysql -fN -R 0.0.0.0:3306:localhost:3306 root@你的服务器ip
Q4: Docker容器内的SpringBoot服务无法连接MySQL,而云服务器本身可以连接。
1. 检查容器网络模式
在云服务器执行:
docker inspect <容器ID> | grep NetworkMode
-
如果是
bridge
模式(默认),容器有独立网络命名空间 -
如果是
host
模式,容器共享主机网络
2. 根据网络模式调整连接配置
情况1:使用Bridge网络(推荐)
# 查看MySQL容器的IP
docker inspect <mysql容器ID> | grep IPAddress
在SpringBoot配置中使用该IP:
spring:
datasource:
url: jdbc:mysql://云服务器ip:3306/hmdp?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true # 替换为云服务器IP
情况2:使用Host网络
启动SpringBoot容器时添加 --network host
:
// docker run --network host -d -p 8088:8088 --name *** your_springboot_image
docker run --network host -d -p 8088:8088 --name hmdp-real2 hmdp-real
配置中使用 localhost
:
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/hmdp?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true