ARTICLE DETAIL

资讯详情

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

Ubuntu安装Docker全指南:从apt源到Compose部署与排错

Ubuntu安装Docker全指南:从apt源到Compose部署与排错 最近帮朋友折腾服务器又在Ubuntu上装了一轮Docker。说实话这东西装起来不算难但网上教程一堆有的让你用脚本有的让你用apt有的直接让你下载deb包新手很容易看晕。尤其是你手上这台机器是Ubuntu 22.04还是20.04内核版本到了几之前有没有装过旧版Docker这些都会直接影响你的安装方式和后续体验。我打算把这些年踩过的坑整理成一套实操流程从安装前准备、三种安装方式对比、装完后的必要配置到Compose部署、问题排查尽量讲清楚每一步背后的原因而不是光丢几条命令。这篇文章特别适合刚接触Ubuntu的初学者也适合那些在服务器上反复安装Docker、但总被权限、网络、镜像源问题困扰的朋友。看完你至少能明白为什么推荐用官方apt仓库而不是直接apt install docker.io为什么装完还要配daemon.json以及当docker run报错时应该怎么排查。1. 安装前的准备先搞清楚你的系统和历史残留1.1 确认Ubuntu版本和系统架构装Docker之前第一步不是急着复制粘贴命令而是确认你的Ubuntu版本和CPU架构。不同的Ubuntu版本对应不同的内核版本和service管理方式Docker对系统版本有明确要求。我见过有人在Ubuntu 16.04上硬装新版Docker结果内核太老存储驱动直接起不来那种问题排查起来非常痛苦。先跑这两条命令lsb_release -a uname -mlsb_release -a会输出发行版描述、版本号、代号比如Ubuntu 22.04.4 LTS代号jammy。uname -m输出架构x86_64就是amd64aarch64就是arm64。为什么一定要看架构因为你添加软件源和下载deb包时要选对架构。官方源里amd64的架构标识是amd64arm64是arm64乱选的话apt会报“无法定位软件包”。下面是我实际接触到的常见版本情况Ubuntu版本代号内核特点Docker支持情况20.04 LTSfocalkernel 5.4支持overlay2、cgroups v1默认支持但部分新特性受内核限制22.04 LTSjammykernel 5.15cgroups v2默认支持度高推荐日常使用24.04 LTSnoblekernel 6.8cgroups v2支持度高新版Docker体验更好如果你的系统是老版本比如16.04、18.04我建议先升级系统再装Docker。不是不能装而是老系统上很多包依赖过旧安装过程中容易遇到各种莫名其妙的问题。博主级别的操作习惯是先把基础环境弄干净再动手。1.2 清理历史残留的Docker安装如果你之前用apt、snap或者某些脚本装过Docker现在想重新安装一定先看看残留。残留的旧配置、旧daemon.json、旧的网络规则都可能导致新装成功后磁盘和网络表现异常。比如旧版本创建过docker0网桥新版本启动时发现网桥名称冲突直接启动失败。先检查当前系统到底有没有装过Docker相关包dpkg -l | grep -i docker如果有输出说明之前装过。清理干净再装新版本sudo apt remove --purge -y docker docker-engine docker.io containerd runc sudo rm -rf /var/lib/docker sudo rm -rf /var/lib/containerd注意一个细节/var/lib/docker是Docker默认的数据目录里面存着镜像、容器、卷。如果你只是想重装Docker但还想保留现有镜像和容器数据这个目录不能直接删。如果你是要彻彻底底重来删掉没问题。但实际情况是很多新手不知道这点一删就把数据全丢了。所以执行删除前先想清楚你到底要“重装”还是“清理”。还有个容易被忽略的点Ubuntu的snap也可能带着docker包。可以用snap list | grep docker检查一下有的话sudo snap remove docker。snap版Docker路径和配置都跟官方不一样混用会出问题。2. 三种主流安装方式与选型分析2.1 官方apt仓库安装最稳妥、我最推荐的方式为什么推荐先走官方apt仓库这条路线因为Docker官方为Ubuntu维护了独立的软件源里面的docker-ce、docker-ce-cli、containerd.io都是经过官方测试的版本更新及时依赖关系清晰。而直接用apt install docker.io装的是Ubuntu发行版仓库里的Docker版本往往滞后而且与官方的新版命令行工具、Compose插件可能存在兼容性差异。从Ubuntu 22.04开始apt源里的docker.io版本其实也能用但版本更新缓慢。比如你想用docker compose这个新命令旧版本docker.io可能只支持docker-compose还得单独装Python版的compose。装官方源就没这个烦恼。操作步骤如下。首先安装需要的依赖sudo apt update sudo apt install -y ca-certificates curl gnupg lsb-release这些软件包是给后续添加源准备的。ca-certificates用于HTTPS验证curl下载密钥gnupg处理GPG钥匙lsb-release读取发行版名称。然后添加Docker官方的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这里用install -m 0755 -d先创建目录是为了确保目录存在且权限正确。把GPG密钥去armor化后存成二进制的.gpg文件这是新版apt的推荐做法。接着添加软件源。Ubuntu不同版本代号不同所以我推荐用变量自动适配echo deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null这条命令里几个关键点dpkg --print-architecture自动输出当前架构不会写死。lsb_release -cs输出系统代号比如jammy、focal。注意仓库类型是stable如果你所在区域访问docker.com很慢建议先配置镜像加速源这个后面单讲。很多人卡在这一步是因为网络问题curl下载GPG key超时就以为是命令写错了。更新索引并安装sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin这里装的不只是docker引擎还包含了Buildx插件和Compose插件。Buildx用于多架构镜像构建Compose用于编排多容器应用。一次性装齐能省掉后续很多麻烦。安装完成先看版本确认成功docker --version docker compose version装完官方仓库后默认情况下docker命令需要root权限。先别急后面有专门的用户组配置章节。2.2 官方脚本安装图快但不够透明很多教程会推荐一条命令安装curl -fsSL https://get.docker.com | sh官方脚本的好处是傻瓜式自动检测系统、添加源、安装依赖和Docker。但坏处是它不够透明脚本会在你不知情的情况下改系统源。另外如果脚本下载失败或断在中间你很难排查它到底执行到哪一步。我的建议是临时测试环境可以用脚本生产环境、公司服务器、需要长期维护的机器还是老老实实用手动apt仓库的方式。原因很简单手动方式你知道自己做了什么出了问题也知道从哪里查。那种“一条命令搞定”的安装如果哪天Docker起不来你连系统被改过什么都没概念。脚本安装示范curl -fsSL https://get.docker.com | sudo sh脚本跑完后同样验证一下版本。脚本安装的Docker也是官方软件源里的docker-ce本质上跟手动添加源是一样的只是省去了index步骤。如果你已经用脚本装好了后续想换回手动管理其实也不太必要因为体系一致。2.3 离线安装面向内网环境的方案如果你的机器完全不能访问外网或者公司内网有合规要求那上面基于curl和apt源的方式全都不适用。这时候需要用deb包离线安装。首先要在一台可以联网的同版本Ubuntu机器上下载对应deb包cd /tmp sudo apt download docker-ce docker-ce-cli containerd.ioapt download只下载不安装。下载下来的文件是.deb包。把它们传到目标机器后执行sudo dpkg -i docker-ce*.deb docker-ce-cli*.deb containerd.io*.deb但dpkg安装时很可能报依赖缺失比如需要libicu、libseccomp等。这时候你还需要同时下载这些依赖包或者配置好内网apt源。说白了离线安装最麻烦的不是Docker本身而是依赖链。如果你不是重度离线需求我更推荐在能联网的机器上先生成一个离线包目录把所有依赖一次性下齐再拷贝到内网用apt install /path/*.deb安装。这属于额外的工程化技巧了本期先不展开。3. 安装后的系统级配置让Docker用得更顺手3.1 用户组配置不想每次sudo就做这一步Docker安装完成后立刻会遇到权限问题。直接跑docker ps会提示docker: permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: dial unix /var/run/docker.sock: connect: permission denied这是因为Docker守护进程绑定的是Unix socket默认只有root用户和docker用户组的成员有权限访问。解决方法一是每次都加sudo二是把当前用户加入docker组。执行sudo usermod -aG docker $USER注意这条命令只是把用户加入docker组需要重新登录或执行newgrp docker才能生效。很多新手执行完立刻又试docker ps发现还是permission denied以为是没生效其实是没有刷新会话。更彻底的做法是退出当前SSH会话重新登录一次。另外加入docker组等于把这个用户提升到了与root相当的特权。因为用户可以操作Docker创建特权容器进而访问宿主机文件系统。所以生产服务器上要谨慎决定哪些用户能加入docker组这不是一个无伤大雅的权限操作。3.2 配置开机自启和daemon.json参数安装官方版本时systemd服务文件一般已经就位。但为了保证重启后Docker能自动运行建议手动启用sudo systemctl enable docker sudo systemctl start docker如果Docker已经运行systemctl start不会重复启动放心执行。状态可以用systemctl status docker查看按下q退出详情页。接下来是重点修改/etc/docker/daemon.json。这个是Docker守护进程的配置文件很多高级配置都写在这里。常见的痛点有两个国内镜像拉取慢、容器日志无限增长。如果没有这个文件手动创建sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json EOF { registry-mirrors: [https://docker.m.daocloud.io], log-driver: json-file, log-opts: { max-size: 10m, max-file: 3 }, storage-driver: overlay2 } EOF逐项解释registry-mirrors镜像加速地址。国内直连Docker Hub很慢换成可用的镜像加速器能显著提升拉取速度。注意不同时间段、不同地域可用的镜像源不同需要自己实测。log-driver和log-opts限制容器日志大小。默认情况下一个容器如果不加限制日志文件可以无限增长直到占满磁盘。我踩过这个坑一个简单的测试容器半年没管日志居然吞掉了几十GB磁盘空间。storage-driver设置为overlay2。这是现代Ubuntu上推荐的存储驱动比老的aufs更稳定高效。不过如果内核足够新Docker默认会自动选择overlay2不写也没问题。修改完配置需要重启Docker才能生效sudo systemctl restart docker重启后可以用docker info查看当前使用的存储驱动和日志配置有没有生效。4. Docker Compose 安装与项目部署实例4.1 Compose插件安装方式很多人还在用docker-compose这套老的工具链。新版Docker更推荐把Compose作为Docker CLI的一个子命令集成进来也就是docker compose。如果安装第2节推荐的官方apt仓库方式并且装了docker-compose-plugin那docker compose直接可用。验证docker compose version如果你的环境没有Compose插件可以单独安装sudo apt install -y docker-compose-plugin或者在GitHub上下载二进制包。这里我就不贴下载链接了重点说一下Compose文件的结构。因为Compose让你可以把多个容器定义在一个YAML文件里然后一次性启动非常适合MySQL、Redis、Nginx这类多服务场景。比如你搜“docker安装mysql8.0并使用”这样的需求用Compose搭一台MySQL加一个管理面板就非常舒服。4.2 实战案例用docker compose部署MySQL 8.0我先写一个最小可用的docker-compose.ymlversion: 3.8 services: mysql: image: mysql:8.0 container_name: my_mysql restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: rootPssw0rd MYSQL_DATABASE: mydb ports: - 3306:3306 volumes: - mysql_data:/var/lib/mysql command: --character-set-serverutf8mb4 --collation-serverutf8mb4_unicode_ci volumes: mysql_data:保存文件后启动docker compose up -d解释一下关键点image: mysql:8.0表示使用MySQL 8.0官方镜像。container_name自定义容器名否则Compose会自动生成带前缀的容器名。restart: unless-stopped表示容器非手动停止时Docker重启或系统重开都会自动拉起这个容器。environment里设置了root密码和初始数据库名。ports把宿主机的3306映射到容器的3306。注意如果宿主机自己已经装了3306端口服务这里会冲突。volumes使用命名卷mysql_data持久化数据容器删除后数据还在。command追加MySQL启动参数指定字符集为utf8mb4。启动后检查状态docker compose ps docker logs my_mysql如果你只是想用数据库不用进入容器。在宿主机上用客户端连接即可mysql -h127.0.0.1 -P3306 -uroot -p这里容易踩的坑是MySQL8默认认证插件是caching_sha2_password一些老的客户端程序连接时会报认证不支持。解决办法是在Compose的command里加一行--default-authentication-pluginmysql_native_password或者在创建用户时指定认证插件。但新客户端一般没这个问题不用盲目改。Compose的真正优势在于多服务联动。比如一边是MySQL一边是Redis再加个Nginx反代一个YAML文件全部搞定。以后我会专门写一篇更复杂的Compose编排文章这里先确保你能跑通基础。5. 常见问题与排查技巧实录5.1 拉取镜像慢或超时网上一搜“docker拉取镜像慢”大多数回答都是让你配加速。上面我已经给出了daemon.json的写法。但如果配了加速还是慢建议换个镜像加速地址。很多镜像加速本质上是代理时好时坏可以备两个地址一个挂了换另一个。拉取镜像失败时先区分是DNS问题还是网络问题。用docker pull报EOF、timeout这种多半是网络阻断。先试curl https://registry-1.docker.io/v2/看能否连通再逐级排查。5.2 docker run报“network not found”或“iptables”错误比较常见的错误是docker: Error response from daemon: create network ... network not found这种一般是你手动删除了默认的bridge网络或者误删了docker_gwbridge。解决办法是重建网络docker network prune这个命令会清理掉所有没有被容器使用的网络注意先确认没有正在使用的自定义网络。另外就是iptables相关报错。Ubuntu上自带的ufw防火墙和Docker的iptables规则有可能会冲突。最直接的表现是容器能启动但宿主机的某些端口访问不到容器里的服务。这通常是ufw防住了Docker映射的端口或者是Docker直接把规则写进了INPUT链导致你的ufw配置失效。我的处理习惯是生产环境如果不需要Docker完全绕过防火墙就把容器端口映射到具体接口上同时在ufw里放行对应端口。比如sudo ufw allow 3306/tcp别小看这个我见过有人折腾一晚上最后发现是ufw开着但没放行端口。5.3 Docker服务启不来daemon.json写错的典型场景改完daemon.json后docker服务无法启动这是高频问题。大多数原因是JSON语法错误。也许你觉得这里不就一个逗号吗但就是这一个小逗号systemd会让整个服务起不来。排查方法sudo systemctl status docker如果显示Failed再看具体日志journalctl -u docker -n 50同时也可以先手动验证 daemon.json 的语法。用Python的json模块python3 -m json.tool /etc/docker/daemon.json如果输出object不存在或报ParseError那说明JSON格式确实错了。检查引号、逗号、括号。这个问题在运维群里的出现频率极高写配置时一定养成先校验再重启的习惯。5.4 Ubuntu特有的AppArmor权限问题Ubuntu默认启用了AppArmor而Docker的容器会被加载默认的AppArmor profile。偶尔你运行某些特权操作容器时会遇到奇怪的权限拒绝比如operation not permitted。这时先别怀疑Docker考虑是不是AppArmor在拦截。临时绕过方法是给容器加上docker run --security-opt apparmorunconfined --rm -it ubuntu bash如果问题解决确实和AppArmor有关。生产环境不建议直接全禁而是根据需要写一条宽松的AppArmor profile。还有一个Ubuntu上常见的坑是cgroup v2。新版Docker完全支持cgroup v2一般没问题。但如果你在WSL2或者某些虚拟机里跑Ubuntu会出现资源限制不生效的问题。检查方式stat -fc %T /sys/fs/cgroup输出cgroup2fs说明是cgroup v2输出tmpfs则是v1。Docker 20.10以上版本对v2支持已经非常成熟如果还是遇到问题优先升级Docker版本。5.5 卸载Docker时保留数据还是删干净最后顺手提一下卸载。有些朋友装完发现怎么老出问题想退回或者彻底删除。如果你确认不再使用干净卸载的完整流程sudo apt purge -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin sudo rm -rf /var/lib/docker sudo rm -rf /etc/docker sudo rm -rf /var/lib/containerd如果你只是出问题想重装留数据的话就别删/var/lib/docker。先把镜像容器导出来再操作。这是我的经验卸载这种操作宁可多留个目录也别为了省那点磁盘空间把重要容器永久丢失。最后我自己的一点实操体会安装Docker这件事单看命令似乎五六步但当你真的在Ubuntu上一步步操作下来会发现细节非常多。我后来习惯的做法是装之前先花十分钟确认系统状态、清理残留装完立刻把用户组、daemon.json、日志限制、开机自启全部配好。这样能避免后续90%的坑。再补一句很多人喜欢用脚本一把梭但服务器上我还是建议手动走官方apt仓库的流程。脚本适合实验不适合稳定环境。毕竟Docker装好后你要在上面跑数据库、服务、定时任务如果系统底子没打好后面的问题都是加倍放大。希望这篇文章能帮你少走弯路装完直接上手用起来。
返回列表