主题:从本地 tar 镜像加载到多服务容器(含 MySQL/SSH/HiveServer2等服务)配置的全流程
适用版本:Docker Desktop 4.82.0 + Engine 29.6.1(其他 4.x 版本基本兼容)
操作系统:Windows 10 / 11
典型场景:比如你拿到一个大数据全栈镜像 tar 文件(几 GB ~ 几十 GB),要加载并在 Docker Desktop 上跑起来
📌 占位符约定(先看一遍)
为方便你这套教程套用自己的环境,下面把所有"具体值"都换成<占位符>。你复制粘贴时,把尖括号连带尖括号里的英文一起替换成你自己的实际值就行:
| 占位符 | 含义 | 举例替换值 |
|---|---|---|
<yourpath>\yourmirror.tar | 你下载下来的 tar 镜像绝对路径 | E:\BaiduSyncdisk\镜像\yourmirror.tar |
<your-image-name> | 你给镜像起的 repository 名 | centos-hadoop-spark |
<your-tag> | 你给镜像打的 tag | v3、latest |
<your-image-sha256> | docker load后输出的镜像 ID | 223a9deecaf4...那一长串 |
<your-container-name> | 你想叫的容器名 | hadoop-stack |
<your-volume-name> | 你自定义的 named volume 名 | mysql_data |
<your-windows-data-path> | 主机 Windows 上的持久化目录 | E:\docker-data\hadoop\data |
<your-yml-file> | 你的 docker-compose.yml 文件绝对路径 | E:\docker-data\hadoop-stack.yml |
<your-password> | 你要设的 MySQL/容器 root 密码 | YourStrongPassword123 |
<your-linux-ip> | 你的 Windows 主机在局域网的 IPv4 | 192.168.x.x |
<your-doc-dir> | 你存放技术文档的目录 | D:\Md |
重点提示样式约定:
- 黄色背景高亮= 关键提示(铁律 / 易踩坑 / 一句话原则)
- 红色 = 警告 / 危险 / 必错(❌)
- 绿色 = 正确 / 推荐 / OK(✅)
- 蓝色 = 提示 / 信息 / 小技巧(💡)
目录
- 核心认知:Docker Desktop 能做什么 / 不能做什么
- 第一步:加载本地 tar 镜像
- 第二步:选择启动方式(GUI vs 命令行 vs docker-compose)
- 第三步:编写 docker-compose.yml(核心)
- 摸清镜像结构 + 数据卷策略详解(启动前必看)
- MySQL 服务——最常见的坑
- MySQL 密码问题——万能解法
- SSH 服务自启
- 容器启动自动运行多个服务
- 常见问题速查表
- 经验法则铁律汇总
- 附录:完整命令参考
- 文档维护
1. 核心认知:Docker Desktop 能做什么 / 不能做什么
1.1 真相
| Docker Desktop 能做 | Docker Desktop不能做 |
|---|---|
| 装好 Docker 引擎(藏在 WSL2 实例里) | 让你完全不用命令行 |
| 跨平台统一 UI(Win/Mac/Linux 一致) | 替代docker run的复杂配置 |
| 可视化看 Logs / 容器状态 / 文件树 | 替代docker exec进容器 |
| 一键 Stop / Restart / Delete 容器 | 替代docker compose |
| 简单镜像 Run(容器名/端口/卷/env) | 覆盖容器启动 Command/Entrypoint |
GUI Run 窗口字段有限(4.82.0 版):只有 Container name / Ports / Volumes / Environment variables,没有 Command / Entrypoint 覆盖字段。
1.2 镜像复杂度对应方案
| 镜像复杂度 | 推荐方案 |
|---|---|
| 简单镜像(nginx、redis、官方 mysql:8) | Docker Desktop GUI Run 窗口完全够用 |
| 复杂镜像(比如你要装十几个服务的 Hadoop 全栈) | docker-compose.yml(推荐) |
| 一次性临时调试 | 命令行docker run |
1.3 关于 WSL
┌─── Windows 11 ────────────────────────────────────────┐ │ │ │ ┌─── Docker Desktop 装的 Linux(隐藏)──────────┐ │ │ │ 名字: docker-desktop-data / docker-desktop │ │ │ │ 作用: 跑容器进程 + 存镜像(overlay2) │ │ │ │ 特点: 用户看不到、不能用、只服务 Docker │ │ │ └─────────────────────────────────────────────────┘ │ │ │ │ ┌─── 你自己装的 WSL Linux(独立)──────────────┐ │ │ │ 名字: Ubuntu / Debian / CentOS ... │ │ │ │ 作用: 直接当 Linux 机器用 │ │ │ │ 特点: 能进 shell、装软件、跑服务、写代码 │ │ │ └─────────────────────────────────────────────────┘ │ └────────────────────────────────────────────────────────┘比如你装了 Docker Desktop,它会自己建一个 WSL2 实例作为运行时,对你不可见。你自己另外装的 WSL Ubuntu / Debian 是独立的 Linux 环境,跟 Docker Desktop 那个 Linux 是两回事——是互补不是替代。
2. 第一步:加载本地 tar 镜像
2.1 确认文件
比如你把 tar 镜像下载到D:\downloads\或某个子目录里,那就把路径替换成你自己的。先Get-Item看下文件在不在、大小对不对:
Get-Item"<yourpath>\yourmirror.tar"|Select-ObjectName,Length,LastWriteTime|Format-List期望:
- 文件存在
- 大小合理(比如你的镜像是 10 GB 级别的 Hadoop 全栈,就正常)
- 如果路径找不到 → 很可能你的 tar 镜像藏在
BaiduSyncdisk的某个子目录里没下完,比如你要去同步盘里翻一翻
2.2 确认 Docker Desktop 在跑
docker version--format"Docker Engine: { {.Server.Version}}`nDocker Desktop running: { {.Server.Platform}}"期望:类似Docker Engine: 29.6.1这种输出。
2.3 执行docker load
docker load-i"<yourpath>\yourmirror.tar"耗时参考:
- 比如你的镜像文件是 10 GB,大概10 分钟
- 进度不可见(NTFS → WSL2 虚拟磁盘的 IO 是主要瓶颈)
- 完成后输出类似:
Loaded image ID: sha256:<your-image-sha256>
2.4 打 tag(给镜像起个名字)
docker load出来的镜像只有 sha256 ID,没有 repository:tag,这种情况下docker images列表里看不到,docker run也得写那一长串 hash。比如你要给它起个短名:
# 把 <your-image-sha256> 替换成上面 Load 出来的 ID,把 <your-image-name>:<your-tag> 替换成你想要的名字docker tag <your-image-sha256> <your-image-name>:<your-tag># 验证一下镜像列表docker images--format"table { {.Repository}}\t{ {.Tag}}\t{ {.ID}}\t{ {.Size}}"2.5 查看镜像元信息
比如你要先看一眼镜像里到底预装了啥、作者留了啥环境变量、默认工作目录是哪儿、声明了哪些卷:
# 看环境变量(找 PASSWORD / ROOT / HOME 这类关键词)docker inspect <your-image-name>:<your-tag>--format'{ {range .Config.Env}}{ {println .}}{ {end}}'|grep-iE"MYSQL|PASSWORD|ROOT|HOME"# 看工作目录docker inspect <your-image-name>:<your-tag>--format'WORKDIR: { {.Config.WorkingDir}}'# 看预声明的卷docker inspect <your-image-name>:<your-tag>--format'{ {json .Config.Volumes}}'|python-m json.tool3. 第二步:选择启动方式(GUI vs 命令行 vs docker-compose)
3.1 启动方式对比
| 方式 | 命令 | 优点 | 缺点 |
|---|---|---|---|
| GUI Run 窗口 | Docker Desktop → Run | 直观 | 字段少,没 Command |
命令行docker run | docker run -it ... | 灵活 | 长命令易出错 |
docker-composeyml | docker compose -f <your-yml-file> up -d | 配置可视化、可复用 | 需要写 yml 文件 |
3.2 最小可运行原则
比如你的镜像已经有默认 CMD,最小可运行就是这样:
docker run <your-image-name>:<your-tag>但保活问题要小心:
- 比如你的镜像默认
CMD ["/bin/bash"]→ 启动后没 stdin 立即退出 → 容器状态变Exited (0) - 你必须给它加个保活命令(
tail -f /dev/null)→ 容器才一直 Running
3.3 推荐:写个 yml(最稳)
详见第四节。
4. 第三步:编写 docker-compose.yml(核心)
4.1 yml 模板(整段都是例子,根据你的场景增减)
下面把这份 yml 存到你自己选的位置,比如你打算放在E:\docker-data\下,那就存成<your-yml-file>:
# ============================================================# 这一段是 docker-compose.yml 模板示例# 你可以拷过去改成自己的:所有 <xxx> 占位符都按需替换# 适用:比如你想跑一个本地 load 的大数据镜像,里面要带 SSH + MySQL + 几个 Web UI# ============================================================services:<your-service-name>:# 比如你的服务名可以叫 hadoop / bigdata / my-stackimage:<your-image-name>:<your-tag># 比如你的镜像叫 centos-hadoop-spark:v3container_name:<your-container-name># 比如你想叫它 hadoop-stackpull_policy:never# 比如你的镜像是本地 load 的,不想让 Docker 去 Docker Hub 拉,就写 nevertty:truestdin_open:true# ============================================================# ports 段:这里列的都是 <主机端口>:<容器端口> 的映射# 比如你要把容器里的某个端口"翻译"成主机的端口给外部访问,就照下面这种格式写# ============================================================ports:# 例如:比如你要暴露容器里的 HiveServer2(容器端口 10000),主机这边也用 10000,就写 "10000:10000"-"10000:10000"# 例如:比如你要暴露容器里的 SSH(容器端口 22),不想跟主机 22 冲突,主机用 2222 就写 "2222:22"-"2222:22"# 例如:比如你要暴露容器里的 MySQL(容器端口 3306),主机也用 3306 就写 "3306:3306"-"3306:3306"# 例如:比如你还想暴露容器里的 HDFS Web UI(容器端口 9870),就再加一行 "9870:9870"-"9870:9870"# 例如:比如你还要暴露容器里的 YARN Web UI(容器端口 8088),再写 "8088:8088"-"8088:8088"# ============================================================# volumes 段:把容器里哪些目录拿出来共享# 比如你要把容器里的 /data 挂到主机的 <your-windows-data-path> 就写 "