
1. 从“为什么是Ubuntu 20.04”说起如果你正在看这篇文章大概率是刚接触Docker或者需要在Ubuntu 20.04这个特定的长期支持版本上搭建开发或生产环境。我之所以选择从这个版本切入是因为它至今仍是许多企业服务器和开发者桌面上的主力军拥有极佳的稳定性和广泛的社区支持。Docker作为容器化技术的代名词其核心价值在于提供了一套标准化的应用打包、分发和运行方案彻底解决了“在我机器上能跑”的世纪难题。在Ubuntu上安装Docker可以说是将两个最稳定、最流行的开源技术栈结合为后续的微服务部署、CI/CD流水线、甚至是个人学习实验打下最坚实的地基。很多人第一次接触Docker安装可能会直奔Docker Desktop。但在Linux服务器环境下我们通常使用的是更轻量、更纯粹的Docker Engine。这篇文章我会带你走一遍在Ubuntu 20.04 Focal Fossa上从零开始安装和配置Docker Engine的完整流程。这不仅仅是把几条命令敲进去我会详细解释每一步背后的意图帮你避开那些官方文档可能一笔带过但实际部署中却频频踩坑的细节。比如为什么我们要用Docker官方的仓库而不是Ubuntu自带的版本如何为国内网络环境配置镜像加速安装完成后第一个容器该怎么跑又该如何管理这些我都会一一拆解。2. 安装前的环境审视与准备工作在动手安装任何软件之前理清环境现状是避免后续诡异问题的关键。对于Docker安装我们需要关注三个核心点系统版本、包管理工具状态以及关键的内核特性支持。2.1 确认你的Ubuntu 20.04系统首先打开终端用下面这条命令确认你的系统版本。这不仅能确保我们后续的步骤是针对20.04的也能帮你检查系统是否处于一个正常更新的状态。lsb_release -a你应该能看到类似下面的输出No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.6 LTS Release: 20.04 Codename: focal关键信息是Release: 20.04和Codename: focal。LTS代表长期支持这意味着系统会获得长达五年的安全更新和维护这也是我们选择它的主要原因。如果你的系统版本不是20.04那么本文中关于仓库源的部分命令可能需要调整。2.2 更新apt包索引并安装基础工具在安装Docker之前确保你的apt包列表是最新的这是一个好习惯。同时我们还需要安装一些工具用于让apt可以通过HTTPS协议使用仓库。sudo apt update sudo apt upgrade -y执行upgrade会更新所有已安装的包到最新版本。在生产环境中你可能需要更谨慎地评估升级的影响但对于个人学习或新环境直接升级到最新稳定版通常是最佳选择。接下来安装必要的依赖包sudo apt install -y apt-transport-https ca-certificates curl software-properties-common gnupg lsb-release我来解释一下这几个包的作用apt-transport-https允许apt通过HTTPS协议下载包。Docker的官方仓库地址是HTTPS的没有这个包就无法添加源。ca-certificates系统中CA证书的集合用于验证HTTPS连接的安全性。curl命令行下载工具我们用它来下载Docker的GPG密钥。software-properties-common提供add-apt-repository命令这是一个管理PPA个人软件包存档和第三方仓库的便捷工具。gnupgGNU隐私卫士用于处理和验证我们即将添加的Docker官方GPG密钥确保软件包的完整性和来源可信。lsb-release我们已经用过的命令它提供lsb_release工具来获取系统发行版信息。注意有些极简安装的Ubuntu Server可能默认没有安装curl或software-properties-common所以这一步是必须的不要跳过。2.3 内核支持检查虚拟化与存储驱动Docker依赖于Linux内核的特定功能。对于Ubuntu 20.04其默认内核5.4 LTS已经包含了所有必需的功能但检查一下总没坏处。检查cgroups和命名空间支持这些是容器隔离的基础。现代Linux内核默认都已启用。检查存储驱动Docker需要一种存储驱动来管理镜像和容器的分层文件系统。对于Ubuntu默认且推荐的是overlay2驱动。你可以通过以下命令检查当前内核是否支持grep overlay /proc/filesystems如果输出包含nodev overlay则说明支持。Ubuntu 20.04 肯定是支持的。关于“Virtualization Support Not Detected”这是一个在Windows/macOS上安装Docker Desktop时常见的错误但在原生Linux包括Ubuntu上安装Docker Engine时通常不会遇到。这个错误提示的是CPU的硬件虚拟化支持Intel VT-x / AMD-V未开启这主要是为了在非Linux宿主机上运行一个轻量级Linux虚拟机来承载Docker Engine。在Ubuntu这样的Linux宿主机上Docker Engine是直接运行在宿主内核之上的它利用的是内核的cgroup和namespace功能而非硬件虚拟化。所以如果你在Ubuntu上安装可以暂时忽略这个网络热词相关的错误。3. 添加Docker官方APT仓库并安装这是整个安装过程的核心步骤。我们不使用Ubuntu自带的、可能版本陈旧的docker.io包而是添加Docker官方的APT仓库以确保获得最新、最稳定的版本并享受持续的更新。3.1 添加Docker的GPG密钥GPG密钥用于验证从Docker仓库下载的软件包是否真实、未被篡改。这是软件供应链安全的重要一环。curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg逐段解释这个命令curl -fsSL-f表示静默失败不输出错误页面-s静默模式-S在错误时显示错误信息-L跟随重定向。组合起来就是以安静、可靠的方式下载。https://download.docker.com/...Docker官方GPG密钥的下载地址。| sudo gpg --dearmor -o ...将下载的密钥流通过管道传递给gpg --dearmor命令进行解码并将输出结果保存到/usr/share/keyrings/docker-archive-keyring.gpg这个系统级的密钥环文件中。--dearmor是将ASCII格式的密钥转换为二进制格式。3.2 设置稳定的Docker APT仓库源接下来我们需要告诉apt系统去哪里找Docker的软件包。我们将仓库信息写入一个.list文件。echo \ deb [arch$(dpkg --print-architecture) signed-by/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null这个命令看起来复杂我们来拆解deb [...]这是一个Debian系软件仓库的声明行。[arch$(dpkg --print-architecture)动态获取当前系统的架构如amd64, arm64确保添加对应架构的仓库。signed-by/usr/share/keyrings/docker-archive-keyring.gpg指定用于验证此仓库软件包的GPG密钥路径就是我们上一步保存的。https://download.docker.com/linux/ubuntuDocker官方仓库的基地址。$(lsb_release -cs)动态获取系统的代号Codename对于Ubuntu 20.04就是focal。这确保了仓库路径的准确性。stable使用稳定版仓库。Docker还提供test和nightly仓库但生产环境强烈建议只用stable。| sudo tee /etc/apt/sources.list.d/docker.list将前面echo生成的整行内容通过tee命令写入到/etc/apt/sources.list.d/docker.list文件中。/etc/apt/sources.list.d/目录是专门用于存放额外软件源列表的。 /dev/null将tee命令的标准输出丢弃让终端保持干净。3.3 安装Docker Engine添加仓库后更新apt包索引然后安装Docker Engine及其相关组件。sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin这里安装的包是docker-ceDocker Community Edition即Docker引擎本身。docker-ce-cliDocker命令行客户端你用的docker命令就来自这里。containerd.io一个行业标准的容器运行时Docker Engine实际上是在它的基础上构建的。它是容器生命周期管理的核心。docker-compose-plugin这是Docker Compose的V2版本它作为一个Docker CLI插件安装命令是docker compose注意没有横线。它比独立的docker-composeV1工具集成度更高是未来的方向。实操心得我强烈建议直接安装docker-compose-plugin而不是旧的docker-compose。新版本功能更全与Docker CLI集成更好命令也几乎兼容。如果你遇到的老项目脚本用的是docker-compose带横线可以创建一个软链接sudo ln -s /usr/libexec/docker/cli-plugins/docker-compose /usr/local/bin/docker-compose来兼容。安装完成后Docker服务会自动启动并设置为开机自启。你可以用以下命令验证sudo systemctl status docker你应该看到状态是active (running)。4. 以非root用户身份运行Docker关键配置默认情况下Docker守护进程以root用户运行而docker命令也需要root权限通过sudo。这既不方便也不安全任何能运行docker命令的用户实质上就拥有了root权限。最佳实践是将你的普通用户添加到docker用户组。4.1 管理docker用户组首先检查docker组是否存在通常安装时会自动创建。getent group docker如果存在输出会显示组名、组ID和成员列表。然后将你的当前用户假设用户名是your_username添加到docker组sudo usermod -aG docker $USERusermod修改用户属性的命令。-aG-a表示追加append-G指定附加组。合起来就是将用户追加到指定的附加组中而不会影响用户已有的其他附加组。这里一定要用-aG如果只用-G而漏了-a会导致用户被从其他所有附加组中移除只保留docker组这可能会让你无法登录图形界面或使用sudodocker组名。$USER环境变量代表当前登录的用户名。4.2 生效组权限并验证用户组信息的变更不会立即在当前已登录的会话中生效。你需要完全退出当前终端并重新登录或者启动一个新的登录会话例如打开一个新的终端窗口或者使用su - $USER命令切换会话。重新登录后验证你是否已在docker组中groups输出列表中应该包含docker。现在你应该可以不用sudo直接运行docker命令了docker version这条命令会输出客户端和服务端的版本信息。如果成功说明配置正确。踩坑警告这是新手最容易忽略的一步也是导致后续很多“权限被拒绝”错误的根源。务必确保重新登录后再测试。另外出于安全考虑只有在可信的单用户开发机上才建议这样做。在生产服务器上应严格控制docker组的成员或通过其他机制如sudo规则来管理Docker权限。5. 配置国内镜像加速器从Docker Hub拉取镜像时国内网络速度可能很慢甚至不稳定。配置一个国内镜像加速器可以极大提升体验。常见的加速器有阿里云、腾讯云、中科大、网易等提供的服务。5.1 获取并配置加速器地址这里以阿里云镜像加速器为例需要注册阿里云账号免费获取专属加速地址。登录阿里云容器镜像服务控制台。在左侧菜单找到“镜像工具” - “镜像加速器”。你会看到针对不同操作系统的配置指南复制Ubuntu专属的加速器地址格式类似https://xxxx.mirror.aliyuncs.com。我们需要修改Docker守护进程的配置文件/etc/docker/daemon.json。如果文件不存在就创建它。sudo tee /etc/docker/daemon.json -EOF { registry-mirrors: [https://xxxx.mirror.aliyuncs.com] } EOF请将https://xxxx.mirror.aliyuncs.com替换为你从阿里云控制台复制的真实地址。如果你有多个加速器可以用数组形式添加例如[https://mirror1, https://mirror2]。5.2 重启Docker服务并验证配置修改配置后需要重启Docker服务使配置生效。sudo systemctl daemon-reload sudo systemctl restart docker验证加速器是否配置成功docker info在输出信息中找到Registry Mirrors:这一行下面应该列出你刚刚配置的镜像加速器地址。经验之谈镜像加速器主要加速的是docker.io即Docker Hub的官方镜像拉取。对于其他第三方仓库如quay.io,gcr.io是无效的。拉取那些镜像慢通常需要其他网络解决方案但这超出了本文讨论的安全范畴。另外daemon.json文件是JSON格式必须严格遵守语法最后一个元素后不能有逗号否则会导致Docker服务启动失败。可以用sudo systemctl status docker检查服务状态如果失败用sudo journalctl -xe -u docker查看详细日志排错。6. 运行你的第一个容器Hello-World安装和配置都完成后让我们用最经典的hello-world镜像来验证整个Docker环境是否工作正常。docker run hello-world第一次运行这条命令时会发生以下几件事Docker客户端联系Docker守护进程。守护进程发现本地没有hello-world:latest这个镜像。守护进程根据配置的镜像加速器从Docker Hub或加速器缓存拉取hello-world镜像。镜像拉取成功后守护进程基于这个镜像创建一个新的容器并运行。容器内预置的程序执行在终端输出一段欢迎信息然后容器进程退出。如果你看到类似下面的输出恭喜你Docker已经成功安装并运行Hello from Docker! This message shows that your installation appears to be working correctly. ...这个简单的测试验证了Docker客户端/服务端通信正常、网络拉取镜像正常、容器创建和运行正常。7. Docker基础使用与管理实操现在Docker已经就绪我们来学习几个最核心、最常用的命令和操作让你能真正开始用起来。7.1 镜像Image的基本操作镜像是容器的模板是一个只读的文件层集合。拉取镜像从仓库下载镜像到本地。docker pull ubuntu:20.04这里我们拉取一个Ubuntu 20.04的官方镜像。ubuntu是镜像名20.04是标签Tag指定版本。不指定标签时默认为latest。列出本地镜像docker images # 或者使用更现代的 image ls 命令 docker image ls这会显示镜像仓库名、标签、镜像ID、创建时间和大小。删除镜像docker rmi image_id_or_name # 例如docker rmi hello-world如果镜像有对应的容器存在即使容器已停止需要先删除容器才能删除镜像。可以使用-f强制删除但不推荐。7.2 容器Container的生命周期管理容器是镜像的运行实例。运行一个新容器docker run是最强大的命令它结合了创建和启动。docker run -it --rm ubuntu:20.04 /bin/bash-i保持标准输入STDIN打开允许交互。-t分配一个伪终端pseudo-TTY通常与-i连用实现交互式shell。--rm容器退出后自动删除它。非常适合临时测试避免留下大量停止的容器。ubuntu:20.04使用的镜像。/bin/bash容器启动后要执行的命令这里我们启动一个bash shell。 执行后你会进入容器的bash终端。输入exit或CtrlD退出容器会停止并被删除因为用了--rm。在后台运行容器守护态docker run -d --name my_nginx -p 8080:80 nginx-d后台运行detached mode。--name my_nginx给容器起个名字便于后续管理。-p 8080:80端口映射将宿主机的8080端口映射到容器的80端口。nginx使用Nginx官方镜像。 运行后你可以在宿主机浏览器访问http://localhost:8080看到Nginx欢迎页。查看容器docker ps # 查看正在运行的容器 docker ps -a # 查看所有容器包括已停止的停止、启动、重启容器docker stop my_nginx docker start my_nginx docker restart my_nginx进入正在运行的容器docker exec -it my_nginx /bin/bashexec命令是在已运行的容器中执行新命令常用于进入容器调试。-it参数同样是为了获得交互式终端。查看容器日志docker logs my_nginx docker logs -f my_nginx # -f 参数可以持续跟踪follow日志输出删除容器docker rm my_nginx # 删除已停止的容器 docker rm -f my_nginx # -f 强制删除运行中的容器7.3 使用Docker Compose编排多容器应用对于由多个容器如Web应用、数据库、缓存组成的复杂应用使用docker-compose现在是docker compose插件来编排是标准做法。它通过一个docker-compose.yml文件来定义和运行所有服务。假设我们有一个简单的docker-compose.yml文件用于启动一个WordPress网站和其依赖的MySQL数据库version: 3.8 services: db: image: mysql:8.0 volumes: - db_data:/var/lib/mysql restart: always environment: MYSQL_ROOT_PASSWORD: some_root_password MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress_password wordpress: depends_on: - db image: wordpress:latest ports: - 8000:80 restart: always environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress_password WORDPRESS_DB_NAME: wordpress volumes: - wp_data:/var/www/html volumes: db_data: wp_data:在包含这个YAML文件的目录下只需一条命令即可启动整个应用栈docker compose up -d-d同样表示后台运行。使用docker compose down可以停止并移除所有相关容器、网络默认创建的网络但会保留数据卷volumes。如果需要同时删除数据卷可以加-v参数docker compose down -v。注意事项docker composeV2插件的命令是docker compose中间有空格而旧的docker-composeV1独立工具命令是docker-compose中间是横线。我们安装的是插件版所以用前者。语法上两者高度兼容但V2功能更丰富。8. 日常维护与故障排查思路Docker用起来之后日常维护和问题排查是绕不开的。这里分享几个高频场景和我的处理思路。8.1 磁盘空间管理Docker运行久了会积累很多不再使用的镜像、停止的容器、构建缓存和日志占用大量磁盘空间。查看磁盘使用概况docker system df这个命令会清晰地列出镜像、容器、数据卷和构建缓存各自占用的空间非常直观。一键清理谨慎使用docker system prune -a这个命令会删除所有已停止的容器、所有未被任何容器使用的网络、所有悬空镜像none标签的镜像以及构建缓存。-a参数还会删除所有未被容器使用的镜像不仅仅是悬空镜像。执行前请务必确认对于生产环境建议有选择性地清理。针对性清理删除所有已停止的容器docker container prune删除所有悬空镜像docker image prune删除所有未被使用的数据卷docker volume prune特别注意这可能会删除数据库数据8.2 容器内文件与宿主机互传有时需要将宿主机上的配置文件复制到容器内或者将容器内产生的日志、数据复制出来。从宿主机复制到容器docker cp /path/to/local/file my_container:/path/in/container从容器复制到宿主机docker cp my_container:/path/in/container/file /path/on/host8.3 常见问题排查命令当容器行为异常时按以下顺序排查通常能定位大部分问题检查容器状态docker ps -a看容器是否在运行退出代码是什么。非0的退出代码通常意味着容器内主进程崩溃。查看容器日志docker logs container_name这是第一手信息源应用程序的错误信息通常在这里。进入容器检查docker exec -it container_name /bin/sh如果镜像没有bash用sh。进入后可以检查配置文件、进程状态、网络连通性等。检查容器资源docker stats实时查看所有容器的CPU、内存、网络IO使用情况判断是否有资源瓶颈。检查Docker服务本身sudo systemctl status docker和sudo journalctl -u docker --since 1 hour ago查看Docker守护进程的日志排查引擎级别的问题。8.4 关于“Docker Desktop Failed to Start”的再次说明在Ubuntu上我们安装的是Docker Engine不是Docker Desktop。因此网络热词中提到的“Docker Desktop failed to start because virtualization support wasn’t detected”错误在Ubuntu原生安装中不会出现。如果你在Ubuntu上通过其他方式比如用.deb包安装了Docker Desktop并遇到此错误那通常意味着你的CPU硬件虚拟化支持VT-x/AMD-V在BIOS/UEFI中被禁用了需要去主板设置里开启。你是在虚拟机如VMware、VirtualBox里安装的Ubuntu但虚拟化嵌套支持Nested Virtualization没有开启。这需要在VMware或VirtualBox的虚拟机设置中专门启用。对于在物理机或已正确配置嵌套虚拟化的虚拟机上安装的Ubuntu 20.04按照本文步骤安装Docker Engine是不会有这个问题的。