Ubuntu系统Docker与docker-compose完整部署指南:从安装到实战 1. 项目概述为什么要在Ubuntu上部署Docker生态如果你是一名开发者、运维工程师或者正在学习云原生和微服务那么Docker几乎是你绕不开的技术。它通过容器化技术将应用及其所有依赖打包成一个标准化的单元实现了“一次构建处处运行”的梦想。而Ubuntu作为最流行、社区支持最完善的Linux发行版之一自然成为了运行Docker的首选平台。今天要聊的就是在Ubuntu系统上从零开始完整部署Docker引擎及其黄金搭档docker-compose的全过程。这不仅仅是一个安装教程。我会带你理解每一个命令背后的逻辑解释不同安装方式的选择并分享我在生产环境和开发环境中反复折腾后总结出的实战经验与避坑指南。无论你是刚接触Linux的新手还是想优化现有部署流程的老手这篇详尽的指南都能让你在Ubuntu上搭建一个稳定、高效的Docker工作环境避免那些令人头疼的兼容性问题和权限错误。2. 核心思路与方案选型官方仓库 vs 便捷脚本在Ubuntu上安装Docker主流方法有两种使用Docker官方提供的便捷安装脚本或者通过添加Docker的APT软件源来安装。这两种方式各有优劣选择哪一种取决于你的具体场景和对系统的控制需求。2.1 官方APT源安装可控性与稳定性的首选这是我个人最推荐也是生产环境部署的标准做法。它的核心思路是将Docker官方的软件仓库地址添加到Ubuntu系统的APT源列表中然后像安装其他系统软件一样通过apt命令进行安装和管理。为什么选择这种方式版本可控你可以明确指定安装Docker的版本例如docker-ce5:20.10.13~3-0~ubuntu-focal这对于需要环境一致性的CI/CD流水线或生产集群至关重要。易于升级与管理安装后Docker会被集成到系统的包管理体系中。你可以使用apt update和apt upgrade来安全地更新Docker系统会处理好依赖关系。官方支持直接从Docker官方仓库获取软件包保证了组件的完整性和安全性后续获取安全补丁也最直接。可追溯所有操作都是明确的命令行便于写入自动化脚本Ansible, Shell等和审计。当然这种方式步骤稍多需要手动添加仓库和GPG密钥但对于追求稳定和长期维护的系统来说多花的这几分钟是完全值得的。2.2 便捷安装脚本快速体验与一次性环境Docker官方提供了一个名为get-docker.sh的Shell脚本。只需一行命令curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh脚本就会自动检测你的系统并完成所有安装步骤。它的适用场景是什么快速体验在临时测试机、学习环境或者快速搭建演示环境时它极其方便。不关心具体版本脚本通常安装最新的稳定版适合紧跟最新特性的场景。为什么不推荐在生产环境首选它“黑盒”操作脚本自动执行了大量后台操作你无法精确控制它安装了哪些组件、配置了什么参数。一旦出现问题排查难度较大。升级路径不清晰通过脚本安装后如何升级是再次运行脚本还是用包管理器这容易产生混淆。可能覆盖自定义配置脚本可能会覆盖你系统中已有的Docker相关配置。结论对于学习和测试脚本很方便但对于需要严肃对待的开发机或服务器请务必使用APT源安装。本指南将主要围绕APT源安装这一更优方案展开并涵盖docker-compose的独立安装。3. 前期准备与系统检查在开始安装之前我们需要为Ubuntu系统做一些准备工作并检查一些关键的先决条件这能避免很多后续的报错。3.1 更新系统与安装基础工具首先确保你的系统软件包列表是最新的并安装一些可能用到的工具。sudo apt update sudo apt upgrade -y sudo apt install -y apt-transport-https ca-certificates curl software-properties-common gnupg lsb-release命令解析apt update刷新本地软件包索引从配置的源服务器获取最新的软件包列表。apt upgrade -y升级所有可升级的已安装软件包-y参数表示自动确认。apt-transport-https允许APT通过HTTPS协议下载软件包Docker仓库需要它。ca-certificates使系统能够识别和信任CA颁发的SSL证书。curl命令行工具用于从网络下载数据如下载GPG密钥。software-properties-common提供add-apt-repository等管理软件源的工具。gnupg用于加密和数字签名的工具这里用于管理APT源的GPG密钥。lsb-release提供一个标准命令lsb_release -cs来获取系统代号如focal、jammy方便我们动态添加源。3.2 卸载旧版本Docker如有如果你的系统上存在旧版本或冲突的Docker如docker,docker-engine,docker.io最好先清理它们。sudo apt remove -y docker docker-engine docker.io containerd runc注意docker.io是Ubuntu官方仓库里一个较旧的Docker版本与我们即将安装的docker-ce社区版冲突必须移除。3.3 验证内核与虚拟化支持Docker运行依赖于Linux内核的特定功能。虽然Ubuntu桌面版通常已满足但服务器版或某些最小化安装可能需要检查。检查内核版本uname -r建议内核版本在3.10以上。Ubuntu 20.04/22.04默认内核都在5.x完全满足。检查cgroups和命名空间支持 这些是容器技术的基石现代Linux内核默认启用。ls /sys/fs/cgroup/如果能看到cpu,memory等目录说明cgroups已挂载。针对物理机或虚拟机检查虚拟化支持 这对于运行非Linux容器如Windows容器或使用某些加速功能有益但对于标准的Linux容器不是必须条件。如果你在安装Docker Desktop for Linux时遇到“virtualization support not detected”错误才需要关注此项。对于纯命令行安装docker-ce通常无需此步。# 检查CPU是否支持虚拟化AMD是svm Intel是vmx grep -E --color (vmx|svm) /proc/cpuinfo有输出即表示CPU支持。如果是在VMware等虚拟机里安装Ubuntu需要在虚拟机设置中开启“虚拟化引擎”相关选项。4. 安装Docker引擎docker-ce这是最核心的步骤。我们将采用添加Docker官方APT仓库的方式。4.1 添加Docker的官方GPG密钥GPG密钥用于验证从Docker仓库下载的软件包的完整性和真实性确保软件包未被篡改。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操作意图创建目录/etc/apt/keyrings并设置合适权限。使用curl下载Docker官方的GPG公钥。使用gpg --dearmor将下载的密钥转换为APT可识别的格式。将转换后的密钥文件保存到指定位置并赋予可读权限。4.2 添加Docker的APT软件源接下来我们需要告诉APT系统从哪里可以找到Docker的软件包。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命令拆解arch$(dpkg --print-architecture)动态获取当前系统的架构如amd64, arm64确保添加正确的仓库路径。signed-by/etc/apt/keyrings/docker.gpg指定用于验证此仓库的GPG密钥文件路径。$(lsb_release -cs)动态获取当前Ubuntu的版本代号例如Ubuntu 22.04是jammy20.04是focal。stable使用稳定版仓库。Docker还提供test和nightly仓库但生产环境请务必使用stable。sudo tee ...将前面echo输出的仓库配置字符串写入到/etc/apt/sources.list.d/docker.list文件中。/etc/apt/sources.list.d/目录下的文件会被APT自动读取。4.3 安装Docker引擎及其组件添加仓库后更新APT缓存然后安装Docker。sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin安装包说明docker-ceDocker社区版引擎核心。docker-ce-cliDocker命令行工具你用来执行docker run等命令的程序。containerd.io行业标准的容器运行时Docker引擎底层依赖它来管理容器的生命周期。docker-buildx-plugin支持Docker Buildx用于构建多平台镜像如同时构建amd64和arm64镜像。docker-compose-pluginDocker官方推出的docker compose插件注意是docker compose一个单词作为插件。但我们通常还是使用独立的docker-compose带横线二进制文件它更通用。这里安装插件是为了功能互补。4.4 验证Docker安装与基础操作安装完成后启动Docker服务并设置开机自启然后运行一个测试容器。# 启动Docker服务 sudo systemctl start docker # 设置Docker服务开机自启 sudo systemctl enable docker # 查看Docker服务状态 sudo systemctl status docker状态显示active (running)即表示服务已成功启动。运行Hello World容器sudo docker run hello-world这个命令会从Docker Hub拉取一个极小的测试镜像并运行。如果看到“Hello from Docker!”等欢迎信息说明Docker引擎安装、运行、拉取镜像、创建容器整个流程全部成功。实操心得第一次docker run如果失败常见原因是网络问题无法连接Docker Hub或权限问题。可以先尝试sudo docker pull hello-world单独拉取镜像看网络是否通畅。5. 管理用户权限免sudo执行docker命令默认情况下只有root用户和docker组的成员才有权限与Docker守护进程通信即运行docker命令。为了避免每次都要输入sudo我们需要将当前用户加入docker组。# 将当前登录用户添加到docker组 sudo usermod -aG docker $USER重要提示执行此命令后组权限变更不会立即生效。它只修改了用户所属组的配置但当前已登录的会话并没有更新这个信息。生效方法任选其一注销并重新登录最彻底的方式。开启一个新的终端会话在新终端中用户组信息会被重新读取。使用newgrp命令临时在当前终端执行newgrp docker但这只影响当前shell。生效后你应该就可以直接运行docker version或docker run hello-world而不再需要sudo了。避坑指南将用户加入docker组等同于赋予其root权限。因为Docker守护进程以root身份运行容器内的root用户几乎拥有对主机内核的完全访问权。因此切勿将不受信任的用户加入docker组。在个人开发机上可以这样做但在多用户服务器上需谨慎评估。6. 安装独立版docker-compose虽然Docker官方推出了docker compose插件但社区中大量的教程、脚本和项目仍然使用独立的docker-composev1版本。为了获得最好的兼容性我建议安装独立的docker-compose二进制文件。我们将从GitHub Releases页面下载其稳定版本。6.1 下载最新稳定版的docker-compose首先访问 docker-compose的GitHub Releases页面 查看最新的稳定版本号。例如假设最新版本是v2.24.5。在终端中使用curl命令下载对应架构的二进制文件。请将下面命令中的v2.24.5替换为你在GitHub上看到的最新版本。# 下载docker-compose二进制文件到/usr/local/bin目录需要sudo权限 sudo curl -L https://github.com/docker/compose/releases/download/v2.24.5/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose参数解析-L让curl跟随重定向GitHub的下载链接通常会重定向。$(uname -s)获取系统内核名称Linux。$(uname -m)获取机器硬件名称x86_64, aarch64等。-o指定输出文件路径。我们将其下载到/usr/local/bin这是存放用户安装的软件的标准目录通常在系统的PATH环境变量中。6.2 赋予执行权限下载的文件默认没有执行权限需要手动添加。sudo chmod x /usr/local/bin/docker-compose6.3 验证安装安装完成后检查版本以确认安装成功。docker-compose --version # 或使用新版本的命令格式如果你也安装了插件 docker compose version如果输出类似Docker Compose version v2.24.5则表明安装成功。注意事项独立版docker-compose和Docker官方的docker compose插件可以共存。它们的命令略有不同前者是docker-compose后者是docker compose。在编写docker-compose.yml文件时两者语法基本兼容。我个人习惯使用独立版因为它在各种自动化脚本和文档中出现频率更高。7. 配置Docker引擎与镜像加速默认安装的Docker可能需要一些优化配置以提升在国内的使用体验。7.1 配置国内镜像加速器从Docker Hub拉取镜像速度可能较慢。我们可以配置国内镜像加速器如阿里云、腾讯云、中科大等提供的服务。编辑Docker守护进程的配置文件/etc/docker/daemon.json。如果文件不存在则创建它。sudo tee /etc/docker/daemon.json -EOF { registry-mirrors: [ https://docker.mirrors.ustc.edu.cn, https://hub-mirror.c.163.com, https://mirror.baidubce.com ], exec-opts: [native.cgroupdriversystemd], log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 }, storage-driver: overlay2 } EOF配置项详解registry-mirrors镜像加速器地址列表。可以配置多个Docker会按顺序尝试。这里添加了中国科技大学、网易和百度的镜像源。exec-opts:native.cgroupdriversystemd建议设置cgroup驱动为systemd这与Ubuntu使用systemd初始化系统的特性更匹配能提高系统稳定性。log-driver和log-opts配置Docker容器的日志驱动为json-file并限制单个日志文件最大100MB最多保留3个文件防止日志占满磁盘。storage-driver存储驱动设置为overlay2这是目前Linux内核推荐且性能较好的存储驱动。7.2 重启Docker服务使配置生效修改配置后必须重启Docker服务。sudo systemctl daemon-reload sudo systemctl restart dockersystemctl daemon-reload重新加载systemd管理的所有单元文件确保systemd识别到docker.service的配置变更。systemctl restart docker重启Docker服务。验证加速器是否生效docker info在输出信息中查找Registry Mirrors部分应该能看到你刚才配置的镜像地址。8. docker-compose核心概念与快速上手docker-compose是一个用于定义和运行多容器Docker应用的工具。它通过一个YAML格式的配置文件docker-compose.yml来管理一组相关联的容器解决了“多个容器如何协作”的问题。8.1 docker-compose.yml文件结构解析一个最简单的docker-compose.yml示例如下它定义了一个Web应用包含应用本身和Redis缓存version: 3.8 # 指定Compose文件格式的版本 services: # 定义所有需要运行的容器服务 web: # 第一个服务名为“web” build: . # 使用当前目录下的Dockerfile构建镜像 ports: - 5000:5000 # 端口映射主机端口:容器端口 volumes: - .:/code # 数据卷挂载将主机当前目录挂载到容器的/code depends_on: - redis # 依赖关系此服务启动前先启动redis服务 environment: - REDIS_HOSTredis # 设置环境变量 redis: # 第二个服务名为“redis” image: redis:alpine # 直接使用Docker Hub上的redis:alpine镜像 volumes: - redis-data:/data # 使用命名卷挂载持久化Redis数据 volumes: # 在文件底部声明所有用到的命名卷 redis-data: # 定义一个名为redis-data的卷关键指令说明buildvsimagebuild指定构建上下文和Dockerfile路径来创建镜像image指定从仓库拉取现成的镜像。ports端口映射格式为HOST:CONTAINER。将容器内部端口暴露给主机。volumes数据卷挂载用于持久化数据或与主机共享文件。可以是主机路径/host/path:/container/path也可以是命名卷volume_name:/container/path。depends_on定义服务启动顺序。web服务会等待redis服务进入“健康”或“运行”状态后再启动。environment设置容器内的环境变量。8.2 常用docker-compose命令掌握以下几个命令就能应对90%的日常场景启动所有服务后台模式docker-compose up -d-d代表“detached”在后台运行。查看服务运行状态docker-compose ps查看服务日志可指定服务名docker-compose logs -f web # -f 表示跟随日志输出停止所有服务docker-compose down此命令会停止并移除所有容器、网络默认创建的网络但不会移除数据卷和镜像。如果想同时移除数据卷加-v参数docker-compose down -v。构建或重新构建服务镜像docker-compose build当修改了Dockerfile或构建上下文后需要重新构建镜像。在运行中的服务容器内执行命令docker-compose exec web bash # 在web服务容器内启动一个bash shell docker-compose exec redis redis-cli # 在redis服务容器内执行redis-cli命令9. 实战演练使用docker-compose部署WordPress让我们通过一个经典的例子——部署包含WordPress和MySQL的博客系统来串联所有知识点。9.1 创建项目目录与编写docker-compose.yml首先创建一个项目目录并进入。mkdir my-wordpress cd my-wordpress然后创建docker-compose.yml文件nano docker-compose.yml将以下内容粘贴进去version: 3.8 services: db: image: mysql:8.0 # 在生产环境中应使用 secrets 或环境变量文件来管理密码此处仅为演示。 environment: MYSQL_ROOT_PASSWORD: somewordpress MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress volumes: - db_data:/var/lib/mysql restart: always # 为MySQL服务添加健康检查确保WordPress启动时数据库已就绪 healthcheck: test: [CMD, mysqladmin, ping, -h, localhost] timeout: 20s retries: 10 wordpress: depends_on: db: condition: service_healthy # 等待db服务健康状态为healthy image: wordpress:latest ports: - 8080:80 # 将主机的8080端口映射到容器的80端口 environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress WORDPRESS_DB_NAME: wordpress volumes: - wp_data:/var/www/html restart: always volumes: db_data: wp_data:9.2 启动WordPress栈在my-wordpress目录下运行docker-compose up -d你会看到Docker开始拉取mysql:8.0和wordpress:latest镜像然后创建网络、卷并启动两个容器。使用docker-compose ps查看状态两个服务都应为Up。9.3 访问与验证打开你的浏览器访问http://你的服务器IP:8080。你应该能看到WordPress的著名“五分钟安装”页面。按照提示设置站点标题、管理员账号密码即可完成安装。9.4 管理部署停止服务docker-compose down。由于我们在docker-compose.yml中定义了命名卷db_data和wp_data即使容器被删除你的数据库和WordPress文件主题、插件、上传内容也会被保留。下次docker-compose up -d时数据会恢复。更新WordPress只需修改docker-compose.yml中wordpress服务的镜像标签如wordpress:6.4然后运行docker-compose up -dCompose会自动拉取新镜像并重新创建容器数据卷保持不变。备份数据数据卷位于Docker管理的位置通常/var/lib/docker/volumes/下。更规范的备份方式是使用docker run --volumes-from或专门的备份容器。10. 常见问题排查与优化技巧即使按照步骤操作你也可能会遇到一些问题。这里记录了一些常见坑点及其解决方案。10.1 Docker服务启动失败问题现象执行sudo systemctl status docker时状态不是active (running)而是failed。排查思路查看详细日志sudo journalctl -xu docker这是最关键的排查命令会输出Docker服务的详细启动日志。常见原因与解决存储驱动问题旧系统或某些VPS可能不支持overlay2。可以尝试在/etc/docker/daemon.json中将其改为devicemapper或vfs性能差仅作测试然后重启Docker。但建议优先升级内核。IP地址冲突Docker默认使用的网段如172.17.0.0/16可能与公司内网冲突。需要在daemon.json中配置bip网桥IP或default-address-pools。磁盘空间不足Docker镜像和容器会占用空间。使用df -h和docker system df检查。SELinux/AppArmor在某些严格的安全策略下可能需要调整策略或将其设置为宽容模式仅用于测试。10.2 用户加入docker组后仍需要sudo问题执行了usermod命令并重新登录后运行docker ps仍提示权限拒绝。解决确认当前用户是否在docker组中groups $USER查看输出是否包含docker。如果包含可能是当前Shell会话的组信息未刷新。最可靠的方法是注销当前用户或断开SSH连接然后重新登录。也可以尝试用sg docker -c “docker ps”来临时以docker组身份执行命令但这并非长久之计。10.3 docker-compose命令未找到问题执行docker-compose --version提示command not found。解决检查文件是否下载到正确位置且具有执行权限ls -lh /usr/local/bin/docker-compose应显示类似-rwxr-xr-x的权限。检查/usr/local/bin是否在你的PATH环境变量中echo $PATH通常默认就在。如果不在可以手动添加或在/usr/bin下创建一个软链接sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose10.4 镜像拉取速度慢或失败问题docker pull或docker-compose up时卡在拉取镜像。解决确认镜像加速器配置已生效执行docker info查看Registry Mirrors。尝试不同的镜像源修改/etc/docker/daemon.json中的registry-mirrors换成其他可用的国内源然后重启Docker。使用代理如果你有可用的HTTP/HTTPS代理可以在Docker服务配置中设置。创建或编辑/etc/systemd/system/docker.service.d/http-proxy.conf[Service] EnvironmentHTTP_PROXYhttp://proxy.example.com:8080 EnvironmentHTTPS_PROXYhttp://proxy.example.com:8080 EnvironmentNO_PROXYlocalhost,127.0.0.1,.internal然后执行sudo systemctl daemon-reload sudo systemctl restart docker。10.5 容器时间与宿主机时间不一致问题容器内的时间不是东八区CST或与宿主机相差8小时。解决在运行容器或编写docker-compose.yml时将宿主机的时区文件挂载到容器内。命令行docker run -v /etc/localtime:/etc/localtime:ro ...docker-compose.ymlservices: your-service: volumes: - /etc/localtime:/etc/localtime:ro:ro表示只读挂载。10.6 磁盘空间管理Docker会占用大量磁盘空间尤其是镜像、容器和构建缓存。清理命令查看磁盘使用docker system df删除所有已停止的容器、未使用的网络、构建缓存和悬空镜像docker system prune -a警告-a参数会删除所有未被容器使用的镜像包括可能被其他镜像依赖的中间层镜像使用前请确认。仅删除悬空镜像docker image prune清理数据卷谨慎会删除数据docker volume prune建议将清理工作加入定时任务crontab定期清理。安装和配置只是第一步真正发挥Docker和Compose威力的在于日常的使用模式。我个人习惯为每个独立项目创建一个目录里面包含docker-compose.yml、Dockerfile如果需要、.env环境变量文件以及项目代码。通过.env文件管理敏感配置如密码并通过docker-compose config命令来验证Compose文件的最终渲染结果这是一个避免配置错误的好习惯。当项目复杂后可以考虑使用docker-compose.override.yml来为不同环境开发、测试提供差异化配置。记住容器应该是无状态的所有需要持久化的数据务必通过volumes映射到宿主机或使用外部存储服务。