先讲个真实经历。上周有同事发我一张截图,Docker Desktop 在 Ubuntu 虚拟机里反复弹窗,说 virtualization support was detected 之类的错误,问我怎么处理。我反问他:你在这台机器上装 Docker Desktop 图什么?他愣了一下,说教程不都这么教的吗。其实这正是大多数人卡在“Ubuntu Docker 安装”这一步的核心原因——装了压根用不上的组件,然后被组件自身的限制困住。
如果你也是正在 Ubuntu 上折腾 Docker 的人,这篇文章应该能帮你少走不少弯路。我会从最基础的“你到底需要装哪个 Docker”讲起,到 apt 仓库安装、用户组配置、镜像加速、高频报错排查,最后再用一个 MySQL 8.0 的 Compose 实例收尾。目标只有一个:让你从头到尾顺顺当当把 Docker 用起来,而不是装完就放在那儿吃灰。
1. 先搞清楚:你要装的是 Docker Engine 还是 Docker Desktop
Docker 这个品牌下面有两个容易混淆的东西,几乎所有安装教程的混乱都从这里开始。
Docker Engine 是一个后台服务(daemon),加上一个叫 docker 的命令行客户端。它是 Docker 真正干活的部分。你执行 docker run、docker pull 这些命令时,和系统打交道的是它。
Docker Desktop 则是带图形界面的完整应用,包含了 Docker Engine、Kubernetes 集群、图形化管理面板等一堆东西。它面向的群体是 Windows 和 macOS 用户,因为那两个系统上原生跑 Linux 容器需要一层虚拟机做支撑,Desktop 把这层东西封装好了,用户双击就能用。
问题就出在这里:很多人在 Ubuntu 上装 Docker 时,照着给 Windows 写的教程走,直接去装 Docker Desktop。Desktop 在 Linux 上依然依赖虚拟化层,所以对环境要求非常苛刻——物理机要求 BIOS 里打开 Intel VT-x 或 AMD SVM,虚拟机里还要求宿主机的虚拟化软件支持并开启嵌套虚拟化。任何一个条件不满足,就会出现“failed to start”或者“virtualization support not detected”的报错。
用个不太恰当的类比:Docker Engine 是发动机,Docker Desktop 是装好发动机的整车。你在 Ubuntu 上只需要发动机就能跑,没必要非去开整车,结果被整车对道路的要求卡住。
所以我的建议非常直接:
- 生产服务器、云主机、普通 Linux 开发机:一律安装 Docker Engine。
- Ubuntu 桌面版且你极度依赖图形界面管理容器:可以试 Desktop,但前提是你的硬件虚拟化全开。
- 虚拟机里的 Ubuntu:装 Engine,别折腾 Desktop,纯粹自找麻烦。
这篇文章后面讲的所有内容,全部围绕 Docker Engine 展开。这是 Ubuntu 上最稳妥、最主流、坑最少的一条路。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 安装前花五分钟做环境检查,能躲掉一半的坑
别嫌我啰嗦,这一步真的值得做。我见过太多人一上来就复制粘贴安装命令,装到一半发现架构不对、系统版本不对,或者磁盘空间不足,又得返工。
打开终端,依次执行下面几条命令,每条命令的用途我都写在后面。
bash复制# 查看系统架构
uname -m
Docker 对架构非常敏感。输出是 x86_64 表示 64 位 x86 架构,aarch64 表示 ARM 架构,绝大多数 Ubuntu 主机都是前者。Docker 官方仓库对这两种架构都提供了软件包,但下载地址不一样,所以先确认架构能避免后续的“package not found”错误。
bash复制# 查看 Ubuntu 版本
lsb_release -a
Docker 官方 apt 仓库对 Ubuntu 的支持是分版本维护的,每个版本(如 22.04 Jammy、24.04 Noble)都有独立的软件源目录。虽然 Docker 也兼容一些旧版本系统,但我建议至少使用 Ubuntu 20.04 及以上版本。如果你还在用 18.04,升级完系统再来装 Docker 吧,别在旧系统上死磕。
bash复制# 确认内存和磁盘空间
free -h
df -h /var/lib/docker
Docker 本身不占太多资源,但容器镜像和容器数据都存放在 /var/lib/docker 目录下。一个 MySQL 镜像加一个 Nginx 镜像,轻松吃掉 1GB 以上空间。如果你只是想装来练手,建议至少准备 5GB 可用磁盘;想在生产环境用,单独给 /var/lib/docker 挂一块大磁盘是最稳妥的做法。
bash复制# 更新软件包索引
sudo apt update
执行完这些基础检查后,还有一件重要的事:如果系统之前装过 Docker(不管是 docker.io 还是旧版 docker-engine),先把旧版本干干净净卸载掉,否则会和新的软件包冲突。
bash复制sudo apt remove docker docker-engine docker.io containerd runc
注意这条命令不会删除你的容器数据和镜像,它们还留在 /var/lib/docker 里。如果是全新机器,无视这一步即可。
另外提醒一句:如果你是在 VMware 或 VirtualBox 这类虚拟机软件里装的 Ubuntu,先去虚拟机设置里确认一下嵌套虚拟化是否开启。VMware 里对应的选项叫“虚拟化 Intel VT-x/EPT 或 AMD-V/RVI”,VirtualBox 里叫“启用嵌套 VT-x/AMD-V”。虽然装 Docker Engine 不强制要求这个,但很多人在装 Desktop 时才来查这个问题,提前知道没坏处。
3. 用 apt 官方仓库安装 Docker Engine:推荐路线详解
环境检查完,开始正式安装。我这里推荐的是 Ubuntu 上最标准的安装方式:从 Docker 官方 apt 仓库安装。好处有三个:第一,能拿到 Docker 最新的稳定版本;第二,后续可以用系统自带的 apt 命令统一升级 Docker;第三,安装过程可控、可审计,出了问题知道去哪查。
3.1 安装依赖工具
bash复制sudo apt install ca-certificates curl gnupg
这几个工具负责后面下载和验证 GPG 密钥。ca-certificates 是 HTTPS 证书信任链,curl 用来下载密钥文件,gnupg 用来做密钥校验。大部分 Ubuntu 系统已经自带其中一部分,但显式安装一遍没有坏处。
3.2 添加 Docker 官方 GPG 密钥
Docker 官方对软件包做了 GPG 签名,目的是防止软件包在传输过程中被篡改。添加密钥这一步的本质,是告诉你的 apt 工具“只有用这把公钥签名的软件包,我才信任”。
bash复制# 创建存放密钥的目录
sudo install -m 0755 -d /etc/apt/keyrings
# 下载并解包密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# 修改权限,让所有用户都能读取
sudo chmod a+r /etc/apt/keyrings/docker.gpg
用 install 命令创建目录而不是 mkdir,是因为它会顺便把目录权限设置成 0755。下载的 GPG 文件是二进制格式,gpg --dearmor 的作用是把上游提供的 ASCII 格式密钥转换成二进制格式,apt 只认这种格式。
chmod a+r 这步容易被忽略,但它很重要。如果权限不对,后面 apt update 时会报“key is not readable”之类的错误,排查起来很烦。
3.3 添加 Docker apt 仓库
bash复制echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo $VERSION_CODENAME) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
这行命令看起来复杂,拆开看其实很简单。arch 参数自动获取你的系统架构,signed-by 指向刚才导入的密钥文件,后面的 $(. /etc/os-release && echo $VERSION_CODENAME) 会自动填上你的 Ubuntu 版本代号。比如 22.04 会变成 jammy,24.04 会变成 noble。
装完仓库后,记得再执行一次 apt update,让 apt 工具读到新仓库里的软件包列表。
bash复制sudo apt update
3.4 安装 Docker 引擎
bash复制sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
这里逐个解释一下这几个软件包,因为很多初学者看到五个包名就懵了:
- docker-ce:Docker 引擎本体,社区版(Community Edition)。
- docker-ce-cli:Docker 命令行工具,就是你在终端里敲的 docker 命令。
- containerd.io:容器运行时,负责实际创建和运行容器。Docker 引擎把容器生命周期管理委托给它。
- docker-buildx-plugin:多架构镜像构建插件,构建镜像时会用到。
- docker-compose-plugin:Docker Compose 插件,用来编排多个容器。
特别说一下最后一个。早些年 Docker Compose 是一个独立的 Python 工具,需要额外安装,版本还经常和 Docker 对不上。现在官方直接把 Compose 做成插件集成到 Docker CLI 里了,装完 docker-compose-plugin,你直接执行 docker compose 就能用,不用再单独折腾 docker-compose 命令。新用户没经历过那个时代可能没感觉,但老用户应该懂得这一点有多爽。
安装过程中如果输出里有“Unable to locate package docker-ce”的报错,九成是 3.3 步的仓库源没配置成功,或者系统版本代号对不上。先检查 /etc/apt/sources.list.d/docker.list 里的内容是否正常,再确认 apt update 有没有报错。
安装完成后,服务默认会自动启动。可以通过下面的命令验证:
bash复制sudo systemctl status docker
看到 active (running) 就对了。如果没启动,手动拉起来:
bash复制sudo systemctl start docker
3.5 其他安装方式,什么时候用
除了 apt 仓库安装,还有两种常见方式,简单提一下。
脚本安装:
bash复制curl -fsSL https://get.docker.com | sudo sh
一条命令搞定,非常适合临时测试环境。但它的缺点也很明显:脚本在升级时会直接覆盖已有配置,升级后版本行为可能和你预期不一致;而且脚本内部做了很多自动判断,你无法精确控制安装内容。生产环境我不推荐这种用法。
离线安装:内网隔离的服务器上,你只能在一台能联网的机器上把 .deb 包下载下来,再拷贝到目标机器上安装。具体做法是用 apt install --download-only 或 apt download 先拉包,再 dpkg -i 手动安装。这种方式会失去 apt 的依赖自动解析能力,需要手动处理依赖关系,建议只作为最后的办法。
4. 装完先别急着用,这三项设置决定体验
很多教程装完 Docker 就跑 hello-world 然后收工。但实际用了几个月的人都知道,安装只是开始,真正让 Docker 用得顺手,还得靠下面这三项设置。不做的话也不是不能用,只是每次都会多几条烦心报错、多几步重复操作。
4.1 把当前用户加入 docker 组,省掉日常 sudo
装完 Docker 后,直接执行 docker version 会看到权限报错:
bash复制docker: permission denied while trying to connect to the Docker daemon socket
原因是 Docker 守护进程的 socket 文件 /var/run/docker.sock 默认只对 root 用户和 docker 用户组开放。解决方案有两种。
一种是每次命令前加 sudo,简单粗暴,但时间久了你会发现很烦,而且有些脚本里没法写 sudo,导致自动化操作失败。
另一种是把当前用户加入 docker 用户组:
bash复制sudo usermod -aG docker $USER
执行完后需要重新登录或者运行 newgrp docker 让用户组立即生效。然后用 docker version 验证一下,应该就能正常访问了。
这里必须提醒一句:加入 docker 组的用户权限等同于 root。原因是 Docker 的守护进程以 root 身份运行,能操作 Docker 的用户实际上能通过挂载宿主机目录等方式拿到宿主机 root 权限。所以仅限你真的信任的账号加入 docker 组,生产服务器上更要谨慎。你要是用 root 账号登服务器,那无所谓;但一个多人共用的开发机,别批量添加用户进组。
4.2 设置开机自启,让容器跟着系统起来
Docker 引擎装好之后,开机自启默认是打开的,但保险起见还是显式设置一下:
bash复制sudo systemctl enable docker
sudo systemctl enable containerd
enable 的意思是让服务随系统启动。有些教程只 enable docker 不 enable containerd,结果系统重启后 Docker 起来了但容器运行时没起来,容器全部处于创建失败状态。两个服务都设置为开机自启,是稳妥的做法。
另外容器层面还有一个 restart 策略,比如 docker run --restart unless-stopped。这个策略的意思是:如果容器异常退出,Docker 会自动重启它;但如果你手动 stop 它,Docker 不会在你重启系统后强行把它拉起来。生产环境跑数据库容器,这个策略几乎是标配。后面写 Compose 配置时我还会再提一次。
4.3 配置镜像加速,解决 Docker 镜像下载慢
这可能是国内用户最关心的问题。docker pull 一个官方镜像,尤其是几百 MB 的镜像,默认源在境外,速度经常让人抓狂。解决思路是给 Docker 配置镜像加速器(registry mirror)。
镜像加速器的原理很简单:Docker 官方支持把镜像下载请求先发到加速器,如果加速器本地有缓存就直接返回,没有的话加速器再回源拉取,通过内容分发网络提高速度。这是一项公开、合法的基础设施服务,多家云厂商都提供了免费加速地址,没有特殊用途,单纯为了下载更快。
打开配置文件 /etc/docker/daemon.json,如果文件不存在就新建:
bash复制sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["https://docker.m.daocloud.io"]
}
EOF
注意:上面的地址只是示例,实际配置时请去任意一家云服务商的容器镜像服务页面获取你专属的加速地址。因为每个厂商分配的加速地址都包含你的个人标识,直接抄别人的地址很可能无法生效。
配置完成后重启 Docker:
bash复制sudo systemctl daemon-reload
sudo systemctl restart docker
验证是否生效:
bash复制docker info
输出里找到 Registry Mirrors 一栏,看到你配置的地址就说明配置成功了。
这里有个小经验:加速地址不要配置太多,一两个就够。有些人把网上搜到的加速地址一股脑全填进去,Docker 拉取时反而会依次尝试每个地址,超时重试机制会让响应更慢。
5. 验证安装是否成功,顺便掌握高频命令
环境配置好,先跑一个最小的容器验证整条链路是否通畅。
bash复制docker run hello-world
这条命令做了几件事:本地找有没有 hello-world 镜像,没有就去远程仓库拉取,拉下来后创建容器并运行,容器打印一段欢迎信息后退出。整个过程能跑通,说明 Docker 引擎、镜像下载、容器运行三个核心环节都正常。如果前面镜像加速配置好了,这一步拉取速度应该非常快。
跑完 hello-world,我习惯再跑一个 Nginx 容器,用来验证端口映射和容器网络,毕竟这才是日常使用的高频场景。
bash复制# 后台运行一个 Nginx 容器,命名为 web,映射宿主机的 8080 端口到容器的 80 端口
docker run -d --name web -p 8080:80 nginx
# 查看正在运行的容器
docker ps
# 访问 Nginx 默认页面
curl http://localhost:8080
看到 Nginx 的欢迎页面,说明容器网络、端口映射都正常。接着试几个最常用的排查命令:
bash复制# 进入容器终端,注意 exec 不走 SSH,它直接复用容器内的运行环境
docker exec -it web bash
# 查看容器日志,Nginx 访问日志在这里
docker logs web
执行完先关掉这个测试容器:
bash复制docker stop web
docker rm web
到这里,可以基本掌握 Docker 的命令体系了。我把日常工作最高频的命令整理成一张速查表:
| 命令 | 用途 | 常用参数 |
|---|---|---|
| docker pull 镜像名 | 拉取镜像 | 默认拉 latest 标签,建议指定版本如 nginx:1.27 |
| docker images | 查看本地镜像列表 | -a 显示中间层镜像 |
| docker ps | 查看运行中的容器 | -a 显示所有容器(含已退出) |
| docker run 镜像名 | 创建并启动容器 | -d 后台运行;-p 端口映射;--name 命名;-v 挂载数据卷;--restart 设置重启策略 |
| docker exec -it 容器名 bash | 进入容器执行命令 | 容器内没有 bash 就换 sh |
| docker logs 容器名 | 查看容器日志 | -f 持续跟随输出;--tail 50 只看最后50行 |
| docker stop / start / restart 容器名 | 生命周期管理 | 支持多个容器名同时操作 |
| docker rm 容器名 | 删除容器 | 删除前先 stop;-f 强制删除运行中的容器 |
| docker rmi 镜像名 | 删除镜像 | -f 强制删除 |
| docker system prune | 清理悬空资源 | -a 连未使用的镜像和构建缓存一起清理,慎用 |
| docker system df | 查看 Docker 磁盘占用 | 类似 df 命令,但针对 Docker 各层缓存 |
敲命令这件事,看一百遍不如打一遍。装好环境后,建议拿一台临时机器把这些命令都过一遍,熟了之后再看下面的排错内容会更有体会。
6. 高频报错排查实录:从虚拟化检测失败到镜像拉不下来
这部分是我最想写的内容。网上教程千篇一律地教你“怎么装”,真正值钱的信息是“装的时候遇到问题怎么排”。下面这些案例,都是我在实际环境中遇到过、并且帮不少人解决过的问题。
6.1 Docker Desktop 提示 virtualization support not detected
前文提过这个问题。很多人用的是 Windows 加虚拟机跑 Ubuntu、再在 Ubuntu 里装 Docker Desktop 的套娃方案,然后在某一步摊上这个报错。
排查链路是这样的:
第一,确认你是在物理机还是虚拟机里装的 Ubuntu。物理机的话,进 BIOS/UEFI,找到 CPU 设置,打开 Intel Virtualization Technology(Intel 平台)或 SVM Mode(AMD 平台),保存重启。
第二,如果你在虚拟机里,检查虚拟化软件的嵌套虚拟化设置。VMware 里是“虚拟机设置 -> 处理器 -> 虚拟化引擎 -> 虚拟化 Intel VT-x/EPT 或 AMD-V/RVI”,要勾上。VirtualBox 里是“设置 -> 系统 -> 处理器 -> 启用嵌套 VT-x/AMD-V”。这个选项默认不开启,很多新手就是折在这里。
第三,换成 Docker Engine。诚心建议:你要是通过命令行使唤 Docker,完全不需要 Docker Desktop,直接装 Engine 就绕开了整个虚拟化依赖链。这也是我在第一章反复强调的原因。
6.2 镜像拉取超时或者慢到无法忍受
报错形式一般是 Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled,或者干脆卡在 Pulling fs layer 半天不动。
排查链路:
先分清是网络访问不到 registry 服务,还是速度慢。执行:
bash复制curl -I https://registry-1.docker.io/v2/
如果这个命令卡住或者超时,说明网络层访问官方源有问题,直接检查 DNS 解析和代理设置。如果这条命令秒回,说明网络通路没问题,慢是链路质量问题,优先配置镜像加速。
再检查镜像加速配置是否生效。docker info 里看 Registry Mirrors 字段,没有就按 4.3 节的步骤配置。
还有一个小众但真实存在的问题:同时拉取多个大镜像。Docker 的镜像拉取是分层并行的,但并行度太高会把本机 IO 和带宽全部占满。如果你是一次性 docker compose up 拉起五六个服务,卡一下反而是正常的。解决办法:改配置或者分批拉取,不要几个人同时在一台机器上拉镜像。
6.3 permission denied while trying to connect to the Docker daemon socket
报错全文一般带一段 unix:///var/run/docker.sock。原因就是 4.1 节说过的:当前用户不在 docker 组里。
解决顺序:先确认你属于哪个用户组,执行 id 命令。如果不在 docker 组里,就 usermod -aG docker $USER 加入,然后重新登录。注意是重新登录,不是打开一个新终端窗口那么简单,用户组信息在登录时才加载。
如果你确认自己就在 docker 组里还报这个错,检查 socket 文件的权限:
bash复制ls -l /var/run/docker.sock
正常应该是 srw-rw---- root docker。如果权限不对,说明 Docker 是用非标准方式安装的,要么用 sudo 临时解决,要么调整 docker group 的权限。
6.4 端口映射失败:driver failed programming external connectivity
docker run 加了 -p 8080:80 启动时报错,常见原因有两个。一个是端口已占用,用 ss -tlnp | grep 8080 查一下哪个进程占着;另一个是 Docker 的 iptables 规则和本机防火墙冲突。
对于 Ubuntu 系统,默认防火墙一般是 ufw。Docker 默认会在 iptables 里加自己的规则,ufw 的规则也可能同时存在,两者打架时就会报上述错误。
最直接的排查方式:先停掉 Docker 测试容器,curl 一下端口确认占用情况。如果是 ufw 问题,执行 sudo ufw allow 8080/tcp 放行端口;如果还是不行,调整 Docker 的 iptables 配置属于高阶操作,建议先查 Docker 和 ufw 的版本兼容性。
6.5 磁盘空间被镜像撑爆
镜像、容器、数据卷、构建缓存,占据的都是宿主机磁盘。时间一长,/var/lib/docker 膨胀到几十 GB 很常见。
排查先用 docker system df,它会按镜像、容器、数据卷、构建缓存分类统计占用。
清理手段:
bash复制# 清理悬空镜像(即没有标签且没有被容器引用的镜像)
docker image prune
# 清理所有未使用的镜像,慎用
docker system prune -a
# 清理构建缓存
docker builder prune
如果 Docker 数据在主分区且空间紧张,可以把整个 Docker 数据目录迁移到其他磁盘。方法是在 daemon.json 里加一行:
json复制{
"data-root": "/data/docker"
}
然后重启 Docker。注意:迁移前务必停掉所有容器,迁移后原目录的内容不会自动帮你拷过去,要么使用软链接,要么手工 rsync 数据过去。
7. 顺便把 Compose 装好,用一个 MySQL 8.0 实例收尾
到这里,Docker 单机操作已经能跑通。日常开发中,一个应用往往需要多个容器协作——数据库、缓存、后端、前端,用 docker run 一条条启动命令会非常痛苦。这时候就该 Compose 出场。
新版 Docker 已经默认集成了 Compose 插件(也就是 3.4 节里装的 docker-compose-plugin)。验证一下:
bash复制docker compose version
看到版本号输出就说明可用了。注意,是 docker compose(中间有空格),不是老版的 docker-compose(中间有连字符)。两个命令在语法上有些差异,新项目统一用前者。
Compose 的核心思想:把一组容器的启动参数写进一个 YAML 文件,用文件定义基础设施,可以用 git 版本管理,换机器时拷贝文件就能复现整套环境。
下面用 MySQL 8.0 做示例,覆盖开发和生产通用的编排手法。
7.1 编写 docker-compose.yml
新建一个项目目录,创建 docker-compose.yml:
yaml复制services:
mysql8:
image: mysql:8.0
container_name: mysql8
restart: unless-stopped
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: "your_password_here"
TZ: Asia/Shanghai
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --default-authentication-plugin=mysql_native_password
volumes:
- mysql_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-p"]
interval: 10s
timeout: 5s
retries: 5
volumes:
mysql_data:
拆开解释几个关键点。
image 指定镜像和版本。mysql:8.0 会拉取 8.0 系列最新小版本,比直接写 mysql:latest 好,因为镜像版本可控。
restart: unless-stopped 是 4.2 节说的容器重启策略,生产环境容器退出后自动拉起,宿主机重启后也会自动恢复。
environment 里 MYSQL_ROOT_PASSWORD 是 MySQL 镜像规定的初始化变量。首次启动时,镜像会用这个密码初始化 root 账号。
command 段覆盖了 MySQL 默认启动参数。三个配置分别解决三个常见问题:character-set-server=utf8mb4 让数据库默认字符集支持 emoji 和中文;collation 指定排序规则;default-authentication-plugin 设成 mysql_native_password 是为了兼容老客户端。MySQL 8.0 默认的 caching_sha2_password 认证方式会让一些旧版客户端连不上,如果你确定都用新客户端,这项可以删掉。
volumes 这行是关键。mysql_data:/var/lib/mysql 表示容器内的数据库文件存放在名为 mysql_data 的 Docker 数据卷中。即使容器删掉重建,数据也不会丢。不用 bind mount 是因为数据卷性能更好,而且不受宿主机目录权限影响。
healthcheck 是给容器加健康检查。MySQL 容器在启动过程中会有一个不可连接的窗口期,没有健康检查的话,编排的依赖方可能拿到一个还没就绪的数据库地址。配置后可以通过 docker inspect 查看容器的健康状态。
7.2 启动连接
bash复制docker compose up -d
-d 表示后台启动。执行完后:
bash复制docker compose ps
看到 STATUS 变成 healthy,说明数据库初始化完成,可以用客户端连接了:
bash复制mysql -h 127.0.0.1 -P 3306 -uroot -p
输入密码后能进入 MySQL 命令行,整条链路就通了。
管理命令在这留一份:
bash复制docker compose logs -f mysql8
docker compose restart mysql8
docker compose down
注意:docker compose down 不会删除数据卷,所以不用担心数据丢。如果你确定不要数据卷了,加 -v 参数才会连数据卷一起删。
这个示例稍作修改就能扩展成更复杂的场景。比如 Redis 主从,思路是在同一个 Compose 文件里定义多个 service,master 和 slave 用不同的配置文件挂载进去,容器之间通过 Compose 自动创建的内网网络互相访问。原理和我上面写的 MySQL 实例没有本质区别,多一个 service 就多一份映射关系。
7.3 一个容易翻车的隐藏细节
首次执行 docker compose up 会拉取镜像,时间取决于网络和镜像大小。如果前面镜像加速没配好,MySQL 8.0 镜像接近 600MB,拉取过程会非常折磨。建议在拉取之前先把加速配好,别等卡住了再想起来。
另外,MySQL 镜像首次启动时初始化较慢,如果你用自动化脚本去连数据库,一定要先确认容器健康状态再发起连接。我在生产环境就遇到过脚本连不上数据库导致服务反复重启的案例,最后加了 healthcheck 判断才解决。
装 Docker 这件事,说起来就是几条命令的事,但真正让它好用的,是装完之后的环境调优和对报错机制的理解。我在虚拟机里踩过虚拟化的坑,在服务器上踩过镜像源的坑,在公司网络环境里还踩过各种奇奇怪怪的超时问题。这些经验综合下来最核心的一条就是:Docker 的坑大多数不是 Docker 本身的问题,而是环境和前置条件的问题。把环境检查做在前面,遇到报错先冷静分析是哪一层出了问题,比搜一百条教程都管用。
如果你照着这篇文章装完了,应该已经能熟练运行容器、查看日志、清理资源,并且能跑起一套完整的 MySQL 环境。下一步可以试着用 Compose 把 Nginx、MySQL、Redis 组合起来,模拟一个真实的 Web 服务架构,那才是 Docker 真正发挥价值的地方。
