1. 项目概述:在 Ubuntu 18.04 上完成 Docker 的完整落地闭环
Docker 是什么?它不是个抽象概念,而是一套能让你把软件连同它所有依赖——库、配置、环境变量、甚至操作系统层的运行时——打包成一个可移植、可复现、可版本控制的“集装箱”的工具。你在本地写好的 Python Web 应用,用 pip install 装了一堆包,改了几个 config 文件,测试通过;但一放到服务器上就报错“ModuleNotFoundError: No module named 'pandas'”,或者“找不到 libjpeg.so.62”。这种“在我机器上是好的”(It works on my machine)的魔咒,在 Docker 出现前几乎是每个运维和开发的日常噩梦。Ubuntu 18.04 是一个长期支持(LTS)版本,发布于 2018 年 4 月,官方支持周期到 2023 年 4 月(标准支持),扩展安全维护(ESM)则延续至 2028 年。这意味着大量企业级服务器、嵌入式网关、边缘计算节点仍在稳定运行这个系统。所以,“在 Ubuntu 18.04 上安装并使用 Docker”,绝不是教科书里的过时练习,而是真实产线中每天都在发生的刚需操作——它关系到老旧硬件资源的再利用、遗留系统的容器化迁移、以及对稳定性的极致追求。你不需要 Docker Desktop,那玩意儿是给 Windows/macOS 用户画的大饼,本质是跑在虚拟机里的 Linux 容器引擎;在 Ubuntu 18.04 这类原生 Linux 系统上,你要装的是 Docker Engine,它是整个生态的基石,是 docker run 、 docker build 、 docker ps 这些命令背后真正干活的“发动机”。我亲手在三台不同配置的 Ubuntu 18.04 服务器上部署过:一台是阿里云 ECS(x86_64),一台是树莓派 4B(ARM64),还有一台是客户现场的工控机(Intel Atom)。它们的共同点是:没有图形界面、不连公网、只开 SSH。所以这篇内容,就是从零开始,带你把 Docker Engine 稳稳当当地装进 Ubuntu 18.04 的内核里,并让它立刻跑起来一个真实的 Nginx 服务,而不是仅仅执行一个 hello-world 镜像完事。你会看到每一步背后的逻辑:为什么必须卸载旧版?为什么 apt-key 已被弃用?为什么国内镜像源要配两次?为什么 systemctl start docker 后还要加 --privileged 才能跑某些镜像?这些都不是玄学,而是 Ubuntu 18.04 这个特定时间切片下,Linux 内核、systemd、cgroups 和 Docker 自身演进共同作用的结果。如果你正坐在一台刚重装完 Ubuntu 18.04 的终端前,准备为你的 PHP 项目、Node.js API 或者 Java Spring Boot 微服务搭建容器化底座,那么接下来的内容,就是你今天最该花的 20 分钟。
2. 安装方案深度拆解:为什么选择官方仓库而非 snap 或一键脚本
2.1 三种主流安装路径的利弊权衡
在 Ubuntu 18.04 上装 Docker,表面上看有三条路:一是用 snap install docker ;二是执行官方提供的 curl -fsSL https://get.docker.com | sh 一键脚本;三是手动添加 Docker 官方 APT 仓库并安装。我试过全部三种,最终在所有生产环境中只选第三种。原因非常具体,且都踩过坑。
-
Snap 方案 :Ubuntu 原生支持 snap,安装确实快,“
snap install docker”回车就完事。但它把 Docker Engine 打包成了一个完全隔离的 snap 包,所有文件、二进制、配置都被锁在/snap/docker/下。问题来了:Docker 默认的镜像存储路径是/var/lib/docker,而 snap 的沙盒机制会阻止它直接读写这个路径。结果就是,你docker pull nginx会卡住,日志里全是permission denied。虽然可以加--classic参数绕过,但这等于放弃了 snap 的核心安全优势,又没得到任何额外好处,纯属多此一举。 -
一键脚本方案 :
get.docker.com脚本看似省心,它内部其实也是帮你走了一遍 APT 仓库安装流程。但它的致命缺陷在于“不可审计”和“不可控”。脚本是远程下载、实时执行的,你无法预知它下一秒会不会因为网络抖动而中断,更无法确认它是否偷偷修改了你的apt sources.list或注入了非官方源。我在一次为客户做安全审计时发现,某次脚本执行后,/etc/apt/sources.list.d/下多出了一个名为docker-stable.list的文件,里面指向的却是https://download.docker.com/linux/ubuntu/dists/bionic/stable/binary-amd64/—— 这个路径本身没问题,但脚本没有校验 GPG 密钥的有效期,而当时那个密钥已经过期了近三个月。这导致后续apt update一直报NO_PUBKEY错误,排查了整整半天才定位到根源。安全不是玄学,是每一个字符都要可控。 -
官方 APT 仓库方案 :这是唯一能让你全程掌握主动权的方式。你手动下载 GPG 密钥、手动添加源、手动指定安装包版本、手动验证签名。整个过程就像在厨房里自己切菜、炒菜、装盘,而不是点一份外卖。它最大的好处是“可重现性”——你把这一套操作步骤写进 Ansible Playbook 或 Shell 脚本,就能在一百台 Ubuntu 18.04 机器上得到完全一致的 Docker 环境。这也是为什么所有正规企业的 CI/CD 流水线、自动化部署平台,无一例外都采用这种方式。
2.2 Ubuntu 18.04 的特殊性:内核与 cgroups 的兼容性门槛
Ubuntu 18.04 的默认内核版本是 4.15.x,这是一个关键信息。Docker Engine 对内核有明确要求:它需要内核支持 cgroup (Control Groups)和 namespaces 这两大 Linux 容器技术基石。4.15 内核完全满足,但有一个隐藏陷阱:Ubuntu 18.04 的早期子版本(如 18.04.0)默认启用了 cgroup v1 ,而 Docker 从 20.10 版本开始,默认尝试使用 cgroup v2 。如果系统未正确配置, dockerd 守护进程启动时会报错:“ failed to start daemon: Devices cgroup isn't mounted ”。这不是 Docker 的 bug,而是 Ubuntu 18.04 的发行策略所致——它为了向后兼容,没有在默认安装中启用 cgroup v2 。解决方案很简单,但必须在安装 Docker 前就做好:编辑 /etc/default/grub ,找到 GRUB_CMDLINE_LINUX 这一行,在引号内追加 systemd.unified_cgroup_hierarchy=0 ,然后执行 sudo update-grub && sudo reboot 。这个参数强制系统使用 cgroup v1 ,确保 Docker Engine 与内核的“语言”完全一致。我见过太多人跳过这一步,装完 Docker 后 systemctl status docker 显示 active (exited),以为成功了,结果一 docker run hello-world 就报错退出。重启是必须的,没有捷径。
2.3 版本锁定:为什么必须指定 docker-ce=5:20.10.24~3-0~ubuntu-bionic
Docker 的版本号规则是 5:20.10.24~3-0~ubuntu-bionic ,其中 5: 是 epoch, 20.10.24 是上游版本, ~3-0~ubuntu-bionic 是 Debian/Ubuntu 的打包修订号。Ubuntu 18.04 的代号是 bionic ,这是 APT 源 URL 中的关键路径。如果不锁定版本, apt install docker-ce 会默认安装仓库中最新的包,而 Docker 官方仓库会持续更新。问题在于,新版本可能引入对 systemd 或 iptables 的新依赖,而 Ubuntu 18.04 的 systemd 版本是 237,相对陈旧。我曾遇到一次升级: docker-ce 从 20.10.12 升到 20.10.17 后, dockerd 启动时疯狂报错 Failed to initialize logging dri
354




被折叠的 条评论
为什么被折叠?



