
打开搜索框敲下“ubuntu docker”的基本是三类人一类想先装好 Ubuntu 再跑 Docker一类是已经装好了但 Docker 起不来还有一类是容器确实跑起来了结果 MySQL、Redis 这些一部署就各种报错。这篇文章我把这三条路上的关键环节串起来讲从系统安装方式的选择、Docker 引擎的安装配置到数据库和微服务容器的落地再到我最常被问到的几个故障场景一次性说透。内容偏向 Ubuntu 22.04/24.04 这类 LTS 版本Docker 部分以原生 Linux 引擎为主也会提一句 Docker Desktop 在虚拟机里的坑适合刚从 Windows 转过来、或者准备在服务器上搞容器化的同学。1. 双系统、虚拟机还是 WSL先想清楚 Docker 跑在哪一层很多人第一步就卡住了不是 Docker 的事而是 Ubuntu 本身还没装对地方。我先说结论如果目标是长期认真用 Docker首选物理机装 Ubuntu其次是 VMware 虚拟机里的 UbuntuWSL2 可以作为 Windows 下的临时替代但别指望它把容器网络和 GPU 直通这些事都干得漂亮。1.1 三种环境的取舍对照方案优点主要坑点适合场景物理机双系统性能最完整Docker 的存储驱动、网络栈不隔层需要分区、引导配置装完还要解决显卡和输入法打算把这台机器变成开发/测试服务器VMware 虚拟机可随时快照系统搞坏了恢复方便要开嵌套虚拟化否则内层 Docker Desktop 直接报 virtualization support not detected想先体验 Ubuntu Docker又舍不得 Windows 环境WSL2启动快内存动态分配网络模式和宿主机隔一层部分内核功能受限只写代码不折腾底层网络能接受偶尔的兼容性小毛病这里插一个重要提醒如果你在 VMware 里装 Ubuntu之后又想在 Ubuntu 里跑需要内核模块的容器比如带特殊驱动、需要 iptables 管理的服务务必在 VMware 的虚拟机设置里勾选“虚拟化 Intel VT-x/EPT 或 AMD-V/RVI”否则后续 Docker Desktop 或者某些带虚拟化要求的组件会启动失败。VirtualBox 则是开启“Nested VT-x/AMD-V”。这个选项藏得比较深默认不勾很多人报错后怎么查都是 BIOS 的问题其实问题出在宿主机虚拟机层没有放行。1.2 为什么 Ubuntu 原生命令行才是 Docker 的主场Docker 的核心能力依赖 Linux 内核的 namespaces、cgroups、overlayfsUbuntu 的 LTS 内核和 Docker 引擎适配得最顺。用docker info能看到存储驱动是 overlay2而原本的 devicemapper 基本已经退出历史舞台。在 Ubuntu 上装 Docker没必要装带图形界面的 Docker Desktop那东西在 Linux 上只是多包了一层虚拟机反而让日志和网络排查变复杂。服务器场景直接装 dockerd 加 docker CLI完完全全够用你要是实在喜欢图形界面社区也有 docker-desktop 汉化包之类的东西但那属于锦上添花不是必需品。2. Ubuntu 上装 Docker 的完整链路换源、装引擎、开机自启Ubuntu 官方软件源里的docker.io包虽然也能用但我建议走 Docker 官方 apt 仓库拿到的引擎版本更新而且能一站式安装 compose 插件和 buildx 插件。2.1 官方仓库安装步骤先把系统源更新一下然后安装依赖工具sudo apt update sudo apt install -y ca-certificates curl gnupg添加官方 GPG 密钥和仓库时这一步偶尔会因网络原因失败。多试几次或者临时换成国内镜像源重新拉取即可密钥本身没有地区限制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 ar /etc/apt/keyrings/docker.gpg 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之后就是常规安装sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin装完先别急着跑容器用一行命令验证服务状态sudo systemctl status docker --no-pager如果显示 active (running)说明引擎已经起来了。这一步最容易出的问题是 apt 源里旧包冲突比如之前用 pip 装过 docker-compose又或者手动放过 docker.io。遇到依赖冲突可以先sudo apt remove docker.io docker-compose清理干净再继续。2.2 为什么我建议用 docker-compose-plugin 而不是单独装 compose新版本的 compose 是作为 Docker CLI 插件存在的命令是docker compose中间没有连字符。这和旧版docker-compose是两套东西。用插件的好处是版本和 Docker 引擎同步不会出现 compose 文件里的语法引擎不认的情况。项目的docker-compose.yml文件基本通用但执行命令时注意区分docker-compose up和docker compose up很多人迁移到新环境后第一反应是“compose 命令不存在”其实只是少了那个连字符。2.3 非 root 用户运行 Docker 的权限处理默认情况下执行docker ps需要一个权限用户。刚装完 Docker 就迫不及待复制网上的命令去跑大概率遇到权限不足的报错。正确做法是把当前用户加进 docker 组sudo usermod -aG docker $USER newgrp docker这里有个安全点要说清楚docker 组里的用户基本等同于拿到了宿主机 root 权限因为容器可以挂载/。如果这台机器上有多人共用给 docker 组加人要谨慎。个人开发机无所谓团队机器就要考虑用 rootless 模式或者受控的 CI 环境。开机自启这个事很多人忽视Ubuntu 默认不会自动启动 Docker 服务sudo systemctl enable docker sudo systemctl start docker如果你用的是 WSL2 或者无 systemd 的容器环境自启方式要另说但 Ubuntu 桌面版和服务版都有 systemd这条命令就直接管用。3. 跑起第一个容器之后的三个必查项镜像加速、网络与存储驱动引擎装好了不代表万事大吉。很多人的 Docker 能跑 hello-world但拉个正经镜像就卡死或者容器起来了但外网不通原因往往是这三样没配置。3.1 配置镜像加速和日志限制Docker 默认从 Docker Hub 拉镜像国内网络环境不稳定是常见情况。在/etc/docker/daemon.json里配置镜像加速地址同时把日志大小限制加上防止长期运行的容器把磁盘写爆{ registry-mirrors: [https://docker.m.daocloud.io], log-driver: json-file, log-opts: { max-size: 10m, max-file: 3 }, storage-driver: overlay2 }改完重启 Dockersudo systemctl restart dockerdocker info里能看到 Registry Mirrors 已经生效。日志限制这个配置强烈建议加上我见过最离谱的一次是某容器一天产生 20GB 日志直接把根分区撑满系统卡到只能进恢复模式清理。3.2 容器的网络不通先查这几层“docker 网络不通”也是个高频热词。排查思路按顺序来先看容器网络模式docker network ls默认桥接网络是bridge。在容器内 ping 宿主机 IP不通就先查宿主机的 iptables。Docker 依赖 iptables 做 NAT如果系统里装了 firewalld经常会和 Docker 的规则打架。容器内 DNS 解析失败的话给 daemon.json 增加公共 DNS{ dns: [8.8.8.8, 223.5.5.5] }某些特殊场景下直接把容器网络模式改成 host 能快速绕开问题但要注意端口冲突。这里特别说明一下 iptables 和 firewalld 的问题。Ubuntu 桌面版默认不带 firewalld但有些用户装完会顺手systemctl start firewalld然后 Docker 端口映射就失灵了。兼容方案是在 firewalld 里放行 Docker 的网段或者干脆停掉 firewalld让 Docker 自己管理 iptables别让它俩抢方向盘。3.3 存储驱动和磁盘占用Ubuntu 的内核默认支持 overlay2不需要额外配置。可以用docker info确认docker info | grep -i storage如果输出不是 overlay2通常是因为文件系统本身不支持比如某些特殊网络存储挂载的根分区。遇到这种情况把 Docker 数据目录迁移到本地 ext4 或 xfs 分区是最稳妥的做法sudo systemctl stop docker sudo rsync -avP /var/lib/docker/ /data/docker/然后修改 daemon.json{ data-root: /data/docker }再启动 Docker。大前提是/data有充足空间且文件系统支持 overlay。4. 从数据库到微服务的 Docker 落地MySQL、Redis、GitLab 与我踩过的坑刚装好 Docker 的人最喜欢干的事就是docker run一个数据库感受一下然后就开始在生产目录里堆容器。我建议一开始就用 docker compose 管理多容器项目因为数据库这种有状态服务裸 run 命令很难描述清楚数据卷和网络。4.1 MySQL 8.0 部署与使用MySQL 8.0 的坑主要集中在两个地方一是默认认证插件二是中文乱码。用下面的 compose 配置基本能避免services: mysql8: image: mysql:8.0 container_name: mysql8 restart: always ports: - 3306:3306 environment: MYSQL_ROOT_PASSWORD: YourStrongPass TZ: Asia/Shanghai command: - --character-set-serverutf8mb4 - --collation-serverutf8mb4_unicode_ci - --default-authentication-pluginmysql_native_password volumes: - mysql_data:/var/lib/mysql healthcheck: test: [CMD, mysqladmin, ping, -h, localhost, -uroot, -pYourStrongPass] interval: 10s timeout: 5s retries: 5 volumes: mysql_data:启动后进入容器执行 SQLdocker exec -it mysql8 mysql -uroot -p这里有一个大家经常踩的坑如果宿主机已经装了 MySQL 并用着 3306 端口容器端口映射会直接失败。报错信息是 bind 端口被占用第一步先排查宿主机端口而不是删容器。另外别把MYSQL_ROOT_PASSWORD写在 compose 文件里提交到 Git 仓库哪怕只是内网项目也应该用环境变量文件或 secrets 管理。4.2 Redis 主从复制的 compose 配置“docker 安装 redis 主从”这个搜索词的命中率一直很高。Redis 6 之后官方镜像默认配置变化不大主从的关键参数在启动命令里带上即可services: redis-master: image: redis:7-alpine container_name: redis-master command: [redis-server, --appendonly, yes] ports: - 6379:6379 volumes: - redis_master:/data redis-slave: image: redis:7-alpine container_name: redis-slave command: [redis-server, --replicaof, redis-master, 6379] depends_on: - redis-master volumes: - redis_slave:/data volumes: redis_master: redis_slave:这里有个容易误导人的概念新版的命令参数是--replicaof老版本叫--slaveof。从 Redis 5 开始官方就改了称呼但网上一搜还全是旧命令。我在 Redis 7 上实测过旧参数也能识别但新项目里最好直接用--replicaof。启动后用redis-cli info replication查看role:slave且master_link_status:up就代表主从关系正常。4.3 GitLab 社区版容器化部署GitLab 社区版在 Docker 里的部署稍微重一些主要是内存吃紧。4GB 内存的机器跑 GitLab 会经常无响应我的经验是至少保证 4GB 可用给 GitLab其余容器另算。部署命令最小化版本是这样的sudo docker run --detach \ --hostname gitlab.example.com \ --publish 8443:443 --publish 8080:80 \ --name gitlab \ --restart always \ --volume $GITLAB_HOME/config:/etc/gitlab \ --volume $GITLAB_HOME/logs:/var/log/gitlab \ --volume $GITLAB_HOME/data:/var/opt/gitlab \ gitlab/gitlab-ce:latest首次启动要等几分钟可以用docker logs -f gitlab看初始化进度。很多人以为启动失败其实只是还在跑迁移任务这时候盲目重启反而会把数据目录搞脏。4.4 微服务项目的 Docker Compose 部署思路微服务项目用 compose 编排时核心不是把服务全塞进一个 yaml而是规划好网络和依赖关系。我常用的套路是每个服务显式声明networks不要全丢默认 bridge。用depends_on只保证启动顺序不保证服务就绪。真正的健康检查要靠healthcheck。所有服务设置restart: unless-stopped避免机器重启后服务散架。资源限制用deploy.resources.limits防止某个服务内存泄漏拖垮整台机器。示例片段services: app: image: myapp:latest ports: - 8080:8080 networks: - backend healthcheck: test: [CMD, curl, -f, http://localhost:8080/health] interval: 30s timeout: 3s retries: 3 deploy: resources: limits: memory: 512M db: image: postgres:16 networks: - backend networks: backend: driver: bridge这里要提醒一下deploy.resources.limits在 Docker Compose v2 里能直接生效但在 Swarm 集群里语义更严格。如果你只是单机跑别被旁边文章里 “这是 Swarm 专用” 的说法搞晕Compose 插件早就支持了。5. Docker 启动失败、连不上、虚拟化报错故障排查清单热词里最扎眼的错误是 “virtualization support not detected docker desktop failed to start because v…”还有重启机器后 docker 命令全部拒绝连接以及容器一直处于 Restarting 状态。我把这些场景一起梳理。5.1 虚拟机嵌套虚拟化与 VT-x/AMD-V 报错出现 virtualization support not detected 的完整报错通常是在 Windows 上跑 Docker Desktop但 Docker Desktop 借的虚拟机没开启硬件虚拟化。如果你是从 Ubuntu 虚拟机里的 Docker 遇到类似问题十有八九是宿主机的 VMware/VirtualBox 没开嵌套虚拟化。VMware Workstation 的设置路径是虚拟机设置 - 处理器 - 勾选 “虚拟化 Intel VT-x/EPT 或 AMD-V/RVI”。改完必须关机再开机不能直接热重启。VirtualBox 则是设置 - 系统 - 处理器 - 勾选 “启用嵌套 VT-x/AMD-V”。如果你确认 BIOS 里虚拟化已经开启但还是报错那就要检查是不是用 Windows 的 Hyper-V 和 VMware 混跑了。Hyper-V 开启后 VMware 和 VirtualBox 的硬件虚拟化会被截胡Docker Desktop 也可能受影响。这类共存问题到现在也没有很稳定的通解我的建议是要么纯 VMware要么纯 Hyper-V/WSL2别混着上。5.2 Docker 服务启动失败与日志定位当systemctl start docker起不来时第一反应不是去搜“docker 安装失败”而是先看日志sudo journalctl -u docker --no-pager -n 50常见的启动失败原因有三个daemon.json 语法错误JSON 文件里多了个逗号都起不来。写完后可以docker info验证起不来就先docker daemon --validate之类的方式或者直接python3 -m json.tool /etc/docker/daemon.json检查。iptables 规则残留旧网络规则冲突重启前先iptables -L看看状况。磁盘空间已满df -h /看到使用率 100%Docker 写 PID 文件都写不进去。定位到原因后按部就班处理最忌讳看到报错就去卸载重装很多问题重装一百遍也不会消失。5.3 容器反复重启的经典原因容器状态一直在 Restarting大概率不是 Docker 的问题而是容器内部程序启动即崩。docker logs 容器名看最后输出常见两类数据库类容器密码变了或者数据目录权限不对。Web 服务类容器监听端口和健康检查端口不一致健康检查失败导致编排系统不停重启。遇到这种情况先去掉restart: always改成restart: no让容器崩完停下然后进入容器手动跑启动命令这样才能看到真正的报错。6. Ubuntu 跑 Docker 之前的系统级小补丁SSH、中文输入、显卡如果你是用 Ubuntu 桌面版搞开发环境配置有一堆零碎问题会分散精力。这些虽然和 Docker 没有直接关系但处理不好会让整个系统体验极其难受我挑几个高热度的说一下。6.1 SSH 连接不上新装的 Ubuntu 默认没有 openssh-server远程工具连不上是必然的。安装后还要确认服务状态sudo apt install -y openssh-server sudo systemctl enable --now ssh如果还是连不上逐项排查ip addr看 IP 是否正常。防火墙sudo ufw status。Ubuntu 默认 ufw 可能没启用但如果启用了要sudo ufw allow OpenSSH。sshd 配置里PasswordAuthentication是否被显式改成 no。6.2 中文输入法设置“ubuntu 中文输入法怎么设置”和“ubuntu 安装搜狗输入法”几乎每周都有人问。现代系统的推荐方案是 fcitx5兼容性和 Wayland 都比旧 fcitx 好。搜狗拼音的 Linux 版目前依然是依赖 fcitx 的如果你非要用搜狗就得装 fcitx不是 fcitx5然后在系统设置里把输入法框架切到 fcitx注销重登。我个人的做法是直接 fcitx5 加自带的中文拼音。安装sudo apt install -y fcitx5 fcitx5-chinese-addons然后在环境变量里设置输入法框架编辑~/.profile或/etc/environmentexport GTK_IM_MODULEfcitx export QT_IM_MODULEfcitx export XMODIFIERSimfcitx设完重启或注销再到“区域与语言”里添加汉语拼音。这里经常有人设置完没生效原因多半是没把 fcitx 加到开机自启动桌面环境登录后没有拉起输入法进程。6.3 显卡驱动卸载不掉的处理思路“ubuntu 显卡驱动卸载不掉”这个热词背后通常是两件事一是 N 卡驱动装完系统循环登录想卸载却又找不到卸载入口二是驱动版本老Ubuntu 内核一升级模块加载失败。标准卸载路径sudo apt purge nvidia-* -y sudo apt autoremove -y sudo ubuntu-drivers auto sudo reboot如果提示有进程占用 GPU 而卸不掉先进 tty 文本界面CtrlAltF2把桌面会话停掉再卸。如果连 tty 都进不去就在 GRUB 里选择高级选项进入恢复模式选 root shell然后重新挂载根分区mount -o rw,remount /再执行上面的卸载命令。最闹心的一种情况是 apt 记录乱了驱动包显示未安装但模块还在那就手动清理/lib/modules/下对应的模块文件和/etc/modprobe.d/里的黑名单配置这一招能解决九成的“残留”问题。6.4 忘记密码与系统紧急恢复搜索词里有一条 “ubuntu 忘记登录密码”处理方式很成熟重启进入 GRUB选择高级选项里的 recovery mode选 root shell然后mount -o rw,remount / passwd 你的用户名改完reboot即可。恢复模式默认根分区是只读挂载不执行 remount 的话 passwd 会提示只读文件系统很多人卡在这步。如果连 GRUB 都进不去再用 Ubuntu 安装 U 盘进 live 环境挂载原磁盘改密码逻辑一样。6.5 apt 安装 gcc 失败的小坑很多人sudo apt install gcc报依赖错误然后去搜 “ubuntu 安装 gcc 失败”。其实大部分情况下只需要安装完整的编译套件而不是单独的 gcc 包sudo apt install -y build-essentialbuild-essential 会把 gcc、g、make 一起拉进来。如果还失败先办sudo apt update再检查是不是把系统的 Python 版本或者 32 位源搞混了。另外Ubuntu 24.04 的默认源里已经不再包含部分旧的多架构库遇到 No candidate version 属正常不要硬憋。写在最后的实战感悟我自己从 Ubuntu 16.04 一路用到 24.04Docker 从 1.x 用到现在的 engine v27中间踩过的坑比这篇文章列出来的还要多一倍。最想强调的一点是Docker 在 Ubuntu 上的绝大多数问题都不是 Docker 本身的问题而是系统环境、网络策略、磁盘规划这些“地基”没打稳。装好系统后先花十分钟把 SSH、时间同步、换源、磁盘空间清理这几件事安排好再把 Docker 装上去后面的开发体验会顺畅非常多。如果你在跟着这篇折腾的过程中遇到某个具体报错别急着格式化重装先journalctl -u docker和docker logs两边日志对照着看八成能找到原因。工具是死的排查思路是活的。