前阵子做一次线上数据迁移,我的屏幕同时开着数据库客户端、SSH 终端和 Docker Desktop,来回切换窗口的次数多到连我自己都数不清。迁移结束后我下了个决心:把日常工作流收进同一个工具里。现在我的主力方案是 VS Code,一个编辑器里同时管数据库、SSH、Docker,所有操作不用再满桌面找窗口。这篇就来聊聊这套方案怎么落地,适合什么样的人,以及我踩过的那些坑。如果你是个整天在本地 IDE、远程服务器、数据库客户端之间来回跑的后端或运维开发,应该能秒懂这种痛苦。接下来我不讲大道理,直接给可复现的组合方案和操作细节。
1. 多窗口切换的后遗症:为什么轻量开发需要一个聚合入口
1.1 你正在为切换支付认知税
先说个数据。我曾经自己留意过,一个工作日的下午,我在数据库客户端、SSH 窗口、Docker Desktop 之间切换了 40 多次。每次切过去,脑子里都要重新加载“这个窗口的任务是什么、刚才看到哪、下一步要干嘛”,平均十几秒才能回到状态。按这个算,一天光切换就要消耗十几分钟,更别切换对心流的打断了。遇到生产告警时更糟——你一边看 MySQL 连接数,一边盯 Docker 容器日志,还要 SSH 上去查配置,三四个窗口来回跳,手一乱就容易忘了下一步该干嘛。我曾经因为切换太频繁,把一次本该 5 分钟解决的连接池问题拖到了 20 分钟。
这背后的原理其实很简单:人脑的工作记忆容量有限,频繁切换任务表面上是“看一眼”,实际每一次都是一次上下文切换,成本被很多人低估了。所以我后来的原则很明确:能在一个窗口里顺序完成的事,绝不用三个窗口来回切。所谓“告别切换”,告别的不只是窗口数量,而是无效的心智负担。
1.2 为什么我把宝押在 VS Code 上
先说结论:如果你不想为一个商业 IDE 付费,又需要跨平台、能远程、能玩 Docker,VS Code 是现阶段最均衡的选择。它不是单一个软件,而是“编辑器 + 扩展生态”,数据库由 SQLTools 这类扩展负责,SSH 由 Remote-SSH 负责,Docker 由官方 Docker 扩展负责,平时使用时它们都在同一个窗口的侧边栏里,从这个角度说,它确实是“一个工具”。
为了讲清楚选型逻辑,我把几种常见组合放在一起对比过:
| 方案 | 数据库支持 | SSH | Docker | 成本 | 学习曲线 |
|---|---|---|---|---|---|
| VS Code + 扩展 | SQLTools / Database Client 等,支持主流引擎 | Remote-SSH,成熟稳定 | 官方 Docker 扩展 + Dev Containers | 免费 | 低,但需要理解扩展组合 |
| JetBrains IDEA Ultimate | 内置数据库面板 | 内置 SSH Terminal | 内置 Docker 面板与 Compose | 付费订阅 | 中 |
| 三件套(Navicat + Termius + Docker Desktop) | 最强,ER 图/导入导出丰富 | 专用终端体验好 | Docker Desktop 原生 | 部分付费 | 中高,且切换成本极高 |
如果你公司已经买了 JetBrains 系授权,直接在 IDEA 里把 Database、SSH Terminal、Docker 三个工具窗拖到同一排即可,思路完全一样。下面我按 VS Code 来讲,因为它的配置可复现性最好,也免费。
1.3 这套方案适合谁,不适合谁
这套方案最适合这几类人:以 SSH 远程服务器为主要开发环境的人;日常用 Docker 起服务、查日志、重启容器的人;数据库操作以增删改查、慢查询定位、临时数据修复为主的人。它也适合刚入职的团队新人,一台笔记本连上公司跳板机就能接进现有环境,不用先在本机装一整套 MySQL、Redis、Node 环境。
但如果你把数据库工具用到极致——每天画 ER 图、做数据比对、批量导入导出、做复杂查询审计,DataGrip 或 Navicat 这类专业客户端仍然更强。我不建议为了“统一”而把专业场景硬塞进通用编辑器。划清边界也是成熟的做法:日常查询在 VS Code,重活交给专用工具,但 SSH 和 Docker 的入口已经统一了,这就减少了一大半切换。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据库管理:连接、查改、导入导出都在编辑器里完成
2.1 插件选型:SQLTools 还是 Database Client
数据库扩展我先后试过 SQLTools 和 Database Client,最终长期留在 SQLTools,原因是它对多种数据库引擎的支持很稳,连接配置是 JSON 文件格式,方便随项目走。Database Client 界面更像传统数据库工具,操作直观,也能用。两者都可以支持 MySQL、PostgreSQL、SQLite、SQL Server 等,你按界面喜好挑一个即可,下面是 SQLTools 为主的操作。
安装有个容易漏的细节:SQLTools 的主扩展只提供框架,每种数据库还需要单独装驱动扩展,比如 MySQL/MariaDB 驱动、PostgreSQL 驱动。很多人装完主扩展就急着连,结果连接报“driver not found”,其实就是驱动没装。建议在扩展商店里搜索 SQLTools 后,把带 “Driver” 后缀的对应驱动一并装上,这一步最容易被忽略。
2.2 从零建连:MySQL、PostgreSQL、SQLite
以 MySQL 为例。安装完扩展后,打开命令面板执行 “SQLTools: Manage Connections”,或者直接点侧边栏数据库图标的新建连接。图形界面里填服务器、端口、用户名、密码就行。SQLTools 会把连接配置写进项目的 .vscode/settings.json 或者单独的工作区配置里,手工维护也不复杂,例如:
json复制{
"sqltools.connections": [
{
"name": "dev-mysql",
"driver": "MySQL",
"server": "127.0.0.1",
"port": 3306,
"database": "app_dev",
"username": "root",
"password": "在这里填,或留空每次输入"
},
{
"name": "dev-pg",
"driver": "PostgreSQL",
"server": "127.0.0.1",
"port": 5432,
"database": "app",
"username": "app_user",
"password": ""
}
]
}
这里有个小建议:密码字段尽量别明文提交到项目仓库。SQLTools 支持设置 password 为空时弹出输入框,或者在系统钥匙串中保存。团队共享配置时,把密码去掉,让每个人填自己的账号,比把 root 密码写在仓库里稳妥得多。SQLite 更简单,连接配置里指到 .db 或 .sqlite 文件路径即可,PostgreSQL 和 MySQL 的端口别搞混,SQLTools 会根据驱动给默认值,但你也可以手动改。
2.3 日常操盘:SQL 执行、执行计划与手滑保护
连上后,右键数据库名可以 Open New Query,或者直接打开一个 .sql 文件,用命令面板跑 “SQLTools: Run Query”。单条语句执行很简单,但多语句文件需要注意:默认是执行当前光标所在的语句,或者执行选中的部分。我在刚用的时候习惯整段文件一键执行,结果一条 DELETE 后面跟着一条误写的 UPDATE,直接把测试库数据改歪了,从那以后我强制自己执行前先选中语句。
定位慢查询也别切工具。连接上 MySQL 后执行 EXPLAIN SELECT ... 查看执行计划,或者 show processlist; 看当前会话列表。数据库连接池告警时,我通常会先看连接数和 sleep 状态,再决定是调连接池参数还是杀空闲连接,这些查询在 VS Code 的数据库面板里就能做。再补一个关于连接池的理解:连接池参数是应用侧决定的,数据库插件不会替你解决连接数不够的问题,但它能帮你快速验证连接配置是否有效、连接是否能正常获取。比如你在 Spring Boot 的配置文件里改了最大连接数,重启应用后,直接在这个面板里多开几个连接测试一下,能直观感觉连接建立是否正常。
2.4 通过 SSH 隧道连私有网络数据库
很多数据库不在公网,只有跳板机可以访问。这种场景传统做法是先在终端敲一条 ssh -L 命令建立隧道,再打开数据库客户端连接,隧道断了自己都不知道。SQLTools 的连接配置里直接支持 SSH 隧道:填上跳板机的主机、用户、端口,隧道目标填数据库真实地址和端口,扩展会帮你维护这条隧道。
原理和手动执行 ssh -L 是一样的:本地随机端口监听,SSH 加密通道转发到内网数据库端口,数据库客户端连接本地端口即可。好处是不用另开终端窗口,隧道生命周期由扩展管理,断开重连也能自动恢复。如果你同时用 Remote-SSH 连了同一台跳板机,两者互不冲突,一个管远程开发,一个管数据库流量,这就是聚合入口的优势。
3. SSH 远程主机:免密登录、端口转发和远程工作区
3.1 Remote-SSH 的安装与首次连接
Remote-SSH 是这套工作流的骨架。安装扩展后,左下角会出现一个绿色的远程连接按钮,也可以用命令面板执行 “Remote-SSH: Connect to Host...”。首次连接输入 user@host,VS Code 会在远程主机的用户目录下安装一份 Server 组件,然后自动打开一个远程窗口,左下角显示当前连接的 SSH 目标。
这里要注意:远程机器需要能联网下载 VS Code Server;如果服务器在内网离线环境,需要提前离线安装,这个过程比较繁琐,不过大多数场景不会遇到。Windows 用户不需要额外装 Git Bash,新版 Windows 自带 OpenSSH 客户端,Remote-SSH 直接能识别。首次连上后,你的终端、文件树、搜索结果全部落在远程机器上,之后再连基本就是秒开。
3.2 免密登录:一次配置,数据库与 Docker 全受益
如果你还在每次连接输密码,建议花几分钟配置密钥免密。打开本机终端执行:
bash复制ssh-keygen -t ed25519 -C "your_email"
ssh-copy-id user@server_ip
第一句生成密钥对,默认写在 ~/.ssh/id_ed25519,按几次回车即可;第二句把公钥追加到服务器的 ~/.ssh/authorized_keys。没有 ssh-copy-id 时可以手动执行:cat ~/.ssh/id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"。
密钥生成优先选 ed25519,安全和性能都均衡;如果必须和很老的服务端兼容,再考虑 RSA 2048 以上。多台服务器时,编辑 ~/.ssh/config 可以少记无数 IP:
plaintext复制Host prod-web
HostName 192.168.10.20
User deploy
Port 22
IdentityFile ~/.ssh/id_ed25519_prod
Host db-jump
HostName 10.0.0.5
User jumpuser
IdentityFile ~/.ssh/id_ed25519
保存后在 Remote-SSH 的连接列表里就会直接出现 prod-web、db-jump 这样的别名。这套配置同时会被 Docker 扩展的 ssh:// 连接复用,所以一次配好,数据库、SSH、Docker 都能用同一套密钥,这是整个方案里性价比最高的一步。
3.3 端口转发与远程文件管理的正确姿势
远程服务调试经常要访问容器暴露的端口。如果安全组只开了 22 端口,其他端口都关着,就需要端口转发。Remote-SSH 窗口底部有 Ports 面板,点 Forward Port 输入远程端口,VS Code 会把它映射到本地;也可以直接在 SSH config 里固定下来:
plaintext复制Host prod-web
HostName 192.168.10.20
User deploy
LocalForward 8080 127.0.0.1:8080
LocalForward 3306 127.0.0.1:3306
这样连上 SSH 后,本地 localhost:8080 就能访问远程服务器上的服务,localhost:3306 就指向远程的数据库端口——配合数据库扩展,你查库完全不用把数据库端口暴露到公网。
远程文件管理方面,Remote-SSH 打开远程目录后可以直接编辑文件;如果你习惯本地窗口,也可以装 SFTP 扩展做同步。但我的经验是:既然已经远程开发,直接在远程窗口操作最直观,还能避免“本地改了忘了传”的经典失误。涉及敏感文件时,注意看文件权限,别在 Windows 下编辑后同步上去把换行或权限搞乱。
3.4 从“登录”到“远程开发”:工作区上云
Remote-SSH 的价值不只是开个终端,而是把整个开发环境搬到服务器上。你可以在远程窗口里安装插件、打开 /var/www 目录、写代码、跑 Git、起调试器,VS Code 的终端也自动落到远程机器。新同事入职只需要一个 VS Code 和 SSH 配置,不用在本机装一整套依赖,这对我带新人时特别有用,本机系统是什么几乎无所谓。
这套思路和 Docker 的 Dev Containers 可以叠加:你 SSH 连上远程主机后,再通过 Dev Containers 附加到某个容器,代码和运行环境都在容器里。链路虽然长一点,但每一环都是同一套密钥、同一个窗口,定位问题比切换多个工具要舒服得多。
4. Docker 容器管理:从镜像拉取到容器内开发
4.1 连接 Docker 守护进程:本机与远程两种方式
安装微软官方的 Docker 扩展后,侧边栏会出现 Docker 图标,能看到容器、镜像、网络、卷。本机有 Docker Desktop 时默认就能连上。Windows 上如果 Docker Desktop 报 “Virtualization support not detected” 或一直启动失败,通常是 BIOS 没开虚拟化,或者 WSL2 没装好;先去控制面板启用虚拟机平台,再安装 WSL2 内核,我遇到过几次,基本都靠这两步解决。
更需要掌握的是连远程 Docker。服务器上只要开着 Docker 守护进程,本地 VS Code 的 Docker 扩展可以通过 SSH 方式直接管理远程容器。在用户设置里加两行:
json复制{
"docker.host": "ssh://deploy@prod-web",
"docker.context": "prod-web"
}
这里强烈建议用 ssh://,不要用裸的 tcp://2375。2375 端口不加密,一旦暴露在公网,等于把服务器 Docker 权限交给任意网络可达者,挂载根目录、偷镜像、拔密钥都是分分钟的事。我的做法是把 2375 永远关掉,Docker 远程一律走 SSH 通道。如果你本机装过多个 Docker 环境,比如 Docker Desktop 和 minikube 同时存在,注意 docker context 别选错,Docker 扩展状态栏会显示当前 context,出错时先切回 default 再排查。
4.2 容器生命周期操作:一行命令都不用敲
Docker 扩展的图形操作覆盖了绝大多数日常需求。右键容器可以 Start、Stop、Restart,可以 View Logs 看日志,可以 Attach Shell 进入容器交互式终端。查看镜像、拉取镜像、删除悬空镜像也都在面板里。对于 docker-compose 项目,右键 docker-compose.yml 能直接 Compose Up/Down。
| VS Code 面板操作 | 等价命令 | 适用场景 |
|---|---|---|
| Restart | docker restart |
改完配置重启容器 |
| View Logs | docker logs -f |
排查应用启动异常 |
| Attach Shell | docker exec -it |
进容器看文件、调配置 |
| Compose Up | docker compose up -d | 按编排文件启动整套服务 |
| Build Image | docker build -t xxx . | 从 Dockerfile 构建镜像 |
这套操作下来,我基本告别了“专门打开 Docker Desktop 看容器状态”的习惯。日志跟随滚动的体验和终端里敲 docker logs -f 一样,但窗口就在 VS Code 里,看到报错可以直接点进容器看环境变量或配置,不用再切去别的应用。
4.3 Dev Containers:把开发环境直接搬进容器
光管理容器还不够,真正值钱的是在容器里写代码。安装 Dev Containers 扩展后,可以把容器或一个 docker-compose 服务直接变成远程开发环境。VS Code 会把工作区挂进容器,插件、终端、调试器都运行在容器环境里,本机只需要一个编辑器。
这对团队协作帮助很大:以前“在我电脑上是好的”是个梗,现在 Dockerfile 一致,跑出来的环境就一致。我见过一个老是装不齐依赖的项目,改成 Dev Containers 后新人从拉代码到跑起来只用了十几分钟,因为不用再手动装 Redis、MySQL、Node 版本了。链路长的时候要逐步验证:Remote-SSH 能连主机,Docker 扩展能看到容器,Dev Containers 能附加。任何一环连不上,按这个顺序排查,比一下子换三个工具靠谱得多。
5. 三合一实战:远程服务器上的 MySQL 容器,从踩坑到顺畅
5.1 一次完整联通案例:只开 22 端口的安全玩法
把数据库、SSH、Docker 三件事串起来的最好例子,是一台只开了 22 端口公网防火墙的 Ubuntu 服务器,上面跑着 MySQL 8.0 的 Docker 容器。以前我要用 Navicat 连数据库得先把 3306 暴露出公网,或者手动打隧道;现在全部在 VS Code 里完成。假设服务器上有一个 docker-compose.yml,起一个 MySQL 8.0 和一个应用服务:
yaml复制version: '3.8'
services:
db:
image: mysql:8.0
container_name: app_db
restart: always
environment:
MYSQL_ROOT_PASSWORD: root_pwd
MYSQL_DATABASE: app_dev
ports:
- "127.0.0.1:3306:3306"
volumes:
- db_data:/var/lib/mysql
networks:
- app_net
app:
build: .
depends_on:
- db
ports:
- "127.0.0.1:8080:8080"
networks:
- app_net
networks:
app_net:
volumes:
db_data:
注意两个端口都绑在 127.0.0.1 上,数据库完全不对外暴露。接下来我的操作链路是:
- VS Code 用 Remote-SSH 连上 prod-web,远程打开项目目录;
- Docker 扩展里看到 mysql 和 app 两个容器,先 View Logs 确认 app 没连上数据库;
- 数据库扩展新建连接:服务器填 127.0.0.1,端口 3306,启用 SSH 隧道,跳板机填 prod-web;
- 在数据库面板执行 show processlist; 查看连接是否进来;
- 发现 app 容器的数据库地址写的是 localhost,改为 db 容器名后重启容器;
- 回到数据库面板,看到 app 用户连接正常,问题解决。
这 6 步全程没离开 VS Code。数据库端口始终不暴露公网,SSH 隧道承担了所有安全传输。MySQL 8.0 有个历史兼容问题值得单独提:默认认证插件是 caching_sha2_password,老版本的客户端或驱动会连接失败。如果你必须用老驱动,要么把驱动升级,要么建一个使用 mysql_native_password 的用户:
sql复制CREATE USER 'app'@'%' IDENTIFIED WITH mysql_native_password BY 'strong_pwd';
GRANT ALL PRIVILEGES ON app_dev.* TO 'app'@'%';
FLUSH PRIVILEGES;
这个坑在把 MySQL 5.7 容器换成 8.0 时特别常见,顺手记下来能省不少排查时间。
5.2 我实际踩过的几个坑及完整排查链路
这部分我直接按排查链路讲,不跳步。
第一个坑是 SSH 认证失败。现象是 VS Code 连接时报 Permission denied (publickey),或者 git push 提示认证失败。我先在本地终端手动执行 ssh -vvv prod-web,看日志停在哪个阶段;然后确认使用的私钥路径是否正确,多个密钥时用 -i 指定;接着检查本地私钥权限,如果其他人可读,SSH 会拒绝使用,直接 chmod 600 ~/.ssh/id_ed25519;再检查服务器上 authorized_keys 权限和文件内容,确认公钥确实追加进去了。这个链路的核心原则是:从近到远,从客户端到服务端,一次验证一个变量,别一上来就删 authorized_keys。
第二个坑是 Docker 扩展连不上 daemon。现象是窗口里一片红,报 Cannot connect to the Docker daemon。我会先确认 docker.host 设置是否指向了 ssh://prod-web,因为 .vscode/settings.json 里的配置会覆盖用户设置;然后在终端执行 ssh prod-web "docker ps",验证 SSH 通道和 Docker 服务都正常;如果远程 Docker 服务没启动,就 systemctl start docker。如果用的是 tcp://2375,还要重点检查安全组和防火墙,但我强烈建议直接弃用 tcp 方式,这是原则问题。
第三个坑是容器网络不通。现象是 app 容器连接数据库的 localhost:3306 失败。原因在于每个容器默认有自己的网络栈,localhost 指的是容器自己,不是宿主机,更不是另一个容器。排查时用 docker inspect app_db 看 NetworkMode,用 docker network ls 看现有网络,然后把两个服务放进同一个自定义网络 app_net,app 连接地址写成 db 容器名而不是 localhost。这个坑在新人接手 compose 文件时出现频率极高。
第四个坑是数据库连接池被耗尽。现象是应用间歇性报错 Too many connections 或连接超时。在数据库面板执行 show processlist;,看连接来自哪些 IP、哪些用户、是否全是 sleep;如果大量 sleep 堆积,调小应用连接池的空闲时间;如果是连接数阈值本身不够,调大 max_connections。紧急情况下可以临时 kill 掉空闲连接,但根因一定要去查连接池配置,否则第二天一样会爆。
| 问题 | 典型表现 | 第一切入点 |
|---|---|---|
| SSH 认证失败 | Permission denied (publickey) | ssh -vvv 看日志 |
| Docker daemon 连不上 | Cannot connect to the Docker daemon | ssh 远程手动 docker ps |
| MySQL 8.0 认证失败 | client does not support authentication protocol | 换驱动或建 mysql_native_password 用户 |
| 容器网络不通 | 容器内 localhost 连不上 | docker inspect 查网络 |
| 连接池耗尽 | Too many connections | show processlist |
5.3 沉淀下来的个人工作流
这套流程跑顺后,我现在的工作习惯变成了这样:早上到工位,打开 VS Code,通过 Remote-SSH 连上主力服务器,侧边栏扫一眼 Docker 面板里的容器健康状态;有服务异常直接看日志;需要查库就打开数据库面板,先看慢查询,再 kill 不用的连接;改完代码,右键 Dockerfile 构建镜像,docker-compose 一键重启。整个过程都在一个窗口里。
给团队的协作建议有几点:第一,数据库连接配置里的密码不要提交仓库,用环境变量或者每个人自己的账号;第二,SSH 私钥绝不入库,泄露后等于把所有服务器的钥匙交出去了;第三,Docker 环境一律用 compose 文件描述,不要用一堆记不清的 docker run;第四,涉及生产环境的操作先看日志、先备份,再动手。这些不是理论,都是我交过学费换来的习惯。
最后分享一个我自己的操作习惯:刚开始迁移这套组合时,先只加 Remote-SSH,跑一周;跑顺了再加 Docker 扩展;再顺了再上数据库插件。一次只引入一个变量,出了任何问题都清楚是哪个环节。别幻想一天之内把所有插件装齐就能立刻流畅,那只会让你在五个新坑里同时挣扎。工具的价值是把注意力留给代码和业务,不是留给工具本身。你也不妨从今天开始,试着把一个远程窗口用起来。
