ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Ubuntu Server 25.10 安装 Docker 实战:踩坑记录与配置指南

Ubuntu Server 25.10 安装 Docker 实战:踩坑记录与配置指南 装 Docker 这件事网上一搜一大把教程但我身边好几台 Ubuntu Server 机器都是照着教程一步步走最后卡在同一个地方要么权限报错要么容器网络不通要么镜像拉不下来。这篇文章就把我在 Ubuntu Server 25.10 上从头折腾 Docker 的完整过程记录下来包括我踩过的坑、排查思路和最终配置适合刚接触 Ubuntu Server 的运维新手也适合已经装上 Docker 但总被小问题困扰的人参考。1. 为什么我最终选择在 Ubuntu Server 25.10 上直接装 Docker Engine而不是 Docker Desktop先说结论Ubuntu Server 没有图形桌面环境Docker Desktop 的意义不大直接用 Docker Engine Docker Compose 插件才是正路。很多人在 Windows 或 macOS 上用惯了 Docker Desktop到了 Ubuntu Server 上第一反应是去找 Docker Desktop 的 Linux 版。我一开始也这么干过结果发现 Linux 版 Docker Desktop 依赖 GNOME 或者 KDE 这类桌面环境装上去不仅体积臃肿还会拉进来一堆图形库依赖。更关键的是Docker Desktop 的设计初衷是给开发者本机提供容器运行环境而 Server 上跑容器是为了长期提供服务两者目标完全不同。Ubuntu Server 25.10 是较新的非 LTS 版本内核相对较新对 Docker 的 overlay2 存储驱动、iptables 规则、cgroup 版本支持都比较完整。Docker Engine 本身只依赖内核的几个关键特性namespace资源隔离、cgroups资源限制、iptables/netfilter网络转发、overlayfs镜像分层。25.10 的内核默认全部打开这些特性不需要额外编译模块。还有一点很多人忽略Docker Desktop 自带一个虚拟机层在 Windows/macOS 上通过 Hyper-V 或 Apple Hypervisor 实现Linux 版虽然是原生进程但管理工具链比如 docker desktop 的 GUI 面板在纯命令行环境里就是累赘。在 Server 上我们需要的只是 dockerd 守护进程和 docker CLI 客户端多出来的那层东西只会增加排查问题时的干扰项。提示如果你只是想在本机快速跑几个容器测试Docker Desktop 图省事没问题但如果你是给服务器装 Docker直接装 Engine。Server 环境讲究的是稳定、可控、可脚本化不是图形界面好看。2. 装 Docker 之前我先确认了这三件事2.1 系统版本和内核确认这一步看起来多余但恰恰是很多人翻车的起点。由于 25.10 是较新的版本网上很多教程还在用 20.04 或 22.04 的代号focal、jammy去配置 apt 源照搬的话 apt 会直接报错说源不存在。我先执行了下面的命令确认系统信息lsb_release -a uname -r输出大概是 25.10 的对应版本号内核是 6.8 或更高。这一步的意义在于Docker 官方 apt 源里的 stable 仓库是否包含当前版本的代号目录。不同版本对应的 Docker 源配置不一样直接复制粘贴老教程容易挂掉。2.2 网络环境评估Docker 安装本身需要从download.docker.com拉取依赖国内网络环境下速度可能不理想有时候甚至超时。我评估的结果是官方源偶尔能通但速度不稳定。所以提前把 apt 的国内镜像源和 Docker 的镜像加速器都准备好了。这一步后面单独讲。2.3 清理旧版本残留如果机器之前用apt install docker.ioUbuntu 仓库自带的旧版 Docker装过或者用过 snap 版本的 docker先清理干净再装新版否则会出现/etc/docker/daemon.json冲突、二进制版本错乱之类的诡异问题。我用的清理命令是sudo apt remove --purge docker.io docker-ce docker-ce-cli containerd runc docker-compose-plugin sudo rm -rf /var/lib/docker /etc/docker /etc/containerd注意rm -rf /var/lib/docker会把已有镜像、容器数据全删掉如果你确定没有需要保留的数据再执行。这一步是确保后续安装从零开始不会出现版本混用。3. 核心安装过程官方脚本、apt 仓库、二进制包三种方式我都试了3.1 官方一键脚本最省事但不适合所有场景Docker 官方提供了一键安装脚本命令是curl -fsSL https://get.docker.com | sh这个脚本会自动检测系统版本、配置 apt 源、安装 Docker Engine 及相关组件。听起来很完美但实测有几个问题对非 LTS 版本的支持滞后。脚本里的系统代号判断有时跟不上新版本可能会用上一个版本的代号去匹配源。安装过程不可控。你无法指定版本脚本默认装最新版对生产环境来说不够稳健。脚本执行时会直接修改系统源列表万一装到一半网络断了apt 源处于半配置状态后面修复起来很麻烦。这个方式适合临时测试不建议作为正式安装手段。3.2 官方 apt 仓库我最终选择的方式推荐手动配置 Docker 官方 apt 仓库的好处是源稳定、版本可控、升级可控、卸载干净。步骤拆开来看第一步安装依赖工具sudo apt update sudo apt install -y ca-certificates curl gnupgca-certificates是 HTTPS 证书信任链的必备组件gnupg用于导入和验证 Docker 官方 GPG 公钥。不装的话 apt 源验证会失败。第二步添加 Docker 官方 GPG 公钥sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod ar /etc/apt/keyrings/docker.asc/etc/apt/keyrings目录是 apt 推荐的公钥存放位置chmod ar是为了确保 apt 进程能以非 root 权限读取公钥文件。第三步配置 Docker apt 源这里是最容易踩坑的一步。网上很多教程让你手动写死版本代号比如jammy或noble但 25.10 的代号在 Docker 官方仓库里可能还没有对应的目录。我建议用变量动态获取echo deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release echo $VERSION_CODENAME) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null如果执行apt update时报类似The repository ... does not have a Release file的错误说明 Docker 官方源还没收录当前版本代号。我在实际安装时就遇到了这个情况解决办法是临时改成上一个 LTS 版本的代号echo deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu noble stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null这里用noble24.04 的代号是安全的因为 Docker 的 deb 包依赖的是 glibc 版本和内核特性noble 的包在更新的系统上完全兼容。我用这个方式成功拉到了安装包。第四步安装 Docker 组件sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin注意我特意把docker-buildx-plugin和docker-compose-plugin一起装了。Buildx 是构建多架构镜像的插件Compose 插件则是现在官方推荐的 Compose 使用方式。老一点的教程会让你单独装docker-composePython 版这个已经过时了功能和性能都不如插件版。装完后查看服务状态sudo systemctl status docker sudo docker version如果能正常显示 client 和 server 版本信息说明 dockerd 已经跑起来了。3.3 二进制包离线环境专用如果你所在的服务器完全没有外网或者有严格的内网安全策略得提前在有网的机器上下载好 deb 包。步骤是在有网的 Ubuntu 机器上配好官方源执行sudo apt download docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin然后把.deb文件拷贝到目标机器执行sudo dpkg -i *.debdpkg如果报依赖缺失再执行sudo apt -f install自动修复。这种方式适合内网批量部署但版本升级也要手动操作比较麻烦不建议常规使用。3.4 三种方式的对比总结方式优点缺点适用场景官方一键脚本省事、自动适配版本不可控、非 LTS 支持滞后、会改系统源临时测试、个人开发机官方 apt 仓库版本可控、升级方便、卸载干净配置步骤多、需要理解 GPG 和源机制生产环境、长期运行的服务器二进制 deb 包可离线安装升级麻烦、依赖需要人工处理内网隔离环境、批量部署4. 折腾过程中最折磨人的几个问题排查4.1 权限问题为什么每次都要 sudo装完 Docker 后我直接运行docker ps结果报错permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock原因很简单docker 组和用户组的问题。Docker 的 socket 文件/var/run/docker.sock默认属于root用户和docker组当前用户不在docker组里自然没权限。解决办法是把当前用户加入 docker 组sudo usermod -aG docker $USER newgrp docker注意加完组之后需要重新登录终端或者用newgrp docker临时切换组组权限才会生效。我一开始不知道要重新登录执行完usermod后直接跑docker ps还是报错还以为是没生效。另外有一个安全性提示加入docker组相当于给了用户 root 权限因为容器可以挂载宿主机目录。生产环境慎用。4.2 镜像下载慢加速器配置的正确姿势装完 Docker 第一件事是拉镜像默认从 Docker Hub 拉国内网络环境下速度非常不稳定。网上流传的第三方加速器地址很多已经失效了我最终选择在/etc/docker/daemon.json里配置了可用的镜像加速地址{ registry-mirrors: [https://docker.m.daocloud.io] }然后重启 Dockersudo systemctl daemon-reload sudo systemctl restart docker配置完加速器后拉镜像速度明显快了很多。有一点要注意加速器只对 Docker Hub 官方镜像有效如果你拉的是第三方仓库的镜像比如某个私有 registry走的是另一套逻辑加速器不会生效。4.3 服务启动失败排查链路不能乱遇到过一次 Docker 服务启动失败systemctl status docker显示failed但没给出具体原因。我按照下面的链路一步步排查sudo systemctl status docker # 查看服务状态 sudo journalctl -u docker --since 10 minutes ago # 查看 dockerd 日志 sudo dockerd --debug # 前台启动观察输出dockerd --debug这一步很关键。用前台模式启动可以看到完整的调试日志比 journal 里的信息详细得多。最终定位到是/etc/docker/daemon.json的 JSON 格式写错了多了一个逗号导致配置解析失败。这个教训是改配置之前先备份改完之后用命令验证 JSON 格式python3 -m json.tool /etc/docker/daemon.json4.4 容器网络不通防火墙和 iptables 的冲突跑一个 Nginx 容器做测试做了端口映射-p 8080:80结果外部访问不到。我先检查了容器本身docker ps docker exec -it nginx-test bash curl localhost:80容器内部访问正常说明 Nginx 没问题问题出在宿主机的网络栈。再检查端口监听sudo ss -tlnp | grep 8080有监听但外部就是访问不通。最后发现是 ufw 防火墙的问题sudo ufw statusDocker 默认会用 iptables 做端口转发但 ufw 的规则优先级会导致 Docker 的流量被拦截。解决办法分两种一种是直接放行端口sudo ufw allow 8080/tcp另一种更优雅修改/etc/default/ufw里的DEFAULT_FORWARD_POLICY把DROP改成ACCEPT确保转发流量可以被处理。改完记得sudo ufw reload。注意如果你用的是带图形界面的 Linux 发行版桌面版还有 NetworkManager 和 firewalld 的叠加问题。Server 版相对干净主要就是 ufw 和 iptables 的协作关系需要理解。4.5 容器内 DNS 解析异常还有一个经常遇到的坑容器里apt update报 DNS 解析失败但宿主机一切正常。这通常是 Docker 的 DNS 配置问题。默认情况下 Docker 使用宿主机的 DNS 设置但如果宿主机用的是 systemd-resolvedUbuntu 默认容器拿到的 DNS 地址可能是127.0.0.53这个地址在容器内部是访问不通的。解决办法是在/etc/docker/daemon.json里显式指定 DNS{ dns: [8.8.8.8, 223.5.5.5] }重启 Docker 后重新创建容器DNS 解析恢复正常。这个坑在云服务器上尤其常见因为云厂商的虚拟网络和 systemd-resolved 的交互方式比较特殊。5. 装完 Docker 之后这些配置我建议你立刻做5.1 日志轮转配置防止 /var 分区被塞满Docker 默认不限制容器日志大小一个高频日志的容器跑上几天就能吃光磁盘。我在/etc/docker/daemon.json里加上日志轮转配置{ log-driver: json-file, log-opts: { max-size: 20m, max-file: 5 } }max-size表示单个日志文件最大 20MBmax-file表示最多保留 5 个文件。这样每个容器的日志最多占用 100MB 空间超出后会自动轮转清理。这个配置只对新建容器生效已存在的容器需要删掉重建才会使用新配置。5.2 磁盘空间管理别让 dangling 镜像堆积Docker 用久了会出现大量none标签的 dangling 镜像占空间且没有实际用途。我养成了定期清理的习惯docker system prune -a --volumes这条命令会删除所有未使用的容器、镜像、网络和卷。但注意--volumes会连匿名卷一起删如果你的容器有数据存在匿名卷里删之前先确认。5.3 使用 Docker Compose 编排多容器服务单容器直接docker run没问题但一旦涉及多个服务配合比如应用 MySQL Redis手动跑命令就显得很低效。Ubuntu Server 25.10 上我安装的docker-compose-plugin支持直接用docker compose子命令不需要单独装 Python 版的 docker-composedocker compose version创建一个常见的 Nginx MySQL 服务编排文件services: web: image: nginx:alpine ports: - 8080:80 volumes: - ./html:/usr/share/nginx/html db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: yourpassword volumes: - db_data:/var/lib/mysql volumes: db_data:启动服务docker compose up -d这里的优势是配置即代码服务间的网络自动管理一键启停、一键查看日志。5.4 配置服务开机自启如果你希望 Docker 随系统自动启动服务器场景通常需要执行sudo systemctl enable docker sudo systemctl enable containerd重点是containerd也要开启自启因为 dockerd 依赖它来管理容器运行时。只 enable docker 不 enable containerd 的话重启后 Docker 可能因为 containerd 未启动而异常。6. 几个容易被忽略但早晚会遇上的细节容器时区问题。默认容器使用 UTC 时区日志时间会比北京时间早 8 小时。启动容器时加上-e TZAsia/Shanghai或者在 Compose 里配置environment: TZ: Asia/Shanghai省得后面排查问题时要换算时差。docker exec和docker attach别搞混。exec是在容器里执行新命令attach是附加到容器主进程的终端。调试时用docker exec -it container /bin/bash没问题但不要用attach去接管正在运行的容器容易把容器主进程弄挂。镜像 tag 别只用 latest。生产环境拉镜像务必用具体版本号比如nginx:1.27-alpine不要用nginx:latest。latest 是滚动更新的今天和明天的镜像可能不是同一个版本出了问题很难回溯。系统安装完成、Docker 跑起来只是个开始。我个人的体会是Docker 本身不难难的是把它放进一个长期服务的环境里不闹脾气。日志清理、网络规则、存储规划、版本管理这些琐碎但重要的配置一开始做对后面能少熬几个夜。
返回列表