Ubuntu系统Docker与docker-compose完整部署指南:从安装到实战
2026/8/13 6:35:51 网站建设 项目流程

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命令进行安装和管理。

为什么选择这种方式?

  1. 版本可控:你可以明确指定安装Docker的版本(例如docker-ce=5:20.10.13~3-0~ubuntu-focal),这对于需要环境一致性的CI/CD流水线或生产集群至关重要。
  2. 易于升级与管理:安装后,Docker会被集成到系统的包管理体系中。你可以使用apt updateapt upgrade来安全地更新Docker,系统会处理好依赖关系。
  3. 官方支持:直接从Docker官方仓库获取软件包,保证了组件的完整性和安全性,后续获取安全补丁也最直接。
  4. 可追溯:所有操作都是明确的命令行,便于写入自动化脚本(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 a+r /etc/apt/keyrings/docker.gpg

操作意图

  1. 创建目录/etc/apt/keyrings并设置合适权限。
  2. 使用curl下载Docker官方的GPG公钥。
  3. 使用gpg --dearmor将下载的密钥转换为APT可识别的格式。
  4. 将转换后的密钥文件保存到指定位置,并赋予可读权限。

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是jammy,20.04是focal)。
  • stable:使用稳定版仓库。Docker还提供testnightly仓库,但生产环境请务必使用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-ce:Docker社区版引擎,核心。
  • docker-ce-cli:Docker命令行工具,你用来执行docker run等命令的程序。
  • containerd.io:行业标准的容器运行时,Docker引擎底层依赖它来管理容器的生命周期。
  • docker-buildx-plugin:支持Docker Buildx,用于构建多平台镜像(如同时构建amd64和arm64镜像)。
  • docker-compose-plugin:Docker官方推出的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

重要提示:执行此命令后,组权限变更不会立即生效。它只修改了用户所属组的配置,但当前已登录的会话并没有更新这个信息。

生效方法(任选其一)

  1. 注销并重新登录:最彻底的方式。
  2. 开启一个新的终端会话:在新终端中,用户组信息会被重新读取。
  3. 使用newgrp命令(临时):在当前终端执行newgrp docker,但这只影响当前shell。

生效后,你应该就可以直接运行docker versiondocker run hello-world,而不再需要sudo了。

避坑指南:将用户加入docker组等同于赋予其root权限。因为Docker守护进程以root身份运行,容器内的root用户几乎拥有对主机内核的完全访问权。因此,切勿将不受信任的用户加入docker。在个人开发机上可以这样做,但在多用户服务器上需谨慎评估。

6. 安装独立版docker-compose

虽然Docker官方推出了docker compose插件,但社区中大量的教程、脚本和项目仍然使用独立的docker-compose(v1版本)。为了获得最好的兼容性,我建议安装独立的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-compose

6.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.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "3" }, "storage-driver": "overlay2" } EOF

配置项详解

  • registry-mirrors:镜像加速器地址列表。可以配置多个,Docker会按顺序尝试。这里添加了中国科技大学、网易和百度的镜像源。
  • exec-opts:native.cgroupdriver=systemd:建议设置cgroup驱动为systemd,这与Ubuntu使用systemd初始化系统的特性更匹配,能提高系统稳定性。
  • log-driverlog-opts:配置Docker容器的日志驱动为json-file,并限制单个日志文件最大100MB,最多保留3个文件,防止日志占满磁盘。
  • storage-driver:存储驱动设置为overlay2,这是目前Linux内核推荐且性能较好的存储驱动。

7.2 重启Docker服务使配置生效

修改配置后,必须重启Docker服务。

sudo systemctl daemon-reload sudo systemctl restart docker
  • systemctl 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_HOST=redis # 设置环境变量 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%的日常场景:

  1. 启动所有服务(后台模式)

    docker-compose up -d

    -d代表“detached”,在后台运行。

  2. 查看服务运行状态

    docker-compose ps
  3. 查看服务日志(可指定服务名)

    docker-compose logs -f web # -f 表示跟随日志输出
  4. 停止所有服务

    docker-compose down

    此命令会停止并移除所有容器、网络(默认创建的网络),但不会移除数据卷和镜像。如果想同时移除数据卷,加-v参数:docker-compose down -v

  5. 构建或重新构建服务镜像

    docker-compose build

    当修改了Dockerfile或构建上下文后,需要重新构建镜像。

  6. 在运行中的服务容器内执行命令

    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.0wordpress:latest镜像,然后创建网络、卷,并启动两个容器。

使用docker-compose ps查看状态,两个服务都应为Up

9.3 访问与验证

打开你的浏览器,访问http://你的服务器IP:8080。你应该能看到WordPress的著名“五分钟安装”页面。按照提示设置站点标题、管理员账号密码,即可完成安装。

9.4 管理部署

  • 停止服务docker-compose down。由于我们在docker-compose.yml中定义了命名卷db_datawp_data,即使容器被删除,你的数据库和WordPress文件(主题、插件、上传内容)也会被保留。下次docker-compose up -d时,数据会恢复。
  • 更新WordPress:只需修改docker-compose.ymlwordpress服务的镜像标签(如wordpress:6.4),然后运行docker-compose up -d,Compose会自动拉取新镜像并重新创建容器,数据卷保持不变。
  • 备份数据:数据卷位于Docker管理的位置(通常/var/lib/docker/volumes/下)。更规范的备份方式是使用docker run --volumes-from或专门的备份容器。

10. 常见问题排查与优化技巧

即使按照步骤操作,你也可能会遇到一些问题。这里记录了一些常见坑点及其解决方案。

10.1 Docker服务启动失败

问题现象:执行sudo systemctl status docker时,状态不是active (running),而是failed

排查思路

  1. 查看详细日志

    sudo journalctl -xu docker

    这是最关键的排查命令,会输出Docker服务的详细启动日志。

  2. 常见原因与解决

    • 存储驱动问题:旧系统或某些VPS可能不支持overlay2。可以尝试在/etc/docker/daemon.json中将其改为devicemappervfs(性能差,仅作测试),然后重启Docker。但建议优先升级内核。
    • IP地址冲突:Docker默认使用的网段(如172.17.0.0/16)可能与公司内网冲突。需要在daemon.json中配置bip(网桥IP)或default-address-pools
    • 磁盘空间不足:Docker镜像和容器会占用空间。使用df -hdocker system df检查。
    • SELinux/AppArmor:在某些严格的安全策略下,可能需要调整策略或将其设置为宽容模式(仅用于测试)。

10.2 用户加入docker组后仍需要sudo

问题:执行了usermod命令并重新登录后,运行docker ps仍提示权限拒绝。

解决

  1. 确认当前用户是否在docker组中:
    groups $USER
    查看输出是否包含docker
  2. 如果包含,可能是当前Shell会话的组信息未刷新。最可靠的方法是注销当前用户(或断开SSH连接),然后重新登录
  3. 也可以尝试用sg docker -c “docker ps”来临时以docker组身份执行命令,但这并非长久之计。

10.3 docker-compose命令未找到

问题:执行docker-compose --version提示command not found

解决

  1. 检查文件是否下载到正确位置且具有执行权限:
    ls -lh /usr/local/bin/docker-compose
    应显示类似-rwxr-xr-x的权限。
  2. 检查/usr/local/bin是否在你的PATH环境变量中:
    echo $PATH
    通常默认就在。如果不在,可以手动添加,或在/usr/bin下创建一个软链接:
    sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

10.4 镜像拉取速度慢或失败

问题docker pulldocker-compose up时卡在拉取镜像。

解决

  1. 确认镜像加速器配置已生效:执行docker info,查看Registry Mirrors
  2. 尝试不同的镜像源:修改/etc/docker/daemon.json中的registry-mirrors,换成其他可用的国内源,然后重启Docker。
  3. 使用代理:如果你有可用的HTTP/HTTPS代理,可以在Docker服务配置中设置。创建或编辑/etc/systemd/system/docker.service.d/http-proxy.conf
    [Service] Environment="HTTP_PROXY=http://proxy.example.com:8080" Environment="HTTPS_PROXY=http://proxy.example.com:8080" Environment="NO_PROXY=localhost,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.yml
    services: 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.ymlDockerfile(如果需要)、.env环境变量文件以及项目代码。通过.env文件管理敏感配置(如密码),并通过docker-compose config命令来验证Compose文件的最终渲染结果,这是一个避免配置错误的好习惯。当项目复杂后,可以考虑使用docker-compose.override.yml来为不同环境(开发、测试)提供差异化配置。记住,容器应该是无状态的,所有需要持久化的数据务必通过volumes映射到宿主机或使用外部存储服务。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询