Docker安装与环境配置详解

本文是Docker系列专栏的第二篇,面向从零开始的开发者,系统讲解Docker在Windows、macOS、Linux三大平台的安装方法、环境配置、版本管理、镜像加速、核心参数调优、命令大全以及图形化管理工具的使用。


引言

Docker自2013年开源以来,已经成为容器化技术的事实标准。无论是微服务架构、CI/CD流水线、还是云原生应用部署,Docker都扮演着不可或缺的角色。然而,对于初学者而言,Docker的安装与配置往往是第一道门槛——不同操作系统的安装方式各异、网络加速配置容易踩坑、生产环境的参数调优更需要深厚的经验积累。

本篇博文将从最基础的系统要求评估讲起,手把手带你完成Docker在所有主流平台上的安装,深入解析每一个配置参数的含义,并提供生产环境的完整配置模板。无论你使用的是Windows、macOS还是Linux,无论你是个人开发者还是企业运维工程师,都能在这篇文章中找到适合你的安装与配置方案。

在阅读本文之前,建议先阅读本专栏的第一篇《Docker核心概念与架构解析》,了解容器、镜像、仓库等基本概念,这将有助于你更好地理解本文中的配置选项和操作命令。

适合的读者群体

本文适合以下读者:

  • 零基础初学者:从未接触过Docker,希望从安装开始系统学习
  • 前端/后端开发者:需要在本地搭建开发环境,使用容器化技术提升开发效率
  • 运维工程师:需要在服务器上部署和管理Docker环境
  • 架构师:需要了解Docker的配置选项,为系统设计提供技术依据
  • 技术决策者:需要评估Docker在不同平台的可行性和成本

阅读建议

对于不同需求的读者,建议的阅读路径如下:

  • 快速上手:直接阅读第二章或第三章/第四章中对应你操作系统的安装部分,然后阅读第六章配置镜像加速器
  • 系统学习:按照章节顺序从头到尾阅读,每读完一章动手实践
  • 问题排查:直接跳到第十章查找你遇到的问题和解决方案
  • 深入配置:重点阅读第七章和第八章,掌握Docker的核心配置和命令

环境约定

本文中的命令和配置基于以下环境验证:

  • Docker Engine 27.x(Linux)
  • Docker Desktop 4.30+(Windows/macOS)
  • Ubuntu 22.04 LTS / CentOS 9 Stream(Linux)
  • Windows 11 23H2(Windows)
  • macOS 14 Sonoma(macOS,Apple Silicon)

文中标注的版本号和功能特性以2024年的Docker版本为准。由于Docker更新频繁,部分细节可能随版本变化而调整,建议结合官方文档对照阅读。


第一章 安装前的准备工作

在正式安装Docker之前,做好充分的准备工作可以避免后续安装过程中遇到的各种问题。本章将从系统要求、硬件资源、BIOS设置、内核版本、旧版本卸载以及网络环境六个方面进行详细讲解。

1.1 系统要求评估(Windows/macOS/Linux)

Docker对不同操作系统的版本有明确的要求,下面分别介绍三大平台的系统要求。

1.1.1 Windows系统要求

Docker Desktop for Windows对Windows系统有以下要求:

要求项 最低要求 推荐配置
操作系统版本 Windows 10 64位(Build 19041+) Windows 11 22H2或更高
系统类型 64位处理器 64位多核处理器
内存 4GB 8GB或以上
虚拟化 启用WSL 2或Hyper-V 启用WSL 2
后端 WSL 2(推荐)或Hyper-V WSL 2

注意:Windows 10 Home版不支持Hyper-V,但支持WSL 2后端,因此Home版用户也可以使用Docker Desktop,前提是系统版本满足Build 19041+的要求。

你可以通过以下方式检查Windows版本:

# 查看Windows版本信息
winver

# 通过命令行查看系统版本
systeminfo | findstr /B /C:"OS Name" /C:"OS Version"

# 查看系统架构
echo %PROCESSOR_ARCHITECTURE%

输出示例:

OS Name:                   Microsoft Windows 11 Pro
OS Version:                10.0.22631 N/A Build 22631
1.1.2 macOS系统要求

Docker Desktop for Mac的要求如下:

要求项 Intel芯片Mac Apple Silicon Mac
macOS版本 macOS 11(Big Sur)或更高 macOS 12(Monterey)或更高
芯片 Intel Core i3及以上 Apple M1/M2/M3/M4
内存 4GB 8GB
虚拟化 内置Hypervisor.framework Rosetta 2(可选)

检查macOS版本的方法:

# 查看macOS版本
sw_vers

# 查看CPU架构
uname -m

输出示例:

ProductVersion: 14.4
BuildVersion:   23E214

# uname -m 输出
arm64    # Apple Silicon
x86_64   # Intel
1.1.3 Linux系统要求

Linux是Docker原生支持的平台,不同发行版的要求略有差异:

发行版 支持版本 架构
Ubuntu 20.04, 22.04, 24.04 x86_64, arm64, armhf
Debian 11 (Bullseye), 12 (Bookworm) x86_64, arm64, armhf
CentOS 7, 8 Stream, 9 Stream x86_64, arm64
RHEL 8, 9 x86_64, arm64
Fedora 38, 39, 40 x86_64, arm64
openSUSE Leap 15.4+ x86_64, arm64

检查Linux发行版和内核版本:

# 查看发行版信息
cat /etc/os-release

# 查看内核版本
uname -r

# 查看系统架构
uname -m

输出示例(Ubuntu 22.04):

PRETTY_NAME="Ubuntu 22.04.4 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.4 LTS (Jammy Jellyfish)"

# 内核版本
5.15.0-91-generic

# 架构
x86_64

1.2 硬件资源规划(CPU、内存、磁盘)

Docker虽然本身是一个轻量级的守护进程,但运行容器时会消耗系统资源。合理的硬件规划对Docker的稳定运行至关重要。

1.2.1 CPU资源规划

Docker守护进程本身占用的CPU资源很少,但容器内运行的应用会消耗CPU。以下是不同场景下的CPU建议:

使用场景 最低CPU核心数 推荐CPU核心数 说明
学习/测试 1核 2核 单容器简单应用
个人开发 2核 4核 多容器开发环境
小型生产 4核 8核 中小规模应用部署
中型生产 8核 16核+ 多服务微服务架构
大型生产 16核+ 32核+ 高并发容器化集群

你可以通过以下命令查看CPU信息:

# Linux查看CPU核心数
lscpu
nproc

# macOS查看CPU信息
sysctl -n hw.ncpu
sysctl -n machdep.cpu.brand_string

# Windows查看CPU信息
echo %NUMBER_OF_PROCESSORS%
1.2.2 内存资源规划

内存是Docker运行中最容易成为瓶颈的资源。每个容器都会占用一定的内存,如果不加以限制,可能导致宿主机OOM(Out of Memory)。

使用场景 最低内存 推荐内存 说明
学习/测试 2GB 4GB 基础容器运行
个人开发 4GB 8GB 多容器编排
小型生产 8GB 16GB 应用+数据库
中型生产 16GB 32GB 微服务集群
大型生产 32GB 64GB+ 高密度容器部署

查看系统内存:

# Linux查看内存
free -h

# macOS查看内存
sysctl -n hw.memsize

# Windows查看内存
wmic memorychip get capacity
1.2.3 磁盘资源规划

Docker的镜像和容器数据会占用大量磁盘空间。以下是磁盘使用的关键考虑因素:

# Linux查看磁盘使用情况
df -h

# 查看Docker占用的磁盘空间
docker system df

Docker磁盘使用的关键点:

  • 镜像层存储:每个镜像层默认存储在/var/lib/docker目录下
  • 容器可写层:容器的可写层(writable layer)也存储在数据目录中
  • 数据卷:Volume数据持久化存储
  • 构建缓存:镜像构建过程中产生的缓存
  • 日志文件:容器运行日志

磁盘规划建议:

  • 数据目录建议使用SSD或NVMe硬盘,提升镜像拉取和容器启动速度
  • 至少预留20GB空间用于Docker基础数据
  • 生产环境建议将Docker数据目录挂载到独立磁盘
  • 定期使用docker system prune清理无用资源

1.3 BIOS虚拟化设置(VT-x/AMD-V)

虽然Docker在Linux上是原生运行的(不需要虚拟化),但在Windows和macOS上,Docker Desktop依赖虚拟化技术来运行Linux容器。因此,BIOS中的硬件虚拟化必须启用。

1.3.1 什么是硬件虚拟化

硬件虚拟化是指CPU提供的一种硬件级别的虚拟化支持能力。简单来说,它允许一个物理CPU模拟出多个虚拟CPU,使得多个操作系统可以同时运行在同一台物理机器上。这种技术是实现虚拟机和容器化技术的基础。

在Docker的语境下,硬件虚拟化的作用主要体现在Windows和macOS平台上。由于Docker容器本质上运行的是Linux进程,在Linux系统上Docker可以直接利用Linux内核的命名空间和cgroup功能来隔离容器,不需要额外的虚拟化层。但是,在Windows和macOS上,由于操作系统内核不同,Docker Desktop需要通过虚拟化技术在后台运行一个轻量级的Linux虚拟机,然后在这个虚拟机中运行Docker引擎和容器。

因此,如果你使用的是Linux系统,BIOS虚拟化并非Docker运行的必要条件。但如果你使用的是Windows或macOS系统,则必须确保BIOS中的虚拟化功能已启用,否则Docker Desktop将无法正常工作。

1.3.2 硬件虚拟化的两种技术标准

目前主流的硬件虚拟化技术有两种,分别由Intel和AMD两家处理器厂商提供:

  • VT-x(Intel):Intel Virtualization Technology,是Intel处理器提供的硬件虚拟化技术。几乎所有2005年以后生产的Intel处理器都支持VT-x。VT-x引入了两种CPU运行模式:根模式和非根模式,虚拟机管理器运行在根模式下,而客户机操作系统运行在非根模式下,从而实现了高效的CPU虚拟化。

  • AMD-V(AMD):AMD Virtualization,是AMD处理器提供的硬件虚拟化技术。与Intel的VT-x类似,AMD-V也提供了硬件级别的虚拟化支持。AMD从2006年开始在其处理器中集成AMD-V技术。

除了CPU虚拟化之外,还有一些相关的虚拟化扩展技术值得关注:

  • EPT(Extended Page Tables)/ NPT(Nested Page Tables):这是Intel和AMD分别提供的内存虚拟化加速技术,可以显著减少虚拟机的内存地址转换开销。EPT和NPT是WSL 2和Docker Desktop高效运行的重要基础。

  • SR-IOV(Single Root I/O Virtualization):这是一种网卡虚拟化技术,允许一个物理网卡被多个虚拟机直接使用,减少网络虚拟化的性能开销。

1.3.3 检查虚拟化是否启用

在Windows上检查:

# 方法1:通过任务管理器
# Ctrl+Shift+Esc打开任务管理器 -> 性能 -> CPU -> 查看虚拟化状态

# 方法2:通过命令行
systeminfo | findstr /C:"虚拟化"

# 方法3:通过PowerShell
Get-ComputerInfo -Property "HyperVRequirementVirtualizationFirmwareEnabled"

在Linux上检查:

# 检查Intel VT-x
egrep -c '(vmx|svm)' /proc/cpuinfo
# 输出大于0表示支持虚拟化

# 更详细的检查
apt-get install -y cpu-checker
kvm-ok
# 输出 "KVM acceleration can be used" 表示已启用

在macOS上:

# macOS默认启用Hypervisor.framework,无需BIOS设置
# 但可以检查是否支持
sysctl kern.hv_support
# 输出 kern.hv_support: 1 表示支持
1.3.3 在BIOS中启用虚拟化

不同主板品牌的BIOS设置路径不同,以下是常见品牌的设置方法:

主板品牌 BIOS路径 选项名称
Intel主板 Advanced → CPU Configuration Intel Virtualization Technology
ASUS Advanced → CPU Configuration Intel VT-X
MSI OC → CPU Features Intel Virtualization Tech
Gigabyte M.I.T → Advanced Frequency → CPU Features Virtualization
ASRock Advanced → CPU Configuration Intel Virtualization Technology
Dell Settings → Virtualization Virtualization
HP Security → System Security Virtualization Technology (VTx)
Lenovo Security → Virtualization Intel Virtualization Technology

启用步骤:

  1. 重启电脑,在开机时按下对应按键进入BIOS(常见按键:F2、F12、Del、Esc)
  2. 找到上述路径中的虚拟化选项
  3. 将其设置为Enabled(启用)
  4. 保存设置并退出(通常按F10保存)

1.4 Linux内核版本检查

Docker对Linux内核版本有最低要求,不同版本的Docker Engine对内核版本的要求不同:

Docker版本 最低内核版本 推荐内核版本 说明
Docker 24.x 3.10 5.0+ 支持overlay2存储驱动
Docker 25.x 3.10 5.4+ 推荐使用较新内核
Docker 26.x 3.10 5.10+ 新特性需要较新内核
Docker 27.x 3.10 5.15+ 最新版推荐内核

检查内核版本和关键模块:

# 查看内核版本
uname -r

# 检查内核是否支持必要的模块
lsmod | grep overlay
lsmod | grep br_netfilter

# 如果没有加载,手动加载
sudo modprobe overlay
sudo modprobe br_netfilter

# 设置开机自动加载
cat <<EOF | sudo tee /etc/modules-load.d/docker.conf
overlay
br_netfilter
EOF

# 检查内核参数
# Docker需要以下内核参数支持
cat <<EOF | sudo tee /etc/sysctl.d/docker.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF

# 使参数生效
sudo sysctl --system

# 验证参数是否生效
sysctl net.bridge.bridge-nf-call-iptables
sysctl net.bridge.bridge-nf-call-ip6tables
sysctl net.ipv4.ip_forward

输出验证:

net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1

重要提示:net.ipv4.ip_forward = 1 是Docker容器跨网络通信的关键参数。如果该值为0,容器将无法访问外部网络,也无法被外部网络访问。

1.4.1 检查cgroup版本

Docker支持cgroup v1和cgroup v2。较新的Linux发行版默认使用cgroup v2:

# 检查cgroup版本
stat -fc %T /sys/fs/cgroup/

# cgroup v2 输出: cgroup2fs
# cgroup v1 输出: tmpfs

Docker 20.10及以上版本支持cgroup v2。如果你的系统使用cgroup v2,确保Docker版本不低于20.10。

关于cgroup的深入理解:

cgroup(Control Group,控制组)是Linux内核提供的一种机制,用于限制、记录和隔离进程组使用的物理资源(如CPU、内存、磁盘I/O、网络等)。Docker正是通过cgroup来实现对容器资源使用的限制和管理。

cgroup经历了两个主要版本的发展:

  • cgroup v1:最早的cgroup实现,每个资源控制器(如CPU、内存等)有独立的层级结构。cgroup v1的功能较为完善,但存在层级结构复杂、资源控制器之间协调困难等问题。Ubuntu 20.04及之前的版本、CentOS 7等较旧的发行版默认使用cgroup v1。

  • cgroup v2:重新设计的cgroup版本,使用统一的层级结构,所有资源控制器共享同一个cgroup树。cgroup v2简化了管理,提升了性能,并支持更丰富的资源控制能力(如PSI Pressure Stall Information)。Ubuntu 22.04、CentOS 9 Stream、Debian 12等较新的发行版默认使用cgroup v2。

Docker通过cgroup实现容器资源限制的原理如下:当你在docker run命令中指定--memory="512m"--cpus="1.0"时,Docker守护进程会在cgroup层级中为该容器创建一个cgroup节点,并将资源限制写入对应的cgroup控制文件中。Linux内核会根据这些限制来调度容器的资源使用。

在实际使用中,建议使用cgroup v2(如果系统和Docker版本支持),因为它的性能更好、功能更丰富。但需要注意,某些较老的容器监控工具可能不完全兼容cgroup v2,在升级前需要进行兼容性测试。

另外,Docker的cgroup驱动(cgroup driver)也是一个重要的配置项。Docker支持两种cgroup驱动:cgroupfssystemd。推荐使用systemd驱动,因为它与现代Linux发行版的init系统更好地集成,避免了Docker和systemd之间的cgroup管理冲突。你可以在daemon.json中通过"exec-opts": ["native.cgroupdriver=systemd"]来指定cgroup驱动。

1.4.2 检查必要的系统工具
# 检查iptables
iptables --version

# 检查curl(用于下载安装脚本)
curl --version

# 检查ca-certificates
dpkg -l ca-certificates 2>/dev/null || rpm -qa ca-certificates 2>/dev/null

1.5 旧版本Docker卸载方法

在安装新版Docker之前,如果系统中存在旧版本的Docker(如dockerdocker-enginedocker.iocontainerdrunc等),需要先卸载,否则可能导致冲突。

1.5.1 Ubuntu/Debian卸载旧版本
# 停止Docker服务
sudo systemctl stop docker
sudo systemctl stop docker.socket

# 卸载旧版本Docker包
sudo apt-get remove -y docker docker-engine docker.io containerd runc

# 卸载新版Docker(如果已安装)
sudo apt-get remove -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 清理依赖
sudo apt-get autoremove -y

# 删除Docker数据目录(谨慎操作!这会删除所有镜像、容器和数据卷)
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
sudo rm -rf /etc/docker

# 删除Docker网络配置
sudo rm -rf /run/docker
sudo rm -rf /run/containerd
1.5.2 CentOS/RHEL卸载旧版本
# 停止Docker服务
sudo systemctl stop docker
sudo systemctl stop docker.socket

# 卸载旧版本
sudo yum remove -y docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

# 卸载新版Docker
sudo yum remove -y docker-ce docker-ce-cli containerd.io \
                   docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras

# 删除数据目录
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
sudo rm -rf /etc/docker
1.5.3 Windows卸载旧版本

在Windows上,通过"设置 → 应用 → 已安装的应用"找到Docker Desktop,点击卸载即可。卸载后,建议清理残留文件:

# 清理Docker残留文件
Remove-Item -Recurse -Force "$env:LOCALAPPDATA\Docker"
Remove-Item -Recurse -Force "$env:APPDATA\Docker"
Remove-Item -Recurse -Force "$env:APPDATA\Docker Desktop"
Remove-Item -Recurse -Force "$env:USERPROFILE\.docker"

# 清理WSL中的docker数据
wsl --unregister docker-desktop
wsl --unregister docker-desktop-data
1.5.4 macOS卸载旧版本
# 方法1:通过Docker Desktop应用卸载
# 打开Docker Desktop -> 点击齿轮图标 -> 选择 "Uninstall"

# 方法2:手动卸载
sudo rm -rf /Applications/Docker.app
sudo rm -rf ~/Library/Containers/com.docker.docker
sudo rm -rf ~/Library/Application\ Support/Docker\ Desktop
sudo rm -rf ~/Library/Group\ Containers/group.com.docker
sudo rm -rf ~/.docker

1.6 网络环境与防火墙考量

Docker依赖网络进行镜像拉取、容器间通信以及外部访问。网络环境的配置直接影响Docker的正常使用。

1.6.1 网络连通性检查
# 检查与Docker Hub的连通性
curl -v https://registry-1.docker.io/v2/

# 检查DNS解析
nslookup registry-1.docker.io
dig registry-1.docker.io

# 检查到Docker Hub的网络延迟
ping -c 4 registry-1.docker.io

如果在国内,由于网络原因,直接访问Docker Hub可能很慢甚至无法连接。这种情况下需要配置镜像加速器,详见第六章。

1.6.2 防火墙配置

Docker默认使用iptables进行网络管理。如果你的系统启用了防火墙(如ufwfirewalld),需要注意以下配置:

Ubuntu的UFW防火墙:

# 查看UFW状态
sudo ufw status

# Docker与UFW存在冲突问题
# Docker会直接修改iptables规则,绕过UFW
# 解决方案:修改UFW默认配置
sudo vi /etc/default/ufw

# 将 DEFAULT_FORWARD_POLICY 修改为 ACCEPT
DEFAULT_FORWARD_POLICY="ACCEPT"

# 重启UFW
sudo ufw reload

CentOS的firewalld防火墙:

# 查看firewalld状态
sudo firewall-cmd --state

# 放行Docker需要的端口
sudo firewall-cmd --permanent --zone=trusted --add-interface=docker0
sudo firewall-cmd --permanent --zone=public --add-port=2375/tcp
sudo firewall-cmd --reload
1.6.3 代理配置

如果在企业内网或需要使用代理上网,需要为Docker配置代理:

# 为Docker守护进程配置代理
sudo mkdir -p /etc/systemd/system/docker.service.d

sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf <<EOF
[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.example.com"
EOF

# 重新加载systemd配置
sudo systemctl daemon-reload

# 重启Docker
sudo systemctl restart docker

# 验证代理配置
systemctl show --property=Environment docker

为Docker客户端配置代理(用于docker pull等命令):

# 创建或编辑 ~/.docker/config.json
mkdir -p ~/.docker
cat <<EOF > ~/.docker/config.json
{
  "proxies": {
    "default": {
      "httpProxy": "http://proxy.example.com:8080",
      "httpsProxy": "http://proxy.example.com:8080",
      "noProxy": "localhost,127.0.0.1,*.internal.example.com"
    }
  }
}
EOF
1.6.4 时间同步

Docker容器的时间默认与宿主机同步,但建议确保宿主机时间准确:

# 安装并配置chrony(推荐)
sudo apt-get install -y chrony   # Ubuntu/Debian
sudo yum install -y chrony       # CentOS/RHEL

# 编辑chrony配置
sudo vi /etc/chrony/chrony.conf
# 添加NTP服务器
# server ntp.aliyun.com iburst
# server cn.pool.ntp.org iburst

# 启动并设置开机自启
sudo systemctl enable --now chronyd

# 检查时间同步状态
chronyc tracking

第二章 Linux平台安装Docker

Linux是Docker的原生运行平台,也是生产环境中最常用的部署平台。与Windows和macOS不同,在Linux上Docker直接运行在宿主机内核之上,不需要额外的虚拟化层,因此具有最佳的性能和最低的资源开销。本章将详细讲解在Ubuntu/Debian和CentOS/RHEL上的安装方法,以及官方脚本安装、二进制安装等方式。

在Linux上安装Docker时,需要特别注意以下几点:首先,不同Linux发行版使用不同的包管理器(如apt、yum、dnf、pacman等),安装命令和仓库配置方式有所不同。其次,Docker的安装包括多个组件(Docker Engine、containerd、Docker CLI、Buildx插件、Compose插件),需要确保所有组件的版本兼容。最后,安装后的配置工作(如设置开机自启、配置用户权限、调整内核参数等)同样重要,这些配置直接影响Docker的稳定性和安全性。

2.1 Ubuntu/Debian系统安装(apt方式,完整步骤)

2.1.1 更新系统包索引

首先更新系统的包索引,确保安装的是最新版本的依赖:

# 更新apt包索引
sudo apt-get update

# 安装必要的依赖包
sudo apt-get install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
2.1.2 添加Docker官方GPG密钥
# 创建keyrings目录
sudo install -m 0755 -d /etc/apt/keyrings

# 下载并添加Docker官方GPG密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
    sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# 设置GPG密钥文件权限
sudo chmod a+r /etc/apt/keyrings/docker.gpg

说明:GPG密钥用于验证从Docker仓库下载的软件包的真实性和完整性,防止软件包被篡改。

2.1.3 添加Docker apt仓库
# 添加Docker仓库到apt源列表
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

这个命令做了以下几件事:

  • $(dpkg --print-architecture):自动检测系统架构(amd64、arm64等)
  • signed-by=/etc/apt/keyrings/docker.gpg:指定GPG密钥文件
  • $(. /etc/os-release && echo "$VERSION_CODENAME"):获取Ubuntu版本代号(如jammy、focal等)
  • stable:使用稳定版通道
2.1.4 安装Docker Engine
# 更新apt包索引(添加新仓库后必须更新)
sudo apt-get update

# 安装最新版Docker Engine及相关组件
sudo apt-get install -y \
    docker-ce \
    docker-ce-cli \
    containerd.io \
    docker-buildx-plugin \
    docker-compose-plugin

各包说明:

包名 说明
docker-ce Docker Engine(社区版),守护进程
docker-ce-cli Docker命令行工具
containerd.io 容器运行时
docker-buildx-plugin Docker Buildx增强构建插件
docker-compose-plugin Docker Compose V2插件
2.1.5 安装指定版本

如果需要安装特定版本的Docker:

# 查看可用版本列表
apt-cache madison docker-ce | awk '{ print $3 }'

# 输出示例:
# 5:27.0.3-1~ubuntu.22.04~jammy
# 5:27.0.2-1~ubuntu.22.04~jammy
# 5:26.1.4-1~ubuntu.22.04~jammy
# ...

# 安装指定版本
VERSION_STRING=5:27.0.3-1~ubuntu.22.04~jammy
sudo apt-get install -y \
    docker-ce=$VERSION_STRING \
    docker-ce-cli=$VERSION_STRING \
    containerd.io \
    docker-buildx-plugin \
    docker-compose-plugin
2.1.6 Debian系统安装差异

Debian的安装步骤与Ubuntu基本一致,主要区别在于GPG密钥URL和仓库地址:

# 添加Docker GPG密钥(Debian)
curl -fsSL https://download.docker.com/linux/debian/gpg | \
    sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# 添加Docker仓库(Debian)
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

2.2 CentOS/RHEL系统安装(yum方式,完整步骤)

2.2.1 卸载旧版本
# 卸载旧版本Docker
sudo yum remove -y docker \
    docker-client \
    docker-client-latest \
    docker-common \
    docker-latest \
    docker-latest-logrotate \
    docker-logrotate \
    docker-engine
2.2.2 安装yum-utils工具
# 安装yum-utils(提供yum-config-manager命令)
sudo yum install -y yum-utils
2.2.3 添加Docker yum仓库
# 添加Docker官方仓库
sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

国内用户可以使用阿里云镜像仓库:

sudo yum-config-manager \
    --add-repo \
    https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
2.2.4 安装Docker Engine
# 安装最新版Docker Engine
sudo yum install -y \
    docker-ce \
    docker-ce-cli \
    containerd.io \
    docker-buildx-plugin \
    docker-compose-plugin

如果yum安装时提示接受GPG密钥,确认指纹为060A 61C5 1B55 8A7F 742B 77AA C52F EB6B 621E 9F35后接受即可。

2.2.5 安装指定版本
# 列出可用版本
yum list docker-ce --showduplicates | sort -r

# 输出示例:
# docker-ce.x86_64    3:27.0.3-1.el9    docker-ce-stable
# docker-ce.x86_64    3:27.0.2-1.el9    docker-ce-stable
# ...

# 安装指定版本(注意版本号格式)
sudo yum install -y docker-ce-27.0.3-1.el9 \
    docker-ce-cli-27.0.3-1.el9 \
    containerd.io \
    docker-buildx-plugin \
    docker-compose-plugin
2.2.6 RHEL 9的特殊说明

在RHEL 9上,可能需要额外安装iptables

# RHEL 9可能默认使用nftables,Docker需要iptables
sudo yum install -y iptables iptables-services

# 启动并设置iptables开机自启
sudo systemctl enable --now iptables
2.2.7 启动Docker服务
# 启动Docker服务
sudo systemctl start docker

# 设置Docker开机自启
sudo systemctl enable docker

# 启动containerd服务
sudo systemctl enable --now containerd

# 验证Docker服务状态
sudo systemctl status docker

输出示例:

● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; preset: enabled)
     Active: active (running) since Wed 2024-06-15 10:00:00 CST; 1min ago
       Docs: https://docs.docker.com
   Main PID: 12345 (dockerd)
      Tasks: 10
     Memory: 120.5M
        CPU: 1.234s
     CGroup: /system.slice/docker.service
             └─12345 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
2.2.8 运行测试容器
# 运行hello-world容器验证安装
sudo docker run hello-world

如果看到以下输出,说明Docker安装成功:

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
c1ec31eb4...

Hello from Docker!
This message shows that your installation appears to be working correctly.
...

2.3 使用官方安装脚本一键安装

Docker官方提供了一键安装脚本,适合快速搭建测试环境。但不推荐在生产环境中使用,因为脚本无法精细控制安装的版本和配置。

2.3.1 使用官方脚本安装
# 下载并执行官方安装脚本
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

脚本执行过程中会自动:

  1. 检测操作系统类型和版本
  2. 安装必要的依赖包
  3. 添加Docker官方仓库
  4. 安装最新版Docker Engine
  5. 启动Docker服务并设置开机自启
2.3.2 使用阿里云镜像脚本(国内推荐)
# 使用阿里云镜像加速安装脚本
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh --mirror Aliyun

# 也可以使用Azure中国镜像
sudo sh get-docker.sh --mirror AzureChinaCloud
2.3.3 测试脚本安装的Docker
# 启动Docker服务(如果脚本未自动启动)
sudo systemctl start docker
sudo systemctl enable docker

# 验证安装
sudo docker version
sudo docker run hello-world

注意:脚本安装方式默认以root权限运行Docker。安装完成后,建议按照2.7节的方法将普通用户加入docker组。

2.4 二进制包手动安装

在某些特殊场景下(如无法使用包管理器、离线环境、需要特定版本),可以通过二进制包手动安装Docker。

2.4.1 下载二进制包
# 定义Docker版本
DOCKER_VERSION=27.0.3

# 下载Docker二进制包(x86_64架构)
curl -fsSL https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_VERSION}.tgz \
    -o /tmp/docker-${DOCKER_VERSION}.tgz

# 对于arm64架构
# curl -fsSL https://download.docker.com/linux/static/stable/aarch64/docker-${DOCKER_VERSION}.tgz \
#     -o /tmp/docker-${DOCKER_VERSION}.tgz
2.4.2 解压并安装
# 解压二进制包
tar -xzf /tmp/docker-${DOCKER_VERSION}.tgz -C /tmp

# 复制二进制文件到系统路径
sudo cp /tmp/docker/* /usr/bin/

# 验证文件是否复制成功
ls -la /usr/bin/docker*
2.4.3 创建Docker服务配置
# 创建Docker配置文件目录
sudo mkdir -p /etc/docker

# 创建基础配置文件
sudo tee /etc/docker/daemon.json <<EOF
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "storage-driver": "overlay2"
}
EOF
2.4.4 创建systemd服务文件
# 创建Docker的systemd服务文件
sudo tee /etc/systemd/system/docker.service <<EOF
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target docker.socket firewalld.service containerd.service
Wants=network-online.target containerd.service
Requires=docker.socket

[Service]
Type=notify
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecReload=/bin/kill -s HUP \$MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
StartLimitBurst=3
StartLimitInterval=60s
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
Delegate=yes
KillMode=process

[Install]
WantedBy=multi-user.target
EOF

# 创建Docker socket服务文件
sudo tee /etc/systemd/system/docker.socket <<EOF
[Unit]
Description=Docker Socket for the API

[Socket]
ListenStream=/var/run/docker.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker

[Install]
WantedBy=sockets.target
EOF
2.4.5 启动Docker服务
# 重新加载systemd
sudo systemctl daemon-reload

# 启动Docker服务
sudo systemctl start docker

# 设置开机自启
sudo systemctl enable docker

# 验证安装
sudo docker version
sudo docker info
2.4.6 安装containerd(二进制方式)
# 下载containerd
CONTAINERD_VERSION=1.7.18
curl -fsSL https://github.com/containerd/containerd/releases/download/v${CONTAINERD_VERSION}/containerd-${CONTAINERD_VERSION}-linux-amd64.tar.gz \
    -o /tmp/containerd.tar.gz

# 解压并安装
sudo tar -C /usr -xzf /tmp/containerd.tar.gz

# 创建containerd配置
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

# 创建containerd的systemd服务
sudo tee /etc/systemd/system/containerd.service <<EOF
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target

[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/bin/containerd
Restart=always
RestartSec=5
Delegate=yes
KillMode=process
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity

[Install]
WantedBy=multi-user.target
EOF

# 启动containerd
sudo systemctl daemon-reload
sudo systemctl enable --now containerd

2.5 验证安装结果(docker version、docker info详解)

安装完成后,需要验证Docker是否正确安装并正常运行。

2.5.1 docker version
docker version

输出详解:

Client: Docker Engine - Community
 Version:           27.0.3
 API version:       1.47
 Go version:        go1.21.11
 Git commit:        6615ae7
 Built:             Wed Jun 12 10:00:00 2024
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          27.0.3
  API version:      1.47 (minimum version 1.24)
  Go version:       go1.21.11
  Git commit:       6615ae7
  Built:            Wed Jun 12 10:00:00 2024
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.7.18
  GitCommit:        ae71819c4d20c4c75c跨境电商8a8a8a8a8a8
 runc:
  Version:          1.7.0
  GitCommit:        v1.1.0-0-g81977c0
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

字段说明:

  • Client:Docker客户端信息,即你通过命令行使用的docker命令
  • Server:Docker服务端(守护进程)信息
  • Version:版本号
  • API version:Docker API版本,客户端和服务端的API版本需要兼容
  • Go version:Docker是使用Go语言编写的,这里显示Go编译器版本
  • Git commit:代码提交哈希值,用于精确定位版本
  • OS/Arch:操作系统和CPU架构
  • Context:当前Docker上下文(context),用于管理多个Docker环境
  • containerd:容器运行时版本
  • runc:OCI容器运行时版本
  • docker-init:容器init进程版本

如果只看到Client信息而看不到Server信息,说明Docker守护进程没有正常运行。

2.5.2 docker info
docker info

输出详解:

Client: Docker Engine - Community
 Version:    27.0.3
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.14.0
    Path:     /usr/libexec/docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v2.27.0
    Path:     /usr/libexec/docker/cli-plugins/docker-compose

Server:
 Containers: 5
  Running: 2
  Paused: 0
  Stopped: 3
 Images: 15
 Server Version: 27.0.3
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Using metacopy: false
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: systemd
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: ae71819c4d20c75c...
 runc version: v1.1.0-0-g81977c0
 Security Options:
  apparmor
  seccomp
  Profile: builtin
 Kernel Version: 5.15.0-91-generic
 Operating System: Ubuntu 22.04.4 LTS
 OSType: linux
 Architecture: x86_64
 CPUs: 8
 Total Memory: 15.63GiB
 Name: docker-host
 ID: ABCD:1234:EFGH:5678:IJKL:9012:MNOP:3456
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false

关键字段解析:

字段 说明
Containers 容器总数及各状态数量
Images 本地镜像数量
Storage Driver 存储驱动,推荐overlay2
Logging Driver 日志驱动,默认json-file
Cgroup Driver cgroup驱动,推荐systemd
Cgroup Version cgroup版本
Plugins 已安装的插件(Volume、Network、Log)
Swarm Swarm集群状态
Runtimes 可用的容器运行时
Default Runtime 默认运行时
Security Options 安全选项(apparmor、seccomp)
Docker Root Dir Docker数据目录
Insecure Registries 不安全的镜像仓库列表
2.5.3 运行测试容器
# 运行hello-world容器
docker run hello-world

# 运行Ubuntu容器并执行命令
docker run -it ubuntu bash

# 在容器内执行命令
root@container_id:/# cat /etc/os-release
root@container_id:/# exit

# 运行Nginx容器测试Web服务
docker run -d -p 8080:80 --name my-nginx nginx

# 访问测试
curl http://localhost:8080

2.6 配置Docker开机自启

在生产环境中,确保Docker服务在系统重启后自动启动非常重要。

# 设置Docker开机自启
sudo systemctl enable docker

# 设置containerd开机自启
sudo systemctl enable containerd

# 验证开机自启状态
systemctl is-enabled docker
systemctl is-enabled containerd

# 禁用开机自启(如果需要)
# sudo systemctl disable docker

同时,建议配置Docker的"Live Restore"功能,这样在升级Docker或重启Docker守护进程时,容器不会停止:

# 编辑daemon.json
sudo tee /etc/docker/daemon.json <<EOF
{
  "live-restore": true
}
EOF

# 重新加载配置(不需要重启Docker)
sudo systemctl reload docker

Live Restore的作用:当Docker守护进程重启或升级时,正在运行的容器不会被停止,而是继续运行。这对于生产环境的零停机维护非常重要。

2.7 将用户加入docker组(免sudo)

默认情况下,Docker守护进程以root权限运行,Docker的Unix socket(/var/run/docker.sock)属于root用户和docker组。普通用户需要使用sudo才能运行docker命令。将用户加入docker组后,可以免sudo使用Docker。

# 创建docker组(如果不存在)
sudo groupadd docker

# 将当前用户加入docker组
sudo usermod -aG docker $USER

# 也可以指定用户名
sudo usermod -aG docker username

# 使组变更立即生效(无需重新登录)
newgrp docker

# 或者注销后重新登录
# 验证是否生效
docker run hello-world

安全警告:将用户加入docker组等同于赋予了该用户root权限。因为docker组的成员可以通过挂载宿主机文件系统来获取root权限。在生产环境中,请谨慎操作。

验证用户组:

# 查看当前用户所属的组
groups

# 或查看docker组成员
getent group docker
2.7.1 配置Docker socket权限

如果不想将用户加入docker组,也可以直接修改Docker socket的权限(不推荐,安全性较低):

# 查看Docker socket权限
ls -la /var/run/docker.sock

# 修改权限(允许所有用户访问)
sudo chmod 666 /var/run/docker.sock

# 或者修改所有者
sudo chown $USER:$USER /var/run/docker.sock

注意:上述方法在Docker重启后会失效。推荐使用将用户加入docker组的方式。

2.8 各发行版安装差异对比表

特性 Ubuntu/Debian CentOS/RHEL Fedora Arch Linux
包管理器 apt yum/dnf dnf pacman
安装命令 apt-get install docker-ce yum install docker-ce dnf install docker-ce pacman -S docker
仓库添加 sources.list.d yum-config-manager dnf config-manager 官方仓库已包含
GPG密钥 apt keyrings rpm导入 rpm导入 不需要
服务管理 systemd systemd systemd systemd
防火墙 ufw firewalld firewalld iptables/nftables
默认存储驱动 overlay2 overlay2 overlay2 overlay2
cgroup驱动 systemd systemd systemd systemd

Fedora安装示例:

# 添加Docker仓库
sudo dnf config-manager \
    --add-repo \
    https://download.docker.com/linux/fedora/docker-ce.repo

# 安装Docker
sudo dnf install -y docker-ce docker-ce-cli containerd.io \
    docker-buildx-plugin docker-compose-plugin

# 启动并设置开机自启
sudo systemctl enable --now docker

Arch Linux安装示例:

# Arch Linux官方仓库已包含Docker
sudo pacman -S docker docker-compose

# 启动并设置开机自启
sudo systemctl enable --now docker

# 将用户加入docker组
sudo usermod -aG docker $USER

第三章 Windows平台安装Docker

Windows平台通过Docker Desktop提供完整的Docker开发体验。Docker Desktop for Windows利用WSL 2(Windows Subsystem for Linux 2)或Hyper-V作为后端虚拟化技术,在Windows上运行Linux容器。本章将详细讲解Windows平台上Docker的安装与配置。

在Windows上运行Docker与在Linux上有本质区别。由于Docker容器依赖于Linux内核特性(如命名空间、cgroup等),而Windows使用的是完全不同的内核架构,因此在Windows上无法直接运行Linux容器。Docker Desktop通过在后台运行一个轻量级的Linux虚拟环境(通过WSL 2或Hyper-V实现)来解决这个问题。当你执行docker命令时,命令实际上被转发到这个Linux虚拟环境中执行,容器也运行在这个虚拟环境中。

这种架构带来了一些值得注意的特点:首先,容器的文件系统性能在跨文件系统访问时(如从Windows文件系统访问容器内的文件)会有所下降,建议在WSL的Linux文件系统中进行开发操作。其次,网络通信需要经过虚拟网络转发,虽然Docker Desktop做了大量优化使得localhost可以自动转发,但在某些复杂网络场景下仍可能遇到问题。最后,资源管理通过虚拟机实现,需要在Docker Desktop设置或WSL配置文件中合理分配CPU和内存资源。

3.1 Windows版本要求(Win10/Win11)

3.1.1 版本要求详解

Docker Desktop for Windows对Windows版本有严格的要求:

Windows版本 最低Build版本 是否支持 后端选项
Windows 10 Home Build 19041+ 支持(仅WSL 2) WSL 2
Windows 10 Pro Build 19041+ 支持 WSL 2 / Hyper-V
Windows 10 Enterprise Build 19041+ 支持 WSL 2 / Hyper-V
Windows 10 Education Build 19041+ 支持 WSL 2 / Hyper-V
Windows 11 Home 所有版本 支持(仅WSL 2) WSL 2
Windows 11 Pro 所有版本 支持 WSL 2 / Hyper-V
Windows 11 Enterprise 所有版本 支持 WSL 2 / Hyper-V
Windows Server 2019 1809+ 支持(仅Hyper-V) Hyper-V
Windows Server 2022 21H2+ 支持 Hyper-V

注意:Windows 10 Home版不支持Hyper-V,但通过WSL 2后端仍然可以使用Docker Desktop。这是Docker Desktop 3.0版本后的重大改进。

3.1.2 检查Windows版本
# 检查Windows版本
winver

# 通过命令行检查
[System.Environment]::OSVersion.Version
# 输出: Major  Minor  Build  Revision
#       10     0      22631  0

# 检查Windows版本详细信息
Get-ComputerInfo | Select-Object WindowsVersion, WindowsBuild, OsName, OsArchitecture

# 检查是否为Home版
(Get-WmiObject -Class Win32_OperatingSystem).Caption
3.1.3 检查WSL 2支持
# 检查WSL状态
wsl --status

# 检查WSL版本
wsl --version

# 检查已安装的WSL发行版
wsl --list --verbose

如果WSL未安装,可以通过以下命令安装:

# 安装WSL 2(Windows 10 2004+ 或 Windows 11)
wsl --install

# 如果只需要WSL核心功能
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

安装完成后需要重启计算机。

3.2 启用WSL 2后端

WSL 2(Windows Subsystem for Linux 2)是微软提供的第二代Linux子系统,它使用完整的Linux内核,相比WSL 1具有更好的兼容性和性能。

3.2.1 启用WSL 2功能
# 方法1:使用PowerShell(管理员权限)
# 启用适用于Linux的Windows子系统
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

# 启用虚拟机平台
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

# 方法2:使用图形界面
# 控制面板 -> 程序 -> 启用或关闭Windows功能
# 勾选 "适用于Linux的Windows子系统"
# 勾选 "虚拟机平台"

重启计算机后,设置WSL 2为默认版本:

# 设置WSL 2为默认版本
wsl --set-default-version 2

# 验证WSL 2是否设置成功
wsl --status
# 期望输出: Default Version: 2
3.2.2 安装WSL 2 Linux内核更新包

如果系统提示需要更新WSL 2内核,手动下载安装:

# 下载WSL2 Linux内核更新包
# 手动下载地址: https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

# 或使用PowerShell下载
Invoke-WebRequest -Uri "https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi" -OutFile "$env:TEMP\wsl_update_x64.msi"

# 安装更新包
Start-Process msiexec.exe -ArgumentList "/i $env:TEMP\wsl_update_x64.msi /quiet" -Wait
3.2.3 安装Linux发行版
# 查看可用的Linux发行版
wsl --list --online

# 安装Ubuntu(推荐)
wsl --install -d Ubuntu-22.04

# 安装完成后设置用户名和密码
# 首次启动时会提示创建用户

# 验证WSL 2是否正常运行
wsl --list --verbose
# 期望输出:
#   NAME            STATE           VERSION
# * Ubuntu-22.04    Running         2
3.2.4 配置WSL 2资源限制

默认情况下,WSL 2会自动使用系统资源。你也可以手动配置资源限制:

# 创建或编辑WSL配置文件
# 文件路径: C:\Users\<你的用户名>\.wslconfig

# 内容示例:
@"
[wsl2]
memory=8GB
processors=4
swap=2GB
localhostForwarding=true
"@ | Out-File -FilePath "$env:USERPROFILE\.wslconfig" -Encoding UTF8

# 重启WSL使配置生效
wsl --shutdown

.wslconfig 配置项说明:

配置项 说明 示例
memory 分配给WSL 2的最大内存 8GB
processors 分配给WSL 2的CPU核心数 4
swap 交换空间大小 2GB
localhostForwarding 是否将localhost转发到WSL true
kernelCommandLine 内核启动参数 vsyscall=emulate
networkingMode 网络模式 NAT / mirrored

3.3 Docker Desktop for Windows安装详解

3.3.1 下载Docker Desktop
# 方法1:从官网下载
# 访问 https://www.docker.com/products/docker-desktop/
# 下载 "Docker Desktop for Windows - x86_64"

# 方法2:使用PowerShell下载(Intel/AMD芯片)
Invoke-WebRequest -Uri "https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe" `
    -OutFile "$env:TEMP\DockerDesktopInstaller.exe"

# 方法3:使用winget安装
winget install Docker.DockerDesktop
3.3.2 安装Docker Desktop
# 静默安装(使用默认配置)
Start-Process "$env:TEMP\DockerDesktopInstaller.exe" -Wait -ArgumentList "install", "--quiet"

# 指定WSL 2后端安装
Start-Process "$env:TEMP\DockerDesktopInstaller.exe" -Wait -ArgumentList "install", "--quiet", "--backend=wsl-2"

# 指定安装路径
Start-Process "$env:TEMP\DockerDesktopInstaller.exe" -Wait -ArgumentList "install", "--quiet", "--installation-dir=D:\Docker"
3.3.3 图形界面安装步骤
  1. 双击下载的Docker Desktop Installer.exe文件
  2. 在安装向导中,确认勾选"Use WSL 2 instead of Hyper-V (recommended)"
  3. 点击"OK"开始安装
  4. 安装完成后,重启计算机
  5. 启动Docker Desktop
  6. 阅读并接受Docker Subscription Service Agreement
  7. 等待Docker Engine启动(状态栏显示绿色"Engine running")
3.3.4 验证安装
# 验证Docker版本
docker version

# 验证Docker信息
docker info

# 运行测试容器
docker run hello-world

# 运行Ubuntu容器
docker run -it ubuntu bash

# 测试Docker Compose
docker compose version
3.3.5 配置Docker Desktop

安装完成后,右键点击系统托盘中的Docker图标,选择"Settings"打开设置面板:

General设置:

选项 说明 推荐设置
Start Docker Desktop when you log in 登录时自动启动 根据需求
Open Docker Dashboard at startup 启动时打开面板 关闭
Use WSL 2 based engine 使用WSL 2引擎 开启
Send usage statistics 发送使用统计 关闭
Show weekly tips 显示每周提示 关闭
Open Docker Dashboard at startup 启动时打开面板 关闭

3.4 Hyper-V后端 vs WSL 2后端对比

Docker Desktop for Windows支持两种后端模式,各有优缺点:

特性 WSL 2后端 Hyper-V后端
支持的Windows版本 Win10 19041+(含Home) Win10 Pro/Enterprise 19041+
Linux内核 完整Linux内核(微软维护) Docker提供的Linux内核
启动速度 较慢
内存使用 动态分配,按需使用 固定分配
文件系统性能 跨文件系统访问较慢 跨文件系统访问较慢
网络 localhost自动转发 需要端口转发
GPU支持 支持(需配置) 支持
Docker Compose 支持 支持
Kubernetes 支持 支持
系统集成 与WSL发行版共享文件 独立虚拟机
3.4.1 切换后端模式
# 在Docker Desktop设置中切换
# 右键Docker图标 -> Settings -> General
# 勾选/取消勾选 "Use WSL 2 based engine"
# 点击 "Apply & Restart"

# 如果需要使用Hyper-V后端,需要先启用Hyper-V功能
# 以管理员身份运行PowerShell:
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All

# 重启计算机后生效
3.4.2 WSL 2后端的优势

WSL 2后端的主要优势包括:

  1. 启动速度快:WSL 2使用轻量级虚拟机,启动速度远快于Hyper-V虚拟机
  2. 内存效率高:WSL 2可以动态回收不使用的内存,不会像Hyper-V那样固定占用
  3. 文件系统性能好:在Linux文件系统内的操作性能接近原生Linux
  4. 与WSL发行版集成:可以直接在WSL的Ubuntu等发行版中使用Docker命令
  5. Home版支持:Windows 10/11 Home版用户也能使用Docker Desktop
3.4.3 WSL 2后端的注意事项
# 在WSL发行版中使用Docker
# Docker Desktop会自动在所有WSL 2发行版中安装Docker CLI

# 检查WSL发行版是否启用了Docker集成
# Docker Desktop -> Settings -> Resources -> WSL Integration
# 勾选需要启用Docker集成的WSL发行版

# 在WSL中验证Docker
docker version
docker info

注意:在WSL 2模式下,Docker数据存储在WSL的虚拟磁盘文件(.vhdx)中。默认路径为:C:\Users\<用户名>\AppData\Local\Docker\wsl\。如果需要迁移数据目录,请参考第3.6节的说明。

3.5 Docker Desktop设置面板详解

Docker Desktop的设置面板提供了丰富的配置选项,下面逐一详解。

3.5.1 General(常规设置)
// 配置说明(对应Docker Desktop GUI设置)
{
  "autoStart": false,              // 登录时自动启动
  "openDashboardOnStart": false,   // 启动时打开面板
  "useWsl2Engine": true,           // 使用WSL 2引擎
  "sendStatistics": false,         // 发送使用统计
  "showTips": false,               // 显示提示
  "autoUpdate": true,              // 自动更新
  "excludeFromUpdate": false       // 排除更新
}
3.5.2 Resources(资源设置)

Resources -> Advanced:

CPU:     4 cores     # 分配给Docker的CPU核心数
Memory:  8 GB        # 分配给Docker的内存
Swap:    1 GB        # 交换空间大小
Disk image location: D:\DockerData  # 磁盘镜像位置

注意:在WSL 2模式下,CPU和内存设置可能被.wslconfig覆盖。如果使用WSL 2后端,建议在.wslconfig中统一配置资源限制。

Resources -> WSL Integration:

Enable integration with additional WSL distros:
[x] Ubuntu-22.04
[ ] Debian
[ ] kali-linux

勾选后,对应的WSL发行版中就可以直接使用docker命令。

Resources -> Proxies:

Manual proxy configuration:
HTTP proxy:  http://proxy.example.com:8080
HTTPS proxy: http://proxy.example.com:8080
No proxy:    localhost,127.0.0.1,*.internal.example.com
3.5.3 Docker Engine(Docker引擎配置)

这个面板对应daemon.json配置文件:

{
  "registry-mirrors": [
    "https://registry.docker-cn.com"
  ],
  "insecure-registries": [],
  "debug": false,
  "experimental": false,
  "builder": {
    "gc": {
      "enabled": true,
      "defaultKeepStorage": "20GB"
    }
  }
}

修改后点击"Apply & Restart"使配置生效。

3.5.4 Builders(构建器设置)
BuildKit:    Enabled     # 启用BuildKit(推荐)

BuildKit是Docker的新一代构建引擎,相比传统构建引擎有以下优势:

  • 并行构建,速度更快
  • 支持更灵活的Dockerfile语法
  • 更好的缓存管理
  • 支持多平台镜像构建
3.5.5 Kubernetes设置
Enable Kubernetes: [ ]   # 启用单节点Kubernetes集群
Reset Kubernetes Cluster  # 重置Kubernetes集群

Docker Desktop内置了单节点Kubernetes集群,适合本地开发和测试。

3.6 资源分配与性能调优

3.6.1 迁移Docker数据目录

WSL 2模式下,Docker数据默认存储在C盘,长时间使用后可能占用大量空间。建议迁移到其他磁盘:

# 1. 关闭Docker Desktop
# 右键Docker图标 -> Quit Docker Desktop

# 2. 关闭WSL
wsl --shutdown

# 3. 导出docker-desktop-data(Docker数据存储)
wsl --export docker-desktop-data "D:\DockerBackup\docker-desktop-data.tar"

# 4. 注销原来的docker-desktop-data
wsl --unregister docker-desktop-data

# 5. 重新导入到新位置
wsl --import docker-desktop-data "D:\DockerData\docker-desktop-data" "D:\DockerBackup\docker-desktop-data.tar"

# 6. 启动Docker Desktop
# 验证数据是否正常
docker images
docker ps -a
3.6.2 清理WSL虚拟磁盘空间

WSL 2的虚拟磁盘文件(.vhdx)只会增长不会自动缩小,需要手动压缩:

# 1. 关闭Docker Desktop和WSL
wsl --shutdown

# 2. 使用diskpart压缩虚拟磁盘
diskpart

# 在diskpart中执行:
# select vdisk file="C:\Users\<用户名>\AppData\Local\Docker\wsl\data\ext4.vhdx"
# attach vdisk readonly
# compact vdisk
# detach vdisk
# exit

# 3. 或使用PowerShell命令压缩
Optimize-VHD -Path "C:\Users\<用户名>\AppData\Local\Docker\wsl\data\ext4.vhdx" -Mode Full
3.6.3 性能调优建议
// Docker Desktop daemon.json 性能优化配置
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "storage-driver": "overlay2",
  "builder": {
    "gc": {
      "enabled": true,
      "defaultKeepStorage": "10GB"
    }
  },
  "features": {
    "buildkit": true
  }
}

性能调优清单:

  1. 启用BuildKit加速镜像构建
  2. 配置日志大小限制,防止日志占用过多磁盘
  3. 启用构建缓存垃圾回收
  4. 使用overlay2存储驱动(默认已启用)
  5. 定期运行docker system prune清理无用资源
  6. 在Linux文件系统内(WSL)进行构建操作,避免跨文件系统性能损耗

3.7 文件共享配置

Docker Desktop需要在宿主机和容器之间共享文件,以下是文件共享的配置方法。

3.7.1 WSL 2模式下的文件访问

在WSL 2模式下,文件访问有以下几种方式:

# 方式1:在WSL文件系统中操作(性能最佳)
# 在WSL中创建项目目录
mkdir -p ~/projects/myapp
cd ~/projects/myapp
# 在此目录中创建Dockerfile和项目文件

# 方式2:从WSL访问Windows文件(性能较差)
# Windows的C盘在WSL中映射为 /mnt/c/
cd /mnt/c/Users/用户名/projects/myapp

# 方式3:使用Docker Volume
docker volume create mydata
docker run -v mydata:/data alpine echo "hello"

性能对比:

文件位置 读写性能 适用场景
WSL文件系统(~/) 最佳 开发、构建
Windows文件系统(/mnt/c/) 较差 需要与Windows应用共享
Docker Volume 数据持久化
3.7.2 使用Bind Mount挂载Windows目录
# 挂载Windows目录到容器(WSL 2模式)
# 注意路径格式:使用/mnt/c/...格式

docker run -d \
    -v /mnt/c/Users/用户名/projects/myapp:/app \
    -p 3000:3000 \
    --name my-node-app \
    node:18

# 在Docker Compose中使用
cat <<'EOF' > docker-compose.yml
version: '3.8'
services:
  web:
    image: nginx
    volumes:
      - /mnt/c/Users/用户名/html:/usr/share/nginx/html
    ports:
      - "8080:80"
EOF
3.7.3 文件共享常见问题
# 问题1:文件权限问题
# 在WSL中创建的文件,Windows可能无法正常访问
# 解决方案:配置WSL的metadata选项

# 编辑 /etc/wsl.conf(在WSL中执行)
sudo tee /etc/wsl.conf <<EOF
[automount]
options = "metadata,umask=22,fmask=11"
[interop]
enabled = true
appendWindowsPath = true
EOF

# 重启WSL
wsl --shutdown
wsl

3.8 常见安装问题排查

3.8.1 WSL 2安装失败
# 错误:WslRegisterDistribution failed with error: 0x800701bc
# 原因:WSL 2内核未更新

# 解决方案:
# 1. 下载并安装WSL2 Linux内核更新包
Invoke-WebRequest -Uri "https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi" -OutFile "$env:TEMP\wsl_update_x64.msi"
Start-Process msiexec.exe -ArgumentList "/i $env:TEMP\wsl_update_x64.msi /quiet" -Wait

# 2. 设置WSL 2为默认
wsl --set-default-version 2

# 3. 重启计算机
3.8.2 Docker Desktop无法启动
# 错误:Docker Desktop fails to start

# 解决方案1:重启Docker服务
# 以管理员身份运行PowerShell
Restart-Service com.docker.service
Restart-Service docker

# 解决方案2:重置Docker Desktop
# 右键Docker图标 -> Troubleshoot -> Reset to factory defaults

# 解决方案3:清理WSL
wsl --shutdown
wsl --unregister docker-desktop
wsl --unregister docker-desktop-data
# 然后重新启动Docker Desktop
3.8.3 端口冲突
# 错误:Bind for 0.0.0.0:8080 failed: port is already allocated

# 查看占用端口的进程
netstat -ano | findstr :8080

# 终止占用端口的进程
taskkill /PID <进程ID> /F

# 或在Docker Desktop设置中配置不同的端口
3.8.4 磁盘空间不足
# 查看Docker磁盘使用情况
docker system df

# 清理无用资源
docker system prune -a --volumes

# 压缩WSL虚拟磁盘(参考3.6.2节)
3.8.5 网络连接问题
# 错误:docker: Error response from daemon: Get "https://registry-1.docker.io/v2/": dial tcp

# 解决方案1:配置DNS
# Docker Desktop -> Settings -> Docker Engine
# 添加DNS配置
{
  "dns": ["8.8.8.8", "114.114.114.114"]
}

# 解决方案2:配置镜像加速器(参考第六章)
{
  "registry-mirrors": ["https://registry.docker-cn.com"]
}

# 解决方案3:检查代理设置
# Docker Desktop -> Settings -> Resources -> Proxies

第四章 macOS平台安装Docker

macOS平台同样使用Docker Desktop进行安装。由于macOS使用Apple自研的Hypervisor.framework,Docker Desktop for Mac不需要像Windows那样配置WSL 2或Hyper-V,安装相对简单。本章将讲解Intel芯片和Apple Silicon芯片Mac上的安装方法。

4.1 系统版本要求

4.1.1 版本要求
芯片类型 最低macOS版本 推荐macOS版本
Intel(x86_64) macOS 11 Big Sur macOS 13 Ventura+
Apple Silicon(arm64) macOS 12 Monterey macOS 14 Sonoma+
4.1.2 检查系统信息
# 查看macOS版本
sw_vers
# 输出:
# ProductName:    macOS
# ProductVersion: 14.4
# BuildVersion:   23E214

# 查看CPU架构
uname -m
# 输出:
# arm64    -> Apple Silicon (M1/M2/M3/M4)
# x86_64   -> Intel

# 查看CPU详细信息
sysctl -n machdep.cpu.brand_string
# Intel输出: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
# Apple Silicon输出: Apple M2 Pro

# 查看内存
sysctl -n hw.memsize
# 输出字节数,除以(1024^3)得到GB

# 查看磁盘空间
df -h /

4.2 Docker Desktop for Mac安装(Intel/Apple Silicon)

4.2.1 下载Docker Desktop
# 方法1:从官网下载
# 访问 https://www.docker.com/products/docker-desktop/
# 选择对应芯片版本的DMG文件下载

# 方法2:使用Homebrew下载(推荐)
# 安装Homebrew(如果尚未安装)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# 下载Docker Desktop
brew install --cask docker
4.2.2 安装步骤(图形界面)
  1. 双击下载的Docker.dmg文件
  2. 将Docker图标拖拽到Applications文件夹
  3. 打开Applications文件夹,双击Docker启动
  4. 输入管理员密码授权安装Docker工具
  5. 阅读并接受Docker Subscription Service Agreement
  6. 等待Docker Engine启动(菜单栏Docker图标变为稳定状态)
4.2.3 Apple Silicon特殊说明

在Apple Silicon Mac上,Docker Desktop通过QEMU模拟运行x86_64架构的容器,同时也原生支持arm64架构的容器:

# 在Apple Silicon上检查Docker支持的平台
docker buildx ls

# 查看当前默认平台
docker info | grep -i platform

# 运行arm64原生镜像(默认)
docker run --platform linux/arm64 -it alpine uname -m
# 输出: aarch64

# 运行amd64镜像(通过Rosetta 2或QEMU模拟)
docker run --platform linux/amd64 -it alpine uname -m
# 输出: x86_64
4.2.4 启用Rosetta 2加速(Apple Silicon)
# 安装Rosetta 2(如果尚未安装)
softwareupdate --install-rosetta

# 在Docker Desktop中启用Rosetta 2加速
# Settings -> Features in development -> Use Rosetta for x86/amd64 emulation on Apple Silicon
# 勾选并Apply & Restart

Rosetta 2可以显著提升x86_64容器在Apple Silicon上的运行性能,相比QEMU模拟有2-3倍的性能提升。

4.2.5 验证安装
# 验证Docker版本
docker version

# 验证Docker信息
docker info

# 运行测试容器
docker run hello-world

# 运行Ubuntu容器
docker run -it ubuntu bash

# 检查Docker Compose
docker compose version

4.3 Homebrew安装方式

Homebrew是macOS上最流行的包管理器,使用Homebrew安装Docker非常方便。

4.3.1 使用Homebrew安装Docker Desktop
# 安装Docker Desktop(GUI版本)
brew install --cask docker

# 安装Docker CLI(命令行版本,不含GUI)
brew install docker docker-compose

# 安装Docker Buildx
brew install docker-buildx

# 安装containerd
brew install containerd
4.3.2 使用Homebrew安装Colima(轻量级替代方案)

Colima是一个轻量级的macOS容器运行时,不需要Docker Desktop的GUI界面:

# 安装Colima
brew install colima

# 启动Colima(默认配置)
colima start

# 指定CPU和内存启动
colima start --cpu 4 --memory 8 --disk 50

# 指定架构启动(在Apple Silicon上运行x86_64容器)
colima start --arch x86_64

# 查看Colima状态
colima status

# 停止Colima
colima stop

# 重启Colima
colima restart

# 删除Colima
colima delete

Colima与Docker Desktop对比:

特性 Docker Desktop Colima
界面 GUI + CLI 仅CLI
资源占用 较高 较低
Docker Compose 内置 需单独安装
Kubernetes 内置 需单独安装
文件共享 自动配置 需手动配置
商业许可 大企业需付费 免费
适合场景 开发/学习 CI/CD/服务器
4.3.3 使用Homebrew安装其他Docker工具
# 安装Lazydocker(终端UI工具)
brew install lazydocker

# 安装Dive(镜像分析工具)
brew install dive

# 安装Trivy(安全扫描工具)
brew install trivy

# 安装Skopeo(镜像复制工具)
brew install skopeo

# 安装Hadolint(Dockerfile语法检查)
brew install hadolint

4.4 资源配置与磁盘管理

4.4.1 配置Docker Desktop资源

在Docker Desktop的设置面板中配置资源:

Settings -> Resources:
  CPUs:        4        # CPU核心数
  Memory:      8 GB     # 内存大小
  Swap:        1 GB     # 交换空间
  Disk image size: 64 GB  # 磁盘镜像大小
  Disk image location: /Users/用户名/Library/Containers/com.docker.docker/Data  # 磁盘镜像位置

也可以通过CLI配置:

# 使用Colima配置资源
colima start --cpu 4 --memory 8 --disk 50

# 查看当前资源使用
docker stats --no-stream
4.4.2 迁移Docker数据目录

macOS上Docker数据默认存储在用户目录下,如果需要迁移到外部磁盘:

# 1. 停止Docker Desktop
# 菜单栏Docker图标 -> Quit Docker Desktop

# 2. 迁移数据目录
# 默认位置: ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw
# 迁移到外部磁盘:
mkdir -p /Volumes/ExternalDisk/DockerData
cp ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw \
   /Volumes/ExternalDisk/DockerData/

# 3. 创建符号链接
mv ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw \
   ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw.bak
ln -s /Volumes/ExternalDisk/DockerData/Docker.raw \
      ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw

# 4. 启动Docker Desktop并验证
docker info | grep "Docker Root Dir"
4.4.3 清理Docker磁盘空间
# 查看Docker磁盘使用情况
docker system df

# 清理无用镜像和容器
docker system prune -a

# 清理包括数据卷
docker system prune -a --volumes

# 查看具体的空间占用
docker system df -v

4.5 macOS特有问题与解决方案

4.5.1 文件挂载权限问题

在macOS上,Docker Desktop使用osxfs或VirtioFS进行文件共享,有时会遇到权限问题:

# 问题:容器内无法访问挂载的文件
# 原因:macOS的文件权限与容器内不一致

# 解决方案1:在Dockerfile中设置适当的权限
RUN chmod -R 755 /app

# 解决方案2:使用Docker Volume代替Bind Mount
docker volume create mydata
docker run -v mydata:/data alpine sh

# 解决方案3:配置文件共享(Settings -> Resources -> File sharing)
# 确保挂载的目录在文件共享列表中
4.5.2 网络性能问题
# 问题:容器内访问外部网络慢
# 解决方案:配置DNS

# 编辑daemon.json
# Settings -> Docker Engine
{
  "dns": ["8.8.8.8", "1.1.1.1"]
}

# 或在docker run时指定
docker run --dns 8.8.8.8 -it alpine sh
4.5.3 Apple Silicon运行x86镜像问题
# 问题:某些镜像只有amd64版本,在Apple Silicon上运行报错
# 解决方案1:使用--platform参数指定平台
docker run --platform linux/amd64 -it old-image:latest bash

# 解决方案2:在Dockerfile中指定平台
# Dockerfile
FROM --platform=linux/amd64 ubuntu:22.04

# 解决方案3:启用Rosetta 2(参考4.2.4节)

# 解决方案4:使用buildx构建多架构镜像
docker buildx build --platform linux/amd64,linux/arm64 -t myapp:latest .
4.5.4 Docker Desktop占用内存过高
# 问题:Docker Desktop占用大量内存
# 解决方案1:限制内存使用
# Settings -> Resources -> Memory: 设置为合理值

# 解决方案2:使用Colima替代(更轻量)
brew install colima
colima start --cpu 2 --memory 4

# 解决方案3:定期清理资源
docker system prune -a
4.5.5 虚拟网络冲突
# 问题:Docker网络与macOS VPN冲突
# 解决方案:配置Docker使用不同的IP段

# 编辑daemon.json
{
  "bip": "172.20.0.1/16",
  "default-address-pools": [
    {"base": "172.20.0.0/16", "size": 24}
  ]
}

# 重启Docker Desktop使配置生效
4.5.6 Docker Desktop许可问题

从2022年起,Docker Desktop对大型企业(250人以上或年收入超过1000万美元)需要付费许可。对于不符合条件的用户,Docker Desktop仍然免费。替代方案:

替代方案 说明 适合场景
Colima 轻量级容器运行时 开发/CI
Podman Desktop RedHat的容器工具 开发
OrbStack 高性能替代方案 开发
Rancher Desktop 开源容器管理 开发/测试
minikube K8s本地环境 K8s开发
# 安装OrbStack(Apple Silicon推荐)
brew install --cask orbstack

# 安装Rancher Desktop
brew install --cask rancher

# 安装Podman Desktop
brew install --cask podman-desktop

第五章 Docker版本体系

Docker的版本体系经历了多次演变,了解不同版本和通道的区别,对于选择合适的Docker版本至关重要。本章将详细讲解Docker的版本分类、发布通道、版本号规则以及版本选择策略。

Docker自2013年首次发布以来,经历了多次重大的版本策略调整。早期的Docker采用1.x版本号,从Docker 1.13版本之后,Docker公司调整了版本号方案,采用了基于年月的版本号规则(如17.03、17.06等),后来又调整为简单的递增版本号(如18.09、19.03、20.10等,直到目前的27.x)。与此同时,Docker的产品线也进行了多次调整,从最初的Docker Engine单一产品,发展到Docker CE/EE的双版本策略,再到如今以Docker Engine(开源免费)和Docker Desktop(桌面端产品)为主的格局。

对于使用者来说,理解Docker的版本体系有助于做出正确的选择。在生产环境中,选择一个经过充分验证的稳定版本非常重要,过于前沿的版本可能存在未发现的缺陷。而在开发环境中,使用最新版本可以享受最新的功能和性能优化。此外,了解版本升级和回滚的方法也是运维工作的重要部分,因为Docker版本升级有时可能引入不兼容的变更。

5.1 Docker CE vs Docker EE

Docker曾经分为两个主要版本:社区版(Community Edition)和企业版(Enterprise Edition)。

特性 Docker CE(社区版) Docker EE(企业版)
费用 免费 付费
更新频率 每月 每季度
支持周期 7个月 24个月
安全扫描 不包含 包含
LDAP集成 不包含 包含
多云管理 不包含 包含
技术支持 社区支持 商业支持
认证基础设施 不包含 包含

重要说明:从2020年开始,Docker公司已经停止了Docker EE的销售和维护。Docker EE的技术已经被转让给Mirantis公司,现在以Mirantis Container Runtime的名义继续发展。对于大多数用户和企业,Docker CE(现在直接称为Docker Engine)已经完全满足需求。

5.1.1 Docker Engine(原Docker CE)

Docker Engine是当前Docker的核心产品,它是开源的,免费使用:

# 查看Docker Engine版本
docker version

# Docker Engine的组成
# 1. dockerd - Docker守护进程
# 2. docker CLI - 命令行客户端
# 3. containerd - 容器运行时
# 4. runc - OCI容器运行时
5.1.2 Mirantis Container Runtime(原Docker EE)
# Mirantis Container Runtime使用不同的包名
# 在Ubuntu/Debian上:
sudo apt-get install -y docker-ee docker-ee-cli containerd.io-ee

# 在CentOS/RHEL上:
sudo yum install -y docker-ee docker-ee-cli containerd.io-ee

# 注意:需要先添加Mirantis的仓库和许可证

5.2 Stable vs Edge vs Test通道

Docker Desktop曾经提供不同的发布通道,目前主要使用Stable和Test通道:

通道 说明 更新频率 适合人群
Stable 稳定版,经过充分测试 每月 生产环境、日常开发
Test 测试版,包含新特性 每两周 尝试新功能的开发者
Edge(已废弃) 边缘版,最新功能 每月(已停止) 不再使用
5.2.1 切换发布通道
# Docker Desktop切换通道
# macOS/Windows:
# Settings -> Software updates -> Channel
# 选择 Stable 或 Test

# Linux上没有通道概念,直接安装指定版本即可
5.2.2 查看当前通道和版本
# 查看Docker版本详情
docker version --format '{{.Server.Version}}'

# 查看是否为实验版本
docker version --format '{{.Server.Experimental}}'

# 查看Docker Desktop版本(仅Desktop)
docker desktop version

5.3 版本号规则解读(YY.MM)

Docker Engine采用YY.MM(年.月)的版本号规则:

版本号格式: YY.MM.PATCH

示例:
  27.0.3  -> 2027年(实际为2024年发布,编号27表示第27个大版本) 0月 第3个补丁
  26.1.4  -> 第26个大版本 1月 第4个补丁
  25.0.5  -> 第25个大版本 0月 第5个补丁

注意:从2017年3月开始,Docker采用了每月发布的节奏。版本号的含义:

  • 主版本号:按发布顺序递增(不是年份)
  • 次版本号:发布月份(0-11)
  • 补丁号:该月的第几个补丁版本
5.3.1 版本发布时间线
版本 发布时间 重要特性
20.10 2020-12 cgroup v2支持、Rootless模式
21.x 跳过 -
22.x 跳过 -
23.0 2023-02 BuildKit默认启用、移除旧legacy builder
24.0 2023-05 稳定性改进、cgroup v2增强
25.0 2024-01 移除已废弃特性、性能优化
26.0 2024-04 新的日志驱动、安全增强
27.0 2024-06 containerd image store默认、API变更
5.3.2 查看版本发布说明
# 查看当前版本的详细信息
docker version

# 查看Docker Engine的完整版本信息
docker info --format '{{json .}}' | python3 -m json.tool

Docker各版本的发布说明可以在官方GitHub仓库查看:

https://github.com/moby/moby/releases

5.4 Docker Engine与Docker Desktop的区别

很多初学者容易混淆Docker Engine和Docker Desktop,下面详细对比:

特性 Docker Engine Docker Desktop
运行平台 Linux原生 Windows/macOS
安装方式 包管理器安装 安装包安装
虚拟化 不需要 需要WSL 2/Hyper-V/Hypervisor
GUI界面
Docker Compose 需单独安装插件 内置
Kubernetes 需单独安装 内置(可选启用)
BuildKit 内置 内置
商业许可 完全免费 大企业需付费
资源管理 系统原生 通过虚拟机分配
文件共享 原生文件系统 通过虚拟化文件共享
网络 直接使用宿主机网络 通过虚拟网络转发
适合场景 Linux服务器/生产环境 Windows/macOS开发
5.4.1 Docker Engine架构
# Docker Engine在Linux上的架构
#
# 用户命令 -> docker CLI -> docker daemon (dockerd) -> containerd -> runc -> 容器
#
# 各组件的作用:
# - docker CLI: 接收用户命令,通过REST API发送给dockerd
# - dockerd: Docker守护进程,管理镜像、容器、网络、卷
# - containerd: 高级容器运行时,管理容器生命周期
# - runc: 低级容器运行时,遵循OCI标准,创建和运行容器
5.4.2 Docker Desktop架构
# Docker Desktop在Windows上的架构
#
# 用户命令 -> docker CLI (Windows) -> docker daemon (WSL 2中) -> containerd -> runc -> 容器
#
# Docker Desktop额外组件:
# - Docker Desktop GUI: 图形管理界面
# - Docker Dashboard: 容器/镜像/卷的可视化管理
# - Docker Compose: 内置的容器编排工具
# - Kubernetes: 可选的单节点K8s集群
# - BuildKit: 增强的镜像构建引擎

5.5 如何选择合适的版本

5.5.1 选择决策流程
选择Docker版本的决策流程:

1. 确定操作系统:
   - Linux服务器 -> Docker Engine
   - Windows开发机 -> Docker Desktop for Windows
   - macOS开发机 -> Docker Desktop for Mac / Colima

2. 确定使用场景:
   - 生产环境 -> Docker Engine Stable
   - 开发环境 -> Docker Desktop Stable
   - 测试新特性 -> Docker Desktop Test

3. 确定版本要求:
   - 需要稳定性 -> 选择上一个LTS版本
   - 需要新功能 -> 选择最新版本
   - 特定需求 -> 选择包含所需功能的版本
5.5.2 生产环境版本选择建议
# 生产环境推荐选择策略:
# 1. 不要使用最新版本(可能存在未发现的bug)
# 2. 选择上一个稳定版本
# 3. 关注版本的安全公告
# 4. 制定版本升级计划

# 查看Docker安全公告
# https://github.com/moby/moby/security/advisories

# 生产环境推荐版本(截至2024年):
# Docker Engine 26.x 或 24.x (稳定且经过充分验证)
5.5.3 开发环境版本选择建议
# 开发环境推荐使用最新稳定版
# 原因:
# 1. 享受最新特性和性能优化
# 2. 与生产环境版本差异可控
# 3. 社区支持更好(最新版本的文档和讨论更多)

# 开发环境推荐:
# Docker Desktop 最新 Stable 版本
# Docker Engine 最新 Stable 版本

5.6 Docker版本升级与回滚

5.6.1 升级Docker Engine(Linux)
# Ubuntu/Debian升级Docker
# 1. 更新包索引
sudo apt-get update

# 2. 查看可用新版本
apt-cache policy docker-ce

# 3. 升级Docker
sudo apt-get install --only-upgrade docker-ce docker-ce-cli containerd.io \
    docker-buildx-plugin docker-compose-plugin

# 4. 验证升级结果
docker version

# 5. 重启Docker服务(如果需要)
sudo systemctl restart docker
# CentOS/RHEL升级Docker
# 1. 更新包索引
sudo yum check-update

# 2. 升级Docker
sudo yum update docker-ce docker-ce-cli containerd.io \
    docker-buildx-plugin docker-compose-plugin

# 3. 验证升级结果
docker version

# 4. 重启Docker服务
sudo systemctl restart docker
5.6.2 升级Docker Desktop(Windows/macOS)
# 方法1:自动更新
# Docker Desktop默认启用自动更新
# 设置 -> Software updates -> Check for updates

# 方法2:手动下载新版本
# 从官网下载最新安装包,直接覆盖安装

# 方法3:使用命令行更新(macOS)
brew upgrade --cask docker

# 方法4:使用winget更新(Windows)
winget upgrade Docker.DockerDesktop
5.6.3 回滚Docker版本
# Ubuntu/Debian回滚到指定版本
# 1. 查看可用版本
apt-cache madison docker-ce

# 2. 停止Docker服务
sudo systemctl stop docker

# 3. 安装指定版本(降级)
sudo apt-get install -y \
    docker-ce=5:26.1.4-1~ubuntu.22.04~jammy \
    docker-ce-cli=5:26.1.4-1~ubuntu.22.04~jammy \
    containerd.io

# 4. 锁定版本(防止自动升级)
sudo apt-mark hold docker-ce docker-ce-cli containerd.io

# 5. 重启Docker
sudo systemctl start docker

# 6. 验证版本
docker version
# CentOS/RHEL回滚到指定版本
# 1. 查看可用版本
yum list docker-ce --showduplicates

# 2. 停止Docker
sudo systemctl stop docker

# 3. 降级安装
sudo yum downgrade docker-ce-26.1.4-1.el9 \
    docker-ce-cli-26.1.4-1.el9 containerd.io

# 4. 锁定版本
sudo yum versionlock docker-ce docker-ce-cli containerd.io

# 5. 重启Docker
sudo systemctl start docker
5.6.4 升级前的备份
# 升级前备份Docker数据

# 1. 备份Docker配置文件
sudo cp /etc/docker/daemon.json /etc/docker/daemon.json.bak
sudo cp -r /etc/containerd /etc/containerd.bak

# 2. 备份Docker数据目录(可选,但推荐)
sudo tar -czf /tmp/docker-data-backup.tar.gz /var/lib/docker/

# 3. 导出镜像列表
docker images --format '{{.Repository}}:{{.Tag}}' > /tmp/images-list.txt

# 4. 导出容器配置
docker ps -a --format '{{.Names}} {{.Image}} {{.Command}}' > /tmp/containers-list.txt

# 5. 备份Docker Compose文件
find / -name "docker-compose.yml" -o -name "docker-compose.yaml" 2>/dev/null > /tmp/compose-files.txt
5.6.5 升级后的验证
# 升级后验证清单

# 1. 验证Docker服务状态
sudo systemctl status docker

# 2. 验证Docker版本
docker version

# 3. 验证容器状态
docker ps -a

# 4. 验证网络
docker network ls

# 5. 验证数据卷
docker volume ls

# 6. 运行测试容器
docker run --rm hello-world

# 7. 验证Docker Compose
docker compose version

# 8. 检查日志是否有错误
sudo journalctl -u docker --since "5 minutes ago" | grep -i error

第六章 Docker镜像加速配置

在国内使用Docker时,由于网络原因,从Docker Hub拉取镜像往往非常缓慢,甚至超时失败。配置镜像加速器是解决这个问题的有效方法。本章将详细讲解镜像加速的原理、配置方法和企业级方案。

对于国内的Docker用户来说,镜像拉取速度是影响开发效率的一个关键问题。Docker Hub是Docker官方的公共镜像仓库,其服务器部署在海外。当国内用户从Docker Hub拉取镜像时,数据需要经过国际网络传输,受到网络带宽、跨境延迟、防火墙策略等多种因素的影响,导致拉取速度极慢甚至超时失败。这不仅影响日常开发体验,在CI/CD流水线中更会导致构建超时和部署失败。

镜像加速器(Registry Mirror)是解决这个问题的有效方案。镜像加速器本质上是Docker Hub的一个缓存代理服务器,它部署在国内网络中,当用户请求拉取镜像时,加速器会先检查本地是否已缓存该镜像。如果已缓存且是最新的,则直接返回给用户,速度非常快。如果未缓存或已过期,加速器会从Docker Hub拉取镜像,缓存后再返回给用户。这种机制使得第一次拉取某个镜像时速度可能仍然较慢(因为需要从Docker Hub拉取),但后续再次拉取相同镜像时速度会大幅提升。

6.1 为什么需要镜像加速

6.1.1 Docker Hub访问慢的原因
# 测试从Docker Hub拉取镜像的速度
time docker pull ubuntu:22.04

# 可能的输出:
# Using default tag: latest
# latest: Pulling from library/ubuntu
# ...(等待很长时间)
# Error response from daemon: Get "https://registry-1.docker.io/v2/": 
# net/http: request canceled (Client.Timeout exceeded while awaiting headers)

Docker Hub访问慢的原因主要有:

  1. 物理距离:Docker Hub的服务器主要在美国,国内访问需要跨越太平洋
  2. 网络带宽:国际出口带宽有限,高峰期容易拥塞
  3. DNS解析:某些DNS服务器对Docker Hub域名解析不佳
  4. 防火墙策略:部分网络环境对国际流量有限制
6.1.2 镜像加速的原理

镜像加速器(Registry Mirror)本质上是一个代理服务器,它缓存了Docker Hub上的镜像。当你请求拉取镜像时:

正常流程:
  docker pull -> Docker Hub (registry-1.docker.io) -> 下载镜像层

加速流程:
  docker pull -> 镜像加速器 (mirror.example.com) -> 检查缓存
    -> 如果有缓存: 直接返回(快速)
    -> 如果无缓存: 从Docker Hub拉取并缓存,再返回给你

6.2 国内主流镜像加速器

加速器名称 加速地址 说明 可用性
阿里云 https://<你的ID>.mirror.aliyuncs.com 需要登录获取个人专属地址 稳定
腾讯云 https://mirror.ccs.tencentyun.com 腾讯云内网使用 稳定
中科大 https://docker.mirrors.ustc.edu.cn 教育网速度快 有时不稳定
网易 https://hub-mirror.c.163.com 网易提供的公共加速 稳定
百度 https://mirror.baidubce.com 百度云提供 稳定
Daocloud https://f1361db2.m.daocloud.io DaoCloud提供 有时变化
1Panel https://docker.1panel.live 社区维护 较稳定
南京大学 https://docker.nju.edu.cn 教育网 稳定

注意:镜像加速器的可用性会随时间变化。截至2024年,部分公共加速器可能已失效。建议优先使用阿里云个人加速器或自建代理。

6.2.1 获取阿里云专属加速地址
# 1. 登录阿里云容器镜像服务
# 访问: https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors

# 2. 获取你的专属加速器地址
# 格式: https://xxxxxxxx.mirror.aliyuncs.com

# 3. 该地址是个人专属的,每个阿里云账号都有一个

6.3 配置daemon.json(详细示例)

6.3.1 Linux系统配置
# 创建或编辑Docker配置文件
sudo mkdir -p /etc/docker

sudo tee /etc/docker/daemon.json <<'EOF'
{
  "registry-mirrors": [
    "https://xxxxxxxx.mirror.aliyuncs.com",
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com",
    "https://mirror.baidubce.com"
  ]
}
EOF

# 重新加载systemd配置
sudo systemctl daemon-reload

# 重启Docker服务
sudo systemctl restart docker

# 验证配置是否生效
docker info | grep -A 5 "Registry Mirrors"

输出验证:

 Registry Mirrors:
  https://xxxxxxxx.mirror.aliyuncs.com/
  https://docker.mirrors.ustc.edu.cn/
  https://hub-mirror.c.163.com/
  https://mirror.baidubce.com/
6.3.2 Docker Desktop配置

在Docker Desktop的设置界面中配置:

Settings -> Docker Engine:
{
  "registry-mirrors": [
    "https://xxxxxxxx.mirror.aliyuncs.com",
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com"
  ]
}

点击"Apply & Restart"使配置生效。

6.3.3 完整的daemon.json示例
{
  "registry-mirrors": [
    "https://xxxxxxxx.mirror.aliyuncs.com",
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com",
    "https://mirror.baidubce.com"
  ],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "storage-driver": "overlay2",
  "live-restore": true,
  "dns": ["8.8.8.8", "114.114.114.114"]
}

6.4 多镜像源配置与故障转移

Docker支持配置多个镜像加速器,当第一个加速器不可用时,会自动尝试下一个。

6.4.1 故障转移机制
{
  "registry-mirrors": [
    "https://xxxxxxxx.mirror.aliyuncs.com",
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com",
    "https://mirror.baidubce.com"
  ]
}

工作原理:

  1. Docker首先尝试从第一个加速器拉取镜像
  2. 如果第一个加速器超时或返回错误,自动尝试第二个
  3. 依次类推,直到所有加速器都尝试完毕
  4. 如果所有加速器都失败,最后尝试直接从Docker Hub拉取
6.4.2 加速器健康检查脚本
#!/bin/bash
# 镜像加速器健康检查脚本

MIRRORS=(
    "https://xxxxxxxx.mirror.aliyuncs.com"
    "https://docker.mirrors.ustc.edu.cn"
    "https://hub-mirror.c.163.com"
    "https://mirror.baidubce.com"
    "https://docker.1panel.live"
)

echo "===== Docker镜像加速器健康检查 ====="
echo "时间: $(date)"
echo ""

for mirror in "${MIRRORS[@]}"; do
    echo -n "检查 $mirror ... "
    # 测试连接(超时5秒)
    result=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 \
        "${mirror}/v2/" 2>/dev/null)
    
    if [ "$result" = "401" ] || [ "$result" = "200" ]; then
        echo "正常 (HTTP $result)"
    elif [ "$result" = "000" ]; then
        echo "超时/无法连接"
    else
        echo "异常 (HTTP $result)"
    fi
done

echo ""
echo "===== 检查完成 ====="
6.4.3 测试镜像拉取速度
#!/bin/bash
# 镜像拉取速度测试脚本

echo "===== 镜像拉取速度测试 ====="

# 测试拉取时间
echo "拉取 alpine:latest ..."
time docker pull alpine:latest

echo ""
echo "拉取 nginx:latest ..."
time docker pull nginx:latest

echo ""
echo "拉取 python:3.11-slim ..."
time docker pull python:3.11-slim

# 清理测试镜像
docker rmi alpine:latest nginx:latest python:3.11-slim 2>/dev/null

echo ""
echo "===== 测试完成 ====="

6.5 验证加速效果

6.5.1 查看当前镜像加速配置
# 查看Docker信息中的镜像加速器配置
docker info | grep -A 10 "Registry Mirrors"

# 查看完整的Docker配置
docker info
6.5.2 对比加速前后的拉取速度
# 配置加速器前
# 记录拉取时间
echo "=== 配置加速器前 ==="
time docker pull ubuntu:22.04

# 配置加速器后
echo "=== 配置加速器后 ==="
time docker pull ubuntu:22.04

# 对比两次的时间
6.5.3 查看镜像拉取详情
# 使用--verbose查看拉取详情
docker pull --verbose ubuntu:22.04 2>&1 | head -20

# 查看从哪个源拉取的
docker pull alpine:latest 2>&1
# 如果加速器配置正确,会看到从加速器地址拉取

6.6 企业级私有镜像代理搭建

对于企业环境,可以搭建私有的镜像代理服务,实现统一的镜像加速和管理。

6.6.1 使用Docker Registry作为代理
# 使用官方Docker Registry搭建镜像代理
docker run -d \
    --name registry-proxy \
    -p 5000:5000 \
    -e REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io \
    -v /data/registry-proxy:/var/lib/registry \
    --restart always \
    registry:2

# 配置Docker使用私有代理
# 编辑 /etc/docker/daemon.json
{
  "registry-mirrors": ["http://your-server:5000"],
  "insecure-registries": ["your-server:5000"]
}
6.6.2 使用Harbor搭建企业镜像仓库
# Harbor是VMware开源的企业级镜像仓库
# 支持镜像代理、权限管理、漏洞扫描等功能

# 1. 下载Harbor安装包
wget https://github.com/goharbor/harbor/releases/download/v2.9.0/harbor-offline-installer-v2.9.0.tgz

# 2. 解压
tar -xzf harbor-offline-installer-v2.9.0.tgz
cd harbor

# 3. 复制配置模板
cp harbor.yml.tmpl harbor.yml

# 4. 编辑配置文件
# 修改 hostname、http.port、admin密码等
vi harbor.yml

# 配置示例:
# hostname: harbor.example.com
# http:
#   port: 80
# harbor_admin_password: Harbor12345
# data_volume: /data/harbor

# 5. 安装Harbor
./install.sh --with-trivy

# 6. 配置Harbor作为Docker Hub代理
# 登录Harbor管理界面
# 项目 -> 新建项目
# 项目名称: dockerhub-proxy
# 访问级别: 公开
# 代理镜像仓库: 启用
# 远程仓库URL: https://registry-1.docker.io
6.6.3 使用Nexus作为镜像代理
# Nexus是Sonatype的仓库管理器,支持多种格式

# 1. 运行Nexus容器
docker run -d \
    --name nexus \
    -p 8081:8081 \
    -v /data/nexus:/nexus-data \
    --restart always \
    sonatype/nexus3:latest

# 2. 配置Docker代理仓库
# 登录Nexus管理界面: http://your-server:8081
# 设置 -> Repositories -> Create repository
# 选择 docker (proxy)
# Name: docker-hub-proxy
# Remote storage: https://registry-1.docker.io
# Docker Index: Use Docker Hub

# 3. 创建Docker仓库组(合并proxy和hosted)
# Create repository -> docker (group)
# Name: docker-group
# Member repositories: docker-hub-proxy, docker-hosted

# 4. 配置Docker使用Nexus代理
{
  "registry-mirrors": ["http://your-server:8082"],
  "insecure-registries": ["your-server:8082"]
}
6.6.4 企业级镜像管理最佳实践
# docker-compose.yml - 企业级镜像代理架构
version: '3.8'

services:
  harbor:
    image: goharbor/harbor-core:v2.9.0
    ports:
      - "443:8443"
    volumes:
      - /data/harbor:/var/lib/harbor
    environment:
      - CONFIG_PATH=/etc/harbor/harbor.yml
    restart: always
    depends_on:
      - harbor-db
      - redis

  harbor-db:
    image: goharbor/harbor-db:v2.9.0
    volumes:
      - /data/harbor-db:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=harbor123
    restart: always

  redis:
    image: redis:7-alpine
    volumes:
      - /data/redis:/data
    restart: always

企业镜像管理建议:

  1. 统一入口:所有Docker镜像通过私有仓库代理拉取
  2. 安全扫描:使用Trivy或Clair对镜像进行漏洞扫描
  3. 访问控制:配置RBAC,限制不同团队的镜像访问权限
  4. 缓存策略:合理设置缓存TTL,平衡存储空间和更新频率
  5. 监控告警:监控镜像仓库的健康状态和存储使用情况
  6. 备份策略:定期备份镜像仓库数据
  7. 多区域复制:在多个区域部署镜像仓库,实现跨区域加速

第七章 Docker核心配置详解

Docker的daemon.json是Docker守护进程的核心配置文件,通过它可以控制Docker的几乎所有行为。本章将深入解析每一个配置项的含义、用法和最佳实践。

daemon.json是Docker守护进程(dockerd)在启动时读取的配置文件。这个文件使用JSON格式,包含了Docker守护进程运行所需的所有配置参数。通过修改这个文件,你可以控制Docker的数据存储位置、网络配置、日志行为、安全策略、存储驱动、镜像仓库等几乎所有方面。

对于生产环境而言,正确的daemon.json配置至关重要。一个配置不当的Docker环境可能会遇到各种问题:日志文件无限增长导致磁盘空间耗尽、容器没有资源限制导致OOM(内存溢出)影响宿主机、网络配置不当导致容器无法通信、安全配置缺失导致容器逃逸风险等。因此,深入理解daemon.json的每个配置项,并根据实际需求进行合理配置,是Docker运维工作的核心技能之一。

需要特别注意的是,daemon.json的修改需要重启Docker守护进程才能生效(除非使用了live-restore功能,这种情况下可以通过systemctl reload docker来重新加载配置而不停止正在运行的容器)。在修改配置前,建议先备份现有的配置文件,以便在出现问题时可以快速回滚。此外,daemon.json使用JSON格式,语法错误会导致Docker无法启动,因此在修改后应使用JSON验证工具检查语法是否正确。

7.1 daemon.json完整配置项解析

daemon.json文件位于/etc/docker/daemon.json(Linux)或通过Docker Desktop设置界面配置。以下是完整的配置项概览:

{
  "api-cors-header": "",
  "authorization-plugins": [],
  "bip": "",
  "bridge": "",
  "cgroup-parent": "",
  "cluster-advertise": "",
  "cluster-store": "",
  "containerd": "/run/containerd/containerd.sock",
  "containerd-namespace": "moby",
  "data-root": "/var/lib/docker",
  "debug": false,
  "default-address-pools": [],
  "default-cgroupns-mode": "host",
  "default-gateway": "",
  "default-gateway-v6": "",
  "default-runtime": "runc",
  "default-shm-size": "64M",
  "default-ulimits": {},
  "dns": [],
  "dns-opts": [],
  "dns-search": [],
  "exec-opts": [],
  "exec-root": "/var/run/docker",
  "experimental": false,
  "features": {},
  "fixed-cidr": "",
  "fixed-cidr-v6": "",
  "group": "docker",
  "host-gateway-ip": "",
  "hosts": [],
  "icc": true,
  "init": false,
  "init-path": "/usr/libexec/docker/docker-init",
  "insecure-registries": [],
  "ip": "0.0.0.0",
  "ip-forward": true,
  "ip-masq": true,
  "iptables": true,
  "ip6tables": false,
  "ipv6": false,
  "labels": [],
  "live-restore": false,
  "log-driver": "json-file",
  "log-opts": {},
  "max-concurrent-downloads": 3,
  "max-concurrent-uploads": 5,
  "max-download-attempts": 5,
  "mtu": 0,
  "no-new-privileges": false,
  "node-generic-resource": [],
  "oom-score-adjust": -500,
  "pidfile": "/var/run/docker.pid",
  "raw-args": [],
  "registry-mirrors": [],
  "rootless": false,
  "runtimes": {},
  "seccomp-profile": "",
  "selinux-enabled": false,
  "shutdown-timeout": 15,
  "storage-driver": "overlay2",
  "storage-opts": [],
  "swarm-default-advertise-addr": "",
  "tls": false,
  "tlscacert": "",
  "tlscert": "",
  "tlskey": "",
  "tlsverify": false,
  "userland-proxy": true,
  "userland-proxy-path": "/usr/bin/docker-proxy",
  "userns-remap": ""
}

7.2 数据目录(data-root)配置

Docker默认将所有数据存储在/var/lib/docker目录下,包括镜像、容器、数据卷、网络配置等。在磁盘空间不足或需要使用更快的存储设备时,需要修改数据目录。

7.2.1 修改数据目录
# 1. 停止Docker服务
sudo systemctl stop docker

# 2. 创建新的数据目录
sudo mkdir -p /data/docker

# 3. 迁移现有数据(如果有的话)
sudo rsync -aP /var/lib/docker/ /data/docker/

# 4. 修改daemon.json
sudo tee /etc/docker/daemon.json <<EOF
{
  "data-root": "/data/docker"
}
EOF

# 5. 启动Docker服务
sudo systemctl start docker

# 6. 验证配置是否生效
docker info | grep "Docker Root Dir"
# 期望输出: Docker Root Dir: /data/docker

# 7. 验证数据完整性
docker images
docker ps -a

# 8. 确认无误后,删除旧数据目录
# sudo rm -rf /var/lib/docker
7.2.2 数据目录结构说明
/data/docker/
├── builder/          # BuildKit构建缓存
├── buildkit/         # BuildKit相关数据
├── containers/       # 容器配置和日志
├── image/            # 镜像层数据
│   └── overlay2/     # overlay2存储驱动数据
├── network/          # 网络配置
├── plugins/          # 插件数据
├── runtimes/         # 运行时数据
├── swarm/            # Swarm集群数据
├── tmp/              # 临时文件
├── trust/            # 信任数据
└── volumes/          # 数据卷
7.2.3 使用独立磁盘的性能优化
# 将Docker数据目录放在SSD或NVMe上
# 推荐使用LVM或独立分区管理Docker数据

# 创建LVM逻辑卷(示例)
sudo pvcreate /dev/nvme0n1
sudo vgcreate docker-vg /dev/nvme0n1
sudo lvcreate -l 100%FREE -n docker-lv docker-vg
sudo mkfs.ext4 /dev/docker-vg/docker-lv

# 挂载到Docker数据目录
sudo mkdir -p /data/docker
sudo mount /dev/docker-vg/docker-lv /data/docker

# 设置开机自动挂载
echo "/dev/docker-vg/docker-lv /data/docker ext4 defaults,noatime 0 2" | sudo tee -a /etc/fstab

7.3 日志配置(log-driver、log-opts)

Docker容器的日志如果不加以限制,可能会占用大量磁盘空间,最终导致磁盘写满。

7.3.1 日志驱动类型
日志驱动 说明 适用场景
json-file 默认驱动,JSON格式存储到文件 单机开发/测试
local 优化的本地日志存储 生产环境(推荐)
journald 写入systemd journal systemd系统
syslog 写入syslog 传统日志系统
fluentd 发送到Fluentd 容器化日志收集
awslogs 发送到AWS CloudWatch AWS环境
gcplogs 发送到Google Cloud Logging GCP环境
gelf 发送到Graylog/GELF Graylog用户
splunk 发送到Splunk Splunk用户
none 禁用日志 不需要日志的场景
7.3.2 配置json-file日志限制
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3",
    "labels": "production",
    "env": "os,customer",
    "compress": "true"
  }
}

配置说明:

  • max-size:单个日志文件最大大小,超过后轮转
  • max-file:保留的日志文件数量
  • labels:在日志中包含的容器标签
  • env:在日志中包含的环境变量
  • compress:压缩轮转的日志文件
7.3.3 配置local日志驱动(推荐)
{
  "log-driver": "local",
  "log-opts": {
    "max-size": "10m",
    "max-file": "5",
    "compress": "true"
  }
}

local驱动相比json-file的优势:

  • 更高效的无结构日志存储
  • 默认使用二进制格式
  • 更好的磁盘空间利用率
7.3.4 为单个容器配置日志
# 在docker run时指定日志配置
docker run -d \
    --name my-app \
    --log-driver json-file \
    --log-opt max-size=10m \
    --log-opt max-file=3 \
    nginx:latest

# 使用none驱动禁用日志
docker run -d \
    --name silent-app \
    --log-driver none \
    alpine:latest

# 使用fluentd驱动
docker run -d \
    --name my-app \
    --log-driver fluentd \
    --log-opt fluentd-address=localhost:24224 \
    --log-opt tag=docker.myapp \
    nginx:latest
7.7.5 查看容器日志
# 查看容器日志
docker logs my-app

# 跟踪日志输出
docker logs -f my-app

# 查看最后100行日志
docker logs --tail 100 my-app

# 查看指定时间后的日志
docker logs --since "2024-06-15T10:00:00" my-app

# 查看最近10分钟的日志
docker logs --since 10m my-app

# 查看指定时间段的日志
docker logs --since "2024-06-15T10:00:00" --until "2024-06-15T11:00:00" my-app

# 显示时间戳
docker logs -t my-app

# 查看日志详情(包括日志文件位置)
docker inspect my-app | grep -A 5 LogPath

7.4 网络配置(bip、fixed-cidr、mtu)

Docker的网络配置决定了容器的IP地址分配和网络通信方式。

7.4.1 基础网络配置
{
  "bip": "172.17.0.1/16",
  "fixed-cidr": "172.17.0.0/24",
  "default-address-pools": [
    {"base": "172.20.0.0/16", "size": 24}
  ],
  "mtu": 1500,
  "ip-forward": true,
  "ip-masq": true,
  "icc": true,
  "iptables": true
}

配置说明:

配置项 说明 默认值
bip Docker bridge网络的IP地址和子网 172.17.0.1/16
fixed-cidr 固定容器IP分配范围 -
default-address-pools 自定义网络地址池 -
mtu 最大传输单元 1500
ip-forward 启用IP转发 true
ip-masq 启用IP伪装(NAT) true
icc 允许容器间通信 true
iptables 启用iptables规则管理 true
7.4.2 修改默认网桥IP段
{
  "bip": "192.168.100.1/24"
}
# 验证修改后的网桥配置
docker network inspect bridge | grep -A 5 IPAM

# 修改后docker0网桥的IP
ip addr show docker0
7.4.3 配置自定义网络地址池
{
  "default-address-pools": [
    {"base": "172.20.0.0/16", "size": 24},
    {"base": "172.21.0.0/16", "size": 24}
  ]
}

这会为每个新创建的网络分配一个/24子网,从172.20.0.0/16开始递增。

7.4.4 MTU配置

当Docker运行在VPN或特定网络环境中时,可能需要调整MTU值:

{
  "mtu": 1400
}

常见MTU场景:

场景 推荐MTU值 说明
标准以太网 1500 默认值
VPN网络 1400 VPN封装开销
AWS VPC 9001 Jumbo Frame
Azure VNet 1500 标准值
OpenStack 1450 GRE/VXLAN封装
Kubernetes Overlay 1450 VXLAN封装
7.4.5 IPv6配置
{
  "ipv6": true,
  "fixed-cidr-v6": "fd00:dead:beef::/64",
  "ip6tables": true,
  "default-gateway-v6": "fd00:dead:beef::1"
}
# 验证IPv6配置
docker network inspect bridge | grep -A 10 IPv6

# 运行容器测试IPv6
docker run --rm -it alpine ip -6 addr

7.5 存储驱动选择(overlay2、devicemapper)

存储驱动决定了Docker如何存储和管理镜像层和容器层。

7.5.1 存储驱动对比
存储驱动 支持的文件系统 性能 推荐度 说明
overlay2 ext4, xfs 最佳 推荐 默认驱动,性能最优
fuse-overlayfs 任意 Rootless推荐 无特权模式
devicemapper direct-lvm 一般 不推荐 旧版默认
vfs 任意 最差 不推荐 仅用于调试
btrfs btrfs 可选 需要btrfs文件系统
zfs zfs 可选 需要ZFS文件系统
7.5.2 配置overlay2存储驱动
{
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.size=50G"
  ]
}
# 验证存储驱动
docker info | grep "Storage Driver"
# 期望输出: Storage Driver: overlay2

# 检查overlay2是否正常工作
docker info | grep -A 5 "Storage Driver"
# 期望输出:
# Storage Driver: overlay2
#  Backing Filesystem: extfs
#  Supports d_type: true
#  Using metacopy: false
#  Native Overlay Diff: true
#  userxattr: false
7.5.3 检查文件系统支持
# overlay2需要文件系统支持d_type
# 检查文件系统是否支持d_type
xfs_io -r -c stat / | grep fsxattr

# 检查文件系统类型
df -T /var/lib/docker

# 检查xfs的ftype(需要ftype=1)
xfs_info / | grep ftype
# 期望输出: ftype=1

重要:如果使用xfs文件系统,必须确保ftype=1,否则overlay2无法正常工作。在格式化xfs分区时需要添加-n ftype=1参数:

mkfs.xfs -n ftype=1 /dev/sdb1

存储驱动原理深入理解:

Docker的镜像是由多个只读层组成的,每层对应Dockerfile中的一条指令。当容器启动时,Docker会在镜像层之上添加一个可写层(称为容器层)。所有对容器的修改都会写入这个可写层,而不会修改底层的镜像层。这种机制被称为"写时复制"(Copy-on-Write,CoW),它使得多个容器可以共享同一个镜像的只读层,从而极大地节省了磁盘空间和启动时间。

不同的存储驱动采用了不同的技术来实现这种分层文件系统:

  • overlay2:这是Docker推荐的存储驱动,基于Linux内核的OverlayFS文件系统。OverlayFS将多个目录"叠加"在一起,形成一个统一的视图。overlay2使用两个目录:lowerdir(只读的镜像层)和upperdir(可写的容器层)。当读取文件时,OverlayFS会从upperdir开始查找,如果找到就返回;如果没找到,再从lowerdir中查找。当写入文件时,如果文件存在于lowerdir中,OverlayFS会先将文件复制到upperdir,然后进行修改。overlay2的优势在于它是内核原生支持的,性能优秀,且支持页面缓存共享。

  • devicemapper:这是一种基于块设备的存储驱动,使用LVM(逻辑卷管理器)来管理镜像层和容器层。devicemapper有两种模式:loop-lvm(默认,使用文件模拟块设备,性能差)和direct-lvm(直接使用块设备,性能好但配置复杂)。由于devicemapper配置复杂且性能不如overlay2,目前已被Docker官方标记为不推荐使用。

  • vfs:这是一种最简单的存储驱动,不使用任何高级文件系统特性,直接通过复制文件来实现分层。vfs的性能最差,但兼容性最好,适合在不支持overlay2的文件系统上使用,通常只用于调试目的。

在实际生产环境中,强烈建议使用overlay2存储驱动,并确保底层文件系统(ext4或xfs)支持所需的特性。如果你遇到overlay2相关的问题,首先应该检查文件系统是否支持d_type(这是OverlayFS正常工作的前提条件)。

7.6 安全配置(userns-remap、no-new-privileges)

7.6.1 用户命名空间重映射(userns-remap)

用户命名空间重映射可以将容器内的root用户映射为宿主机上的非特权用户,提高安全性。

{
  "userns-remap": "default"
}
# 使用自定义用户映射
# 1. 创建映射用户
sudo useradd -m dockremap

# 2. 设置子UID和子GID范围
sudo sh -c 'echo "dockremap:100000:65536" >> /etc/subuid'
sudo sh -c 'echo "dockremap:100000:65536" >> /etc/subgid'

# 3. 配置daemon.json
{
  "userns-remap": "dockremap"
}

# 4. 重启Docker
sudo systemctl restart docker

# 5. 验证用户命名空间
docker run --rm alpine cat /proc/self/uid_map
# 容器内的root(0)映射为宿主机的100000
7.6.2 no-new-privileges
{
  "no-new-privileges": true
}

此选项防止容器内的进程通过setuid程序获取额外权限。

7.6.3 seccomp配置
{
  "seccomp-profile": "/etc/docker/seccomp/default.json"
}
# Docker默认的seccomp配置已经提供了良好的安全保护
# 如果需要自定义seccomp策略,可以基于默认配置修改

# 查看Docker默认seccomp配置
docker run --rm --security-opt seccomp=unconfined alpine seccomp-tools dump

# 在docker run时指定seccomp策略
docker run --security-opt seccomp=/path/to/seccomp.json alpine
7.6.4 AppArmor配置
# 在支持AppArmor的系统上(如Ubuntu)
# 查看Docker的AppArmor配置
sudo apparmor_status | grep docker

# 自定义AppArmor配置
sudo tee /etc/apparmor.d/docker-custom <<'EOF'
#include <tunables/global>

profile docker-custom flags=(attach_disconnected,mediate_deleted) {
  #include <abstractions/base>
  
  network inet,
  network inet6,
  
  deny /etc/shadow r,
  deny /etc/passwd w,
  
  # 允许Docker操作
  /var/lib/docker/** rw,
  /var/run/docker.sock rw,
}
EOF

# 加载AppArmor配置
sudo apparmor_parser -r /etc/apparmor.d/docker-custom

# 在docker run时使用
docker run --security-opt apparmor=docker-custom alpine

7.7 资源限制配置

7.7.1 全局默认资源限制
{
  "default-shm-size": "64M",
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 65536,
      "Soft": 65536
    },
    "nproc": {
      "Name": "nproc",
      "Hard": 4096,
      "Soft": 2048
    }
  }
}
7.7.2 容器级资源限制
# CPU限制
docker run -d \
    --name my-app \
    --cpus="1.5" \                          # 限制使用1.5个CPU
    --cpu-shares=512 \                       # CPU权重(默认1024)
    --cpuset-cpus="0,1" \                    # 绑定到CPU 0和1
    --cpu-period=100000 \                    # CPU调度周期(微秒)
    --cpu-quota=50000 \                      # CPU配额(50%的CPU)
    nginx:latest

# 内存限制
docker run -d \
    --name my-app \
    --memory="512m" \                        # 内存限制
    --memory-swap="1g" \                     # 内存+交换空间限制
    --memory-reservation="256m" \            # 内存软限制
    --memory-swappiness=60 \                 # 交换空间倾向(0-100)
    --oom-kill-disable \                     # 禁止OOM Killer杀掉容器
    --oom-score-adj=-500 \                   # OOM优先级调整
    nginx:latest

# IO限制
docker run -d \
    --name my-app \
    --device-read-bps="/dev/sda:10mb" \      # 读速度限制
    --device-write-bps="/dev/sda:10mb" \     # 写速度限制
    --device-read-iops="/dev/sda:1000" \     # 读IOPS限制
    --device-write-iops="/dev/sda:1000" \    # 写IOPS限制
    nginx:latest

# PID限制
docker run -d \
    --name my-app \
    --pids-limit=100 \                       # 最大进程数
    nginx:latest
7.7.3 查看容器资源使用
# 查看所有容器的资源使用
docker stats

# 查看指定容器的资源使用
docker stats my-app

# 只输出一次(适合脚本)
docker stats --no-stream

# 自定义输出格式
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"

# 查看容器的资源限制
docker inspect my-app | grep -A 20 "HostConfig"

7.8 Insecure Registry配置

当使用自签证书的私有镜像仓库时,需要配置insecure-registries。

{
  "insecure-registries": [
    "registry.example.com:5000",
    "10.0.0.100:5000"
  ]
}
# 配置后重启Docker
sudo systemctl restart docker

# 验证配置
docker info | grep -A 5 "Insecure Registries"

# 推送镜像到私有仓库
docker tag my-app:latest registry.example.com:5000/my-app:latest
docker push registry.example.com:5000/my-app:latest

# 从私有仓库拉取镜像
docker pull registry.example.com:5000/my-app:latest

安全提示:insecure-registries配置会跳过TLS证书验证,仅适用于内网测试环境。生产环境应使用正式的TLS证书。

7.9 完整生产环境配置示例

以下是适用于生产环境的完整daemon.json配置:

{
  "data-root": "/data/docker",
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "50m",
    "max-file": "5",
    "compress": "true"
  },
  "storage-driver": "overlay2",
  "storage-opts": [],
  "live-restore": true,
  "max-concurrent-downloads": 10,
  "max-concurrent-uploads": 5,
  "max-download-attempts": 5,
  "shutdown-timeout": 15,
  "default-shm-size": "64M",
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 65536,
      "Soft": 65536
    },
    "nproc": {
      "Name": "nproc",
      "Hard": 4096,
      "Soft": 2048
    }
  },
  "registry-mirrors": [
    "https://xxxxxxxx.mirror.aliyuncs.com",
    "https://docker.mirrors.ustc.edu.cn"
  ],
  "insecure-registries": [],
  "bip": "172.17.0.1/16",
  "default-address-pools": [
    {"base": "172.20.0.0/16", "size": 24}
  ],
  "mtu": 1500,
  "ip-forward": true,
  "ip-masq": true,
  "iptables": true,
  "userland-proxy": false,
  "no-new-privileges": true,
  "features": {
    "buildkit": true
  },
  "builder": {
    "gc": {
      "enabled": true,
      "defaultKeepStorage": "20GB"
    }
  },
  "dns": ["8.8.8.8", "114.114.114.114"],
  "dns-search": ["example.com"]
}

生产环境配置说明:

配置项 生产环境值 说明
data-root /data/docker 使用独立磁盘
log-driver json-file 默认日志驱动
log-opts.max-size 50m 单个日志文件50MB
log-opts.max-file 5 保留5个日志文件
storage-driver overlay2 最佳性能存储驱动
live-restore true 守护进程重启不影响容器
max-concurrent-downloads 10 并行下载层数
userland-proxy false 禁用用户态代理(性能更好)
no-new-privileges true 安全加固
buildkit true 启用BuildKit
builder.gc.enabled true 自动清理构建缓存

第八章 Docker CLI基础命令大全

Docker命令行工具(docker CLI)是与Docker守护进程交互的主要方式。本章将系统讲解Docker的所有基础命令,包括系统信息、镜像管理、容器管理、网络管理、数据卷管理和系统管理命令。

Docker CLI是Docker使用者最常接触的工具。掌握Docker命令行工具是使用Docker的基本功,无论是日常的容器管理、镜像构建,还是生产环境的运维排障,都离不开Docker命令。Docker的命令体系设计得比较直观,采用了"docker + 管理对象 + 操作"的语法结构(如docker container rundocker image ls等),同时也支持简写形式(如docker rundocker images等),方便快速输入。

对于初学者来说,学习Docker命令的最好方法是边学边练。建议在阅读本章时,打开终端逐条执行示例命令,观察输出结果,加深理解。同时,善用docker --helpdocker <命令> --help可以查看每个命令的详细帮助信息,这是学习Docker命令的重要途径。

需要注意的是,Docker命令有一些历史遗留的简写形式。在较新的Docker版本中,官方推荐使用完整的命令格式(如docker container ls而不是docker ps),但简写形式仍然被完全支持,在实际使用中两种形式都很常见。本章会同时展示两种形式,方便读者理解。

8.1 命令体系总览(docker命令分类)

Docker命令按照功能可以分为以下几大类:

docker命令体系
├── 系统信息命令
│   ├── docker version      # 查看版本
│   ├── docker info         # 查看系统信息
│   └── docker system       # 系统管理
├── 镜像命令
│   ├── docker images       # 列出镜像
│   ├── docker pull         # 拉取镜像
│   ├── docker push         # 推送镜像
│   ├── docker build        # 构建镜像
│   ├── docker tag          # 标记镜像
│   ├── docker rmi          # 删除镜像
│   ├── docker save         # 导出镜像
│   ├── docker load         # 导入镜像
│   ├── docker history      # 查看镜像历史
│   └── docker inspect      # 查看镜像详情
├── 容器命令
│   ├── docker run          # 运行容器
│   ├── docker ps           # 列出容器
│   ├── docker start/stop   # 启动/停止容器
│   ├── docker restart      # 重启容器
│   ├── docker rm           # 删除容器
│   ├── docker exec         # 执行命令
│   ├── docker attach       # 附加容器
│   ├── docker logs         # 查看日志
│   ├── docker stats        # 资源统计
│   ├── docker top          # 查看进程
│   ├── docker inspect      # 查看详情
│   ├── docker cp           # 复制文件
│   ├── docker diff         # 查看变更
│   ├── docker export       # 导出容器
│   ├── docker import       # 导入容器
│   ├── docker commit       # 提交容器
│   ├── docker rename       # 重命名
│   ├── docker update       # 更新配置
│   ├── docker wait         # 等待退出
│   └── docker port         # 查看端口
├── 网络命令
│   ├── docker network create   # 创建网络
│   ├── docker network ls       # 列出网络
│   ├── docker network rm       # 删除网络
│   ├── docker network inspect  # 查看网络
│   ├── docker network connect  # 连接网络
│   ├── docker network disconnect  # 断开网络
│   └── docker network prune    # 清理网络
├── 数据卷命令
│   ├── docker volume create    # 创建卷
│   ├── docker volume ls        # 列出卷
│   ├── docker volume rm        # 删除卷
│   ├── docker volume inspect   # 查看卷
│   └── docker volume prune     # 清理卷
└── 系统管理命令
    ├── docker system df        # 磁盘使用
    ├── docker system events    # 事件监听
    ├── docker system info      # 系统信息
    └── docker system prune     # 清理资源

8.2 系统信息命令(version、info、system)

8.2.1 docker version
# 查看Docker版本
docker version

# 只查看客户端版本
docker version --format '{{.Client.Version}}'

# 只查看服务端版本
docker version --format '{{.Server.Version}}'

# JSON格式输出
docker version --format '{{json .}}'
8.2.2 docker info
# 查看Docker系统信息
docker info

# 只查看特定信息
docker info --format '{{.Containers}}'          # 容器数量
docker info --format '{{.Images}}'              # 镜像数量
docker info --format '{{.Driver}}'              # 存储驱动
docker info --format '{{.DockerRootDir}}'       # 数据目录
docker info --format '{{.ServerVersion}}'       # 服务端版本

# JSON格式输出(适合脚本处理)
docker info --format '{{json .}}' | python3 -m json.tool
8.2.3 docker system
# 查看Docker磁盘使用情况
docker system df

# 详细查看磁盘使用
docker system df -v

# 查看Docker事件
docker system events

# 过滤事件
docker system events --filter type=container
docker system events --filter event=start
docker system events --since "2024-06-15T10:00:00"

# 清理无用资源
docker system prune

# 清理所有无用资源(包括未使用的镜像)
docker system prune -a

# 清理包括数据卷
docker system prune -a --volumes

# 清理构建缓存
docker builder prune
docker builder prune -a

8.3 镜像命令(images、pull、push、build、tag、rmi、save、load、history、inspect)

8.3.1 docker images(列出镜像)
# 列出所有本地镜像
docker images

# 列出所有镜像(包括中间层)
docker images -a

# 只显示镜像ID
docker images -q

# 过滤镜像
docker images --filter "dangling=true"          # 只显示悬空镜像
docker images --filter "label=com.example.version=1.0"  # 按标签过滤
docker images --filter "before=ubuntu:22.04"    # 显示某镜像之前的镜像
docker images --filter "since=ubuntu:20.04"     # 显示某镜像之后的镜像

# 格式化输出
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}\t{{.CreatedSince}}"
docker images --format "{{.Repository}}:{{.Tag}} {{.Size}}"

# 按仓库名过滤
docker images ubuntu
docker images ubuntu:22.04

# 按引用方式过滤
docker images --filter "reference=ubuntu:*"
8.3.2 docker pull(拉取镜像)
# 拉取最新版本
docker pull ubuntu

# 拉取指定版本
docker pull ubuntu:22.04

# 拉取指定平台
docker pull --platform linux/arm64 ubuntu:22.04

# 拉取所有标签
docker pull -a ubuntu

# 从私有仓库拉取
docker pull registry.example.com:5000/myapp:latest

# 拉取镜像并显示详情
docker pull ubuntu:22.04 --quiet=false

# 按摘要拉取(确保获取特定版本)
docker pull ubuntu@sha256:35fb3083f7f...
8.3.3 docker push(推送镜像)
# 登录镜像仓库
docker login registry.example.com:5000

# 推送镜像
docker push registry.example.com:5000/myapp:latest

# 推送所有标签
docker push -a registry.example.com:5000/myapp

# 退出登录
docker logout registry.example.com:5000
8.3.4 docker build(构建镜像)
# 基本构建
docker build -t myapp:latest .

# 指定Dockerfile路径
docker build -f Dockerfile.prod -t myapp:prod .

# 不使用缓存构建
docker build --no-cache -t myapp:latest .

# 指定构建参数
docker build --build-arg VERSION=1.0 --build-arg ENV=prod -t myapp:latest .

# 多阶段构建
docker build --target builder -t myapp:builder .
docker build --target final -t myapp:final .

# 指定平台构建
docker build --platform linux/amd64,linux/arm64 -t myapp:latest .

# 使用BuildKit构建(推荐)
DOCKER_BUILDKIT=1 docker build -t myapp:latest .

# 构建并推送
docker buildx build --push -t registry.example.com:5000/myapp:latest .

# 查看构建历史
docker history myapp:latest
8.3.5 docker tag(标记镜像)
# 给镜像添加标签
docker tag ubuntu:22.04 my-ubuntu:latest

# 添加仓库前缀
docker tag myapp:latest registry.example.com:5000/myapp:latest

# 添加多个标签
docker tag myapp:v1.0 myapp:latest
docker tag myapp:v1.0 myapp:stable
8.3.6 docker rmi(删除镜像)
# 删除指定镜像
docker rmi ubuntu:22.04

# 通过ID删除
docker rmi abcd1234efgh

# 强制删除(即使有容器引用)
docker rmi -f ubuntu:22.04

# 删除所有悬空镜像
docker image prune

# 删除所有未使用的镜像
docker image prune -a

# 删除所有镜像(危险操作)
docker rmi $(docker images -q)
8.3.7 docker save / docker load(导出/导入镜像)
# 导出镜像为tar文件
docker save -o myapp.tar myapp:latest

# 导出多个镜像
docker save -o multi-images.tar ubuntu:22.04 nginx:latest redis:7

# 导出为gzip压缩文件
docker save myapp:latest | gzip > myapp.tar.gz

# 导入镜像
docker load -i myapp.tar

# 导入gzip压缩的镜像
docker load < myapp.tar.gz

# 离线传输镜像示例
# 机器A导出:
docker save myapp:latest | gzip > myapp.tar.gz
scp myapp.tar.gz user@machine-b:/tmp/

# 机器B导入:
docker load < /tmp/myapp.tar.gz
8.3.8 docker history(查看镜像历史)
# 查看镜像构建历史
docker history myapp:latest

# 显示完整信息(不截断)
docker history --no-trunc myapp:latest

# 只显示镜像ID
docker history -q myapp:latest

# JSON格式输出
docker history --format "{{.CreatedBy}}" myapp:latest
8.3.9 docker inspect(查看镜像详情)
# 查看镜像详细信息
docker inspect myapp:latest

# 查看特定字段
docker inspect --format '{{.Architecture}}' myapp:latest
docker inspect --format '{{.Os}}' myapp:latest
docker inspect --format '{{.Config.Cmd}}' myapp:latest
docker inspect --format '{{.Config.Entrypoint}}' myapp:latest
docker inspect --format '{{.Config.Env}}' myapp:latest
docker inspect --format '{{json .Config}}' myapp:latest

# 查看镜像层信息
docker inspect --format '{{json .RootFS.Layers}}' myapp:latest

8.4 容器命令(run、ps、start、stop、restart、rm、exec、attach、logs、stats、top、inspect、cp、diff、export、import、commit、rename、update、wait、port)

8.4.1 docker run(运行容器)- 最核心命令
# 基本运行
docker run hello-world

# 交互式运行
docker run -it ubuntu:22.04 bash

# 后台运行
docker run -d --name my-nginx nginx:latest

# 端口映射
docker run -d -p 8080:80 --name web nginx:latest           # 单端口
docker run -d -p 8080:80 -p 8443:443 --name web nginx      # 多端口
docker run -d -p 127.0.0.1:8080:80 nginx:latest             # 绑定到指定IP
docker run -d -P --name web nginx:latest                    # 随机端口映射

# 挂载数据卷
docker run -d -v /host/path:/container/path nginx:latest     # 绑定挂载
docker run -d -v my-volume:/data nginx:latest                # 命名卷
docker run -d -v /data/nginx nginx:latest                    # 匿名卷
docker run -d -v /host/path:/container/path:ro nginx:latest  # 只读挂载

# 环境变量
docker run -d -e MYSQL_ROOT_PASSWORD=password mysql:8
docker run -d -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=mydb mysql:8
docker run -d --env-file .env nginx:latest                   # 从文件读取

# 重启策略
docker run -d --restart no nginx:latest          # 不重启(默认)
docker run -d --restart on-failure nginx:latest  # 失败时重启
docker run -d --restart on-failure:5 nginx:latest # 最多重启5次
docker run -d --restart always nginx:latest       # 总是重启
docker run -d --restart unless-stopped nginx:latest # 除非手动停止

# 工作目录和用户
docker run -w /app -it ubuntu bash
docker run --user 1000:1000 -it ubuntu bash
docker run --user root -it ubuntu bash

# 网络配置
docker run -d --network host nginx:latest          # 主机网络
docker run -d --network none nginx:latest           # 无网络
docker run -d --network my-net --ip 172.20.0.10 nginx:latest  # 指定IP

# 资源限制
docker run -d --memory="512m" --cpus="1.0" nginx:latest

# 自动删除
docker run --rm -it ubuntu echo "hello"

# 命名和标签
docker run -d --name my-web --hostname myhost nginx:latest

# 健康检查
docker run -d \
    --health-cmd="curl -f http://localhost/ || exit 1" \
    --health-interval=5s \
    --health-retries=3 \
    --health-timeout=2s \
    --health-start-period=10s \
    nginx:latest
8.4.2 docker ps(列出容器)
# 列出运行中的容器
docker ps

# 列出所有容器(包括已停止的)
docker ps -a

# 只显示容器ID
docker ps -q

# 显示最近创建的容器
docker ps -l
docker ps -n 5    # 最近5个

# 过滤容器
docker ps -f "status=running"
docker ps -f "status=exited"
docker ps -f "name=my-web"
docker ps -f "label=environment=production"
docker ps -f "ancestor=nginx:latest"

# 格式化输出
docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Ports}}"
docker ps --format "{{.Names}}: {{.Status}}"

# 显示容器大小
docker ps -s
8.4.3 容器生命周期命令
# 启动已停止的容器
docker start my-container
docker start -i my-container      # 交互模式启动

# 停止容器
docker stop my-container
docker stop -t 30 my-container    # 等待30秒后强制停止

# 重启容器
docker restart my-container
docker restart -t 30 my-container

# 暂停容器(不终止进程,只是暂停)
docker pause my-container

# 恢复暂停的容器
docker unpause my-container

# 删除容器
docker rm my-container
docker rm -f my-container         # 强制删除运行中的容器
docker rm -v my-container         # 同时删除匿名卷
docker rm $(docker ps -aq)        # 删除所有容器
8.4.4 docker exec(在容器中执行命令)
# 在运行中的容器中执行命令
docker exec my-container ls /app

# 交互式执行
docker exec -it my-container bash
docker exec -it my-container sh

# 以指定用户执行
docker exec -u root -it my-container bash
docker exec -u 1000 my-container whoami

# 设置环境变量
docker exec -e DEBUG=true my-container python app.py

# 在指定工作目录执行
docker exec -w /app my-container ls

# 后台执行
docker exec -d my-container touch /tmp/test
8.4.5 docker logs(查看日志)
# 查看容器日志
docker logs my-container

# 跟踪日志输出
docker logs -f my-container

# 显示时间戳
docker logs -t my-container

# 查看最后N行
docker logs --tail 100 my-container

# 查看指定时间后的日志
docker logs --since "2024-06-15" my-container
docker logs --since 30m my-container      # 最近30分钟
docker logs --since 1h my-container       # 最近1小时

# 查看指定时间段的日志
docker logs --since "2024-06-15T10:00:00" --until "2024-06-15T12:00:00" my-container

# 查看容器日志详情
docker inspect my-container --format '{{.LogPath}}'
8.4.6 docker stats(资源统计)
# 查看所有容器的资源使用
docker stats

# 查看指定容器
docker stats my-container

# 只输出一次
docker stats --no-stream

# 自定义格式
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}"

# JSON格式
docker stats --format "{{json .}}" my-container
8.4.7 docker top / docker port / docker diff
# 查看容器内运行的进程
docker top my-container
docker top my-container aux    # 使用aux格式

# 查看容器端口映射
docker port my-container
docker port my-container 80

# 查看容器文件系统变更
docker diff my-container
# A = Added, C = Changed, D = Deleted
8.4.8 docker cp(复制文件)
# 从容器复制文件到宿主机
docker cp my-container:/app/config.yml /host/path/config.yml

# 从宿主机复制文件到容器
docker cp /host/path/config.yml my-container:/app/config.yml

# 复制目录
docker cp my-container:/app/logs /host/path/logs

# 使用容器ID
docker cp abcd1234:/data/file.txt .

# 归档模式复制(保留权限)
docker cp -a my-container:/app /host/path/app
8.4.9 docker commit(提交容器为镜像)
# 将容器提交为镜像
docker commit my-container myapp:latest

# 添加提交信息
docker commit -m "Added custom config" -a "Author Name" my-container myapp:v1.0

# 修改启动命令
docker commit --change='CMD ["nginx", "-g", "daemon off;"]' my-container myapp:latest

# 修改暴露端口
docker commit --change='EXPOSE 8080' my-container myapp:latest

# 注意:docker commit不推荐在生产环境使用
# 推荐使用Dockerfile构建镜像,确保可重复性
8.4.10 docker export / docker import
# 导出容器文件系统为tar
docker export -o container-fs.tar my-container
docker export my-container > container-fs.tar

# 导入容器文件系统为镜像
docker import container-fs.tar myapp:latest

# 导入并设置启动命令
docker import -c "CMD ['nginx', '-g', 'daemon off;']" container-fs.tar myapp:latest

# 导入并设置暴露端口
docker import -c "EXPOSE 80" container-fs.tar myapp:latest

# 注意:docker export/import只导出文件系统,不包含镜像层历史
# docker save/load导出完整的镜像(包含层历史)
8.4.11 docker update / docker wait / docker rename
# 更新容器配置(资源限制等)
docker update --cpus=2 my-container
docker update --memory=1g my-container
docker update --restart=always my-container

# 等待容器停止并返回退出码
docker wait my-container

# 重命名容器
docker rename old-name new-name
8.4.12 docker inspect(查看容器详情)
# 查看容器详细信息
docker inspect my-container

# 查看特定信息
docker inspect --format '{{.State.Status}}' my-container
docker inspect --format '{{.State.Pid}}' my-container
docker inspect --format '{{.NetworkSettings.IPAddress}}' my-container
docker inspect --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-container
docker inspect --format '{{.Config.Image}}' my-container
docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' my-container
docker inspect --format '{{json .State}}' my-container

# 查看容器挂载点
docker inspect --format '{{json .Mounts}}' my-container

# 查看容器端口映射
docker inspect --format '{{json .NetworkSettings.Ports}}' my-container

# 查看容器健康状态
docker inspect --format '{{json .State.Health}}' my-container

8.5 网络命令(network create/ls/rm/inspect/connect/disconnect/prune)

# 列出所有网络
docker network ls

# 查看网络详情
docker network inspect bridge
docker network inspect my-network

# 创建网络
docker network create my-network
docker network create --driver bridge my-network           # 桥接网络
docker network create --driver overlay my-overlay          # 覆盖网络(Swarm)
docker network create --subnet=172.20.0.0/16 my-network    # 指定子网
docker network create --gateway=172.20.0.1 my-network      # 指定网关
docker network create --internal my-internal-network       # 内部网络(不能访问外网)
docker network create --attachable my-attachable-network   # 可附加的覆盖网络

# 连接容器到网络
docker network connect my-network my-container

# 断开容器与网络的连接
docker network disconnect my-network my-container

# 删除网络
docker network rm my-network

# 清理无用网络
docker network prune

# 创建网络并指定IP范围
docker network create \
    --subnet=172.20.0.0/16 \
    --ip-range=172.20.0.0/24 \
    --gateway=172.20.0.1 \
    my-network

# 创建带自定义DNS的网络
docker network create --aux-address="host1=172.20.0.10" my-network

8.6 数据卷命令(volume create/ls/rm/inspect/prune)

# 创建数据卷
docker volume create my-volume
docker volume create --driver local my-volume
docker volume create --driver local --opt type=nfs --opt device=:/data/nfs my-nfs-volume
docker volume create --driver local --opt type=ext4 --opt device=/dev/sdb1 my-block-volume

# 列出数据卷
docker volume ls
docker volume ls -q
docker volume ls --filter "dangling=true"

# 查看数据卷详情
docker volume inspect my-volume
docker volume inspect --format '{{.Mountpoint}}' my-volume

# 删除数据卷
docker volume rm my-volume

# 清理无用数据卷
docker volume prune
docker volume prune -a    # 删除所有未被使用的卷

# 使用数据卷
docker run -d -v my-volume:/data nginx:latest
docker run -d --mount source=my-volume,target=/data nginx:latest

# 创建NFS数据卷(共享存储)
docker volume create --driver local \
    --opt type=nfs \
    --opt o=addr=10.0.0.100,rw \
    --opt device=:/data/shared \
    nfs-volume

8.7 系统管理命令(system df/events/info/prune)

# 查看磁盘使用情况
docker system df
docker system df -v    # 详细信息

# 查看实时事件
docker system events
docker system events --filter type=container
docker system events --filter type=image
docker system events --filter type=network
docker system events --filter event=start
docker system events --filter event=die
docker system events --since "1h"    # 最近1小时的事件

# 系统信息
docker system info

# 清理资源
docker system prune                    # 清理已停止的容器、悬空网络、悬空镜像
docker system prune -a                 # 清理所有未使用的镜像
docker system prune -a --volumes       # 清理所有未使用的镜像和数据卷
docker system prune -f                 # 强制清理(不询问确认)

# 单独清理
docker container prune                 # 清理已停止的容器
docker image prune                     # 清理悬空镜像
docker image prune -a                  # 清理所有未使用的镜像
docker volume prune                    # 清理未使用的数据卷
docker network prune                   # 清理未使用的网络
docker builder prune                   # 清理构建缓存
docker builder prune -a               # 清理所有构建缓存

8.8 每个命令的参数详解与使用示例

8.8.1 docker run完整参数详解
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

# 常用参数分类:

# === 名称与标识 ===
--name string          # 容器名称
--hostname string      # 容器主机名
--domainname string    # 容器域名
--mac-address string   # MAC地址

# === 交互模式 ===
-i, --interactive      # 保持STDIN打开
-t, --tty              # 分配伪终端
-d, --detach           # 后台运行
-a, --attach           # 附加到STDIN/STDOUT/STDERR

# === 网络 ===
--network string       # 网络类型
--ip string            # IPv4地址
--ip6 string           # IPv6地址
-p, --publish          # 端口映射 host:container
-P, --publish-all      # 随机端口映射
--dns string           # DNS服务器
--add-host string      # 添加host记录
--expose               # 暴露端口

# === 存储 ===
-v, --volume           # 挂载卷 host:container[:options]
--mount                # 更详细的挂载配置
--tmpfs                # 挂载tmpfs
--read-only            # 只读文件系统

# === 环境变量 ===
-e, --env              # 环境变量
--env-file             # 环境变量文件

# === 资源限制 ===
--cpus                 # CPU核心数
--cpu-shares           # CPU权重
--cpuset-cpus          # 绑定CPU核心
--memory               # 内存限制
--memory-swap          # 交换空间限制
--pids-limit           # 进程数限制

# === 重启策略 ===
--restart              # 重启策略

# === 健康检查 ===
--health-cmd           # 健康检查命令
--health-interval      # 检查间隔
--health-retries       # 重试次数
--health-timeout       # 超时时间

# === 安全 ===
--user                 # 运行用户
--privileged           # 特权模式
--cap-add              # 添加Linux能力
--cap-drop             # 删除Linux能力
--security-opt         # 安全选项

# === 其他 ===
--rm                   # 退出后自动删除
--workdir              # 工作目录
--entrypoint           # 覆盖入口点
--label                # 标签
--log-driver           # 日志驱动
--platform             # 指定平台
8.8.2 实战综合示例
# 示例1:运行一个完整的Web应用
docker run -d \
    --name web-app \
    --hostname webapp \
    -p 8080:80 \
    -p 8443:443 \
    -v web-html:/usr/share/nginx/html:ro \
    -v web-logs:/var/log/nginx \
    -e NGINX_HOST=example.com \
    -e NGINX_PORT=80 \
    --network my-network \
    --ip 172.20.0.10 \
    --restart unless-stopped \
    --memory="512m" \
    --cpus="0.5" \
    --health-cmd="curl -f http://localhost/ || exit 1" \
    --health-interval=30s \
    --health-retries=3 \
    --log-driver json-file \
    --log-opt max-size=10m \
    --log-opt max-file=3 \
    --label environment=production \
    --label app=web \
    nginx:latest

# 示例2:运行MySQL数据库
docker run -d \
    --name mysql-db \
    -p 3306:3306 \
    -v mysql-data:/var/lib/mysql \
    -v mysql-conf:/etc/mysql/conf.d \
    -e MYSQL_ROOT_PASSWORD=StrongPass123! \
    -e MYSQL_DATABASE=myapp \
    -e MYSQL_USER=appuser \
    -e MYSQL_PASSWORD=AppPass456 \
    --restart unless-stopped \
    --memory="2g" \
    --cpus="1.0" \
    --health-cmd="mysqladmin ping -h localhost -u root -pStrongPass123!" \
    --health-interval=10s \
    --health-retries=5 \
    mysql:8.0

# 示例3:运行Redis缓存
docker run -d \
    --name redis-cache \
    -p 6379:6379 \
    -v redis-data:/data \
    -e REDIS_PASSWORD=RedisPass789 \
    --restart unless-stopped \
    --memory="1g" \
    --memory-swap="1g" \
    --cpus="0.5" \
    redis:7-alpine \
    redis-server --requirepass RedisPass789 --maxmemory 512mb --maxmemory-policy allkeys-lru

# 示例4:运行开发环境
docker run -it \
    --name dev-env \
    -v $(pwd):/workspace \
    -v ~/.ssh:/root/.ssh:ro \
    -v ~/.gitconfig:/root/.gitconfig:ro \
    -p 3000:3000 \
    -p 8080:8080 \
    --network host \
    -e TERM=xterm-256color \
    --cap-add SYS_PTRACE \
    --security-opt seccomp=unconfined \
    node:20 bash

第九章 Docker图形化管理工具

虽然Docker CLI功能强大,但对于初学者或需要管理大量容器的场景,图形化管理工具能极大提升效率。本章将介绍几款主流的Docker图形化管理工具。

在实际工作中,面对数十甚至上百个容器,仅靠命令行工具进行管理往往效率低下且容易出错。图形化管理工具通过可视化的方式展示容器状态、资源使用情况、网络拓扑等信息,使得管理员可以更直观地了解和掌控整个Docker环境。此外,图形化工具通常还提供了一键部署、批量操作、实时监控等高级功能,能够显著提升运维效率。

选择图形化管理工具时,需要考虑以下几个因素:工具的部署方式和资源开销、功能是否满足需求、是否支持远程管理多台Docker主机、是否支持集群管理、社区活跃度和更新频率、以及是否开源免费等。不同的使用场景适合不同的工具,本章将对主流工具进行详细对比,帮助你做出合适的选择。

9.1 Portainer安装与使用(完整教程)

Portainer是最流行的Docker图形化管理工具,提供Web界面来管理容器、镜像、网络、数据卷等Docker资源。

9.1.1 安装Portainer CE(社区版)
# 创建Portainer数据卷
docker volume create portainer_data

# 运行Portainer容器
docker run -d \
    --name portainer \
    -p 9443:9443 \
    -p 9000:9000 \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v portainer_data:/data \
    --restart=always \
    portainer/portainer-ce:latest

# 验证Portainer是否运行
docker ps | grep portainer

# 查看Portainer日志
docker logs portainer
9.1.2 使用Docker Compose安装Portainer
# portainer-compose.yml
version: '3.8'

services:
  portainer:
    image: portainer/portainer-ce:latest
    container_name: portainer
    ports:
      - "9443:9443"
      - "9000:9000"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data
    restart: always

volumes:
  portainer_data:
# 启动Portainer
docker compose -f portainer-compose.yml up -d

# 停止Portainer
docker compose -f portainer-compose.yml down
9.1.3 Portainer初始配置
  1. 打开浏览器访问 https://localhost:9443(首次访问会有证书警告,点击继续即可)
  2. 创建管理员账户(设置用户名和密码,密码至少12位)
  3. 选择Docker环境:选择"Get Started"使用本地Docker环境
  4. 进入管理界面后可以看到:
    • Dashboard:概览面板,显示容器、镜像、卷、网络数量
    • Containers:容器管理(启动、停止、删除、查看日志等)
    • Images:镜像管理(拉取、删除、构建)
    • Volumes:数据卷管理
    • Networks:网络管理
    • Stacks:Docker Compose应用管理
    • Events:Docker事件日志
9.1.4 Portainer常用操作
# 通过Portainer管理远程Docker主机
# 1. 在远程主机上配置Docker API
# 编辑 /etc/docker/daemon.json
{
  "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"]
}

# 2. 或使用TLS加密连接
# 生成证书
openssl genrsa -aes256 -out ca-key.pem 4096
openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
# ...(生成server和client证书)

# 3. 在Portainer中添加远程环境
# Environments -> Add Environment -> Docker Standalone
# 填入远程主机IP和端口
# Portainer管理Docker Swarm集群
# 1. 在Swarm管理节点上部署Portainer
docker service create \
    --name portainer \
    --publish 9443:9443 \
    --publish 9000:9000 \
    --constraint 'node.role == manager' \
    --mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
    --mount type=volume,src=portainer_data,dst=/data \
    portainer/portainer-ce:latest

# 2. 在Portainer中选择Swarm环境
9.1.5 Portainer高级功能
# 使用Portainer Templates快速部署应用
# Settings -> App Templates -> 添加自定义模板

# 示例:添加自定义模板
# Name: MySQL 8.0
# Description: MySQL 8.0 Database
# Docker Compose:
version: '3.8'
services:
  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: "{{ .Values.root_password }}"
    volumes:
      - mysql-data:/var/lib/mysql
    ports:
      - "3306:3306"
volumes:
  mysql-data:

9.2 Docker Desktop图形界面

Docker Desktop自带图形界面(Docker Dashboard),适合Windows和macOS用户。

9.2.1 Docker Dashboard功能
Docker Dashboard主要功能:
├── Containers(容器管理)
│   ├── 查看运行状态
│   ├── 启动/停止/删除容器
│   ├── 查看容器日志
│   ├── 进入容器终端
│   └── 查看容器详情
├── Images(镜像管理)
│   ├── 查看本地镜像
│   ├── 拉取镜像
│   ├── 删除镜像
│   ├── 运行镜像
│   └── 查看镜像详情
├── Volumes(数据卷管理)
│   ├── 查看数据卷
│   ├── 删除数据卷
│   └── 查看数据卷使用情况
├── Builds(构建管理)
│   ├── 查看构建历史
│   └── 取消正在进行的构建
├── Compose(应用管理)
│   ├── 管理Docker Compose应用
│   ├── 启动/停止应用
│   └── 查看应用日志
└── Settings(设置)
    ├── Docker Engine配置
    ├── 资源分配
    ├── 网络配置
    └── Kubernetes配置
9.2.2 Docker Desktop Dev Environments
# Docker Desktop的Dev Environments功能
# 可以创建隔离的开发环境

# 1. 创建开发环境
# Dashboard -> Dev Environments -> Create
# 选择Git仓库或本地目录

# 2. 在开发环境中工作
# Dashboard -> Dev Environments -> 选择环境 -> Open in VS Code

# 3. 使用CLI管理开发环境
docker dev create --name my-dev-env
docker dev list
docker dev start my-dev-env
docker dev stop my-dev-env
docker dev delete my-dev-env

9.3 Lazydocker命令行UI工具

Lazydocker是一个终端UI工具,提供类似图形界面的操作体验,但运行在终端中。

9.3.1 安装Lazydocker
# macOS安装
brew install lazydocker

# Linux安装
LAZYDOCKER_VERSION=0.23.3
curl -fsSL https://github.com/jesseduffield/lazydocker/releases/download/v${LAZYDOCKER_VERSION}/lazydocker_${LAZYDOCKER_VERSION}_Linux_x86_64.tar.gz \
    -o /tmp/lazydocker.tar.gz
tar -xzf /tmp/lazydocker.tar.gz -C /tmp
sudo mv /tmp/lazydocker /usr/local/bin/

# Windows安装(使用Scoop)
scoop install lazydocker

# 使用Go安装
go install github.com/jesseduffield/lazydocker@latest
9.3.2 Lazydocker使用
# 启动Lazydocker
lazydocker

# 常用快捷键:
# x     - 菜单
# [     - 上一个Tab
# ]     - 下一个Tab
# enter - 进入详情
# b     - 批量操作
# d     - 删除
# e     - 编辑(配置文件、Dockerfile等)
# s     - 停止
# r     - 重启
# t     - 日志跟踪
# c     - 容器配置
# m     - 查看内存/CPU使用

# 配置文件
# 位置: ~/.config/lazydocker/config.yml
gui:
  showIcons: true
  theme:
    activeBorderColor:
      - green
      - bold
    inactiveBorderColor:
      - white
reporting: 'off'

9.4 cAdvisor监控面板

cAdvisor(Container Advisor)是Google开源的容器监控工具,提供容器资源使用和性能特征的实时数据。

9.4.1 安装cAdvisor
# 运行cAdvisor容器
docker run -d \
    --name cadvisor \
    --volume=/:/rootfs:ro \
    --volume=/var/run:/var/run:ro \
    --volume=/sys:/sys:ro \
    --volume=/var/lib/docker/:/var/lib/docker:ro \
    --volume=/dev/disk/:/dev/disk:ro \
    --publish=8080:8080 \
    --detach=true \
    --privileged \
    --device=/dev/kmsg \
    --restart=always \
    google/cadvisor:latest

# 访问cAdvisor Web界面
# http://localhost:8080
9.4.2 cAdvisor功能
cAdvisor监控指标:
├── CPU使用率
│   ├── 总CPU使用
│   ├── 每核心使用
│   └── CPU负载
├── 内存使用
│   ├── 已用内存
│   ├── 缓存
│   └── RSS
├── 网络IO
│   ├── 接收字节数
│   ├── 发送字节数
│   └── 网络错误
├── 磁盘IO
│   ├── 读取字节数
│   ├── 写入字节数
│   └── IO操作数
├── 文件系统
│   ├── 已用空间
│   ├── 可用空间
│   └── inode使用
└── 进程信息
    ├── 进程列表
    └── 进程资源使用
9.4.3 cAdvisor + Prometheus + Grafana监控方案
# monitoring-compose.yml
version: '3.8'

services:
  cadvisor:
    image: google/cadvisor:latest
    container_name: cadvisor
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
      - /dev/disk/:/dev/disk:ro
    ports:
      - "8080:8080"
    privileged: true
    restart: always

  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus-data:/prometheus
    ports:
      - "9090:9090"
    restart: always

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    volumes:
      - grafana-data:/var/lib/grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    restart: always

volumes:
  prometheus-data:
  grafana-data:
# prometheus.yml
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'cadvisor'
    static_configs:
      - targets: ['cadvisor:8080']

  - job_name: 'docker'
    static_configs:
      - targets: ['host.docker.internal:9323']
# 启动监控方案
docker compose -f monitoring-compose.yml up -d

# 访问各服务:
# cAdvisor: http://localhost:8080
# Prometheus: http://localhost:9090
# Grafana: http://localhost:3000 (admin/admin)

# 在Grafana中导入cAdvisor仪表盘
# Dashboards -> Import -> ID: 193 (或搜索cAdvisor)

9.5 Rancher容器管理平台简介

Rancher是SUSE开源的企业级容器管理平台,支持管理Kubernetes和Docker Swarm集群。

# 安装Rancher
docker run -d \
    --name rancher \
    --restart=unless-stopped \
    -p 8080:80 \
    -p 8443:443 \
    --privileged \
    rancher/rancher:latest

# 访问Rancher
# https://localhost:8443

# 获取初始密码
docker logs rancher 2>&1 | grep "Bootstrap Password:"

Rancher的主要功能:

  • 多集群Kubernetes管理
  • 应用商店(Catalog)
  • 监控和告警
  • 日志收集
  • 用户和权限管理
  • 负载均衡管理
  • 持久化存储管理

9.6 各管理工具对比表

工具 类型 界面 资源占用 功能丰富度 适合场景
Portainer Web UI 浏览器 个人/小团队
Docker Desktop 桌面应用 GUI Windows/macOS开发
Lazydocker 终端UI TUI 终端用户/SSH连接
cAdvisor 监控面板 浏览器 低(专注监控) 容器监控
Rancher 管理平台 浏览器 极高 企业级K8s管理
Dry 终端UI TUI 快速查看容器
Dockge Web UI 浏览器 Docker Compose管理
# 安装Dry(轻量级终端UI工具)
go install github.com/moncho/dry@latest

# 安装Dockge(Docker Compose管理工具)
docker run -d \
    --name dockge \
    -p 5001:5001 \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v /opt/stacks:/opt/stacks \
    -v dockge-data:/app/data \
    --restart=always \
    louislam/dockge:latest

选择建议:

  • 个人开发/学习:Docker Desktop 或 Portainer
  • 服务器管理:Portainer
  • 终端操作:Lazydocker
  • 容器监控:cAdvisor + Grafana
  • 企业级管理:Rancher
  • Docker Compose管理:Dockge

第十章 常见问题排查与最佳实践

在本章中,我们将汇总Docker安装和使用过程中最常见的错误及其解决方案,并提供Docker环境配置的最佳实践清单。

无论你多么仔细地按照教程操作,在实际使用Docker的过程中总会遇到各种各样的问题。这些问题可能源于操作系统差异、网络环境限制、配置错误、资源不足等多种原因。对于初学者来说,遇到问题时往往不知所措,不知道从何入手排查。而对于有经验的工程师来说,一套系统化的问题排查方法论能够帮助他们快速定位和解决问题。

本章的内容组织遵循"问题现象 -> 原因分析 -> 解决方案 -> 预防措施"的模式。对于每个常见问题,我们都会首先描述问题的典型表现(即错误信息),然后分析导致问题的可能原因,接着给出具体的解决步骤和命令,最后提供预防该问题再次发生的建议。这种结构化的排查方法不仅适用于本章列出的具体问题,也可以作为一种通用的故障排查思路应用到其他Docker问题中。

除了问题排查之外,本章还提供了大量的最佳实践建议。这些最佳实践来自于生产环境的实际经验积累,涵盖了安全、性能、运维和开发四个方面。遵循这些最佳实践可以帮助你构建一个更加稳定、高效、安全的Docker环境,减少日常运维中的问题发生频率。

10.1 安装常见错误汇总与解决方案

10.1.1 无法连接到Docker守护进程
# 错误信息:
# Cannot connect to the Docker daemon at unix:///var/run/docker.sock. 
# Is the docker daemon running?

# 排查步骤:

# 1. 检查Docker服务状态
sudo systemctl status docker

# 2. 如果未运行,启动Docker
sudo systemctl start docker

# 3. 检查Docker socket文件
ls -la /var/run/docker.sock

# 4. 检查用户是否在docker组中
groups $USER

# 5. 如果不在docker组中,添加用户
sudo usermod -aG docker $USER
newgrp docker

# 6. 检查Docker日志
sudo journalctl -u docker --no-pager | tail -50

# 7. 检查Docker配置文件语法
sudo dockerd --validate
10.1.2 镜像拉取失败
# 错误信息:
# Error response from daemon: Get "https://registry-1.docker.io/v2/": 
# dial tcp: lookup registry-1.docker.io: no such host
# 或
# net/http: request canceled (Client.Timeout exceeded while awaiting headers)

# 排查步骤:

# 1. 检查网络连通性
ping registry-1.docker.io
curl -v https://registry-1.docker.io/v2/

# 2. 检查DNS配置
cat /etc/resolv.conf
nslookup registry-1.docker.io

# 3. 配置DNS
# 编辑 /etc/docker/daemon.json
{
  "dns": ["8.8.8.8", "114.114.114.114"]
}

# 4. 配置镜像加速器
{
  "registry-mirrors": [
    "https://xxxxxxxx.mirror.aliyuncs.com",
    "https://docker.mirrors.ustc.edu.cn"
  ]
}

# 5. 配置代理(如果需要)
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf <<EOF
[Service]
Environment="HTTP_PROXY=http://proxy:8080"
Environment="HTTPS_PROXY=http://proxy:8080"
Environment="NO_PROXY=localhost,127.0.0.1"
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

# 6. 重启Docker
sudo systemctl restart docker
10.1.3 端口已被占用
# 错误信息:
# Bind for 0.0.0.0:80 failed: port is already allocated

# 排查步骤:

# Linux:
# 查看占用端口的进程
sudo lsof -i :80
sudo netstat -tlnp | grep :80
sudo ss -tlnp | grep :80

# 终止占用端口的进程
sudo kill -9 $(sudo lsof -t -i :80)

# 或修改Docker容器端口映射
docker run -p 8081:80 nginx:latest

# Windows:
netstat -ano | findstr :80
taskkill /PID <PID> /F

# macOS:
lsof -i :80
kill -9 <PID>
10.1.4 权限被拒绝
# 错误信息:
# permission denied while trying to connect to the Docker daemon socket

# 解决方案:

# 方法1:使用sudo
sudo docker ps

# 方法2:将用户加入docker组(推荐)
sudo usermod -aG docker $USER
newgrp docker

# 方法3:修改socket权限(不推荐)
sudo chmod 666 /var/run/docker.sock

# 方法4:使用Rootless模式
# 安装rootlesskit
sudo apt-get install -y uidmap
dockerd-rootless-setuptool.sh install
systemctl --user enable --now docker
10.1.5 Docker服务启动失败
# 错误信息:
# Job for docker.service failed because the control process exited with error code

# 排查步骤:

# 1. 查看详细错误日志
sudo journalctl -u docker --no-pager | tail -50

# 2. 常见原因及解决方案

# 原因1: daemon.json配置错误
# 验证JSON语法
python3 -c "import json; json.load(open('/etc/docker/daemon.json'))"

# 原因2: 存储驱动不兼容
# 检查文件系统
df -T /var/lib/docker
# 修改存储驱动为overlay2
{
  "storage-driver": "overlay2"
}

# 原因3: iptables问题
sudo iptables -F
sudo systemctl restart docker

# 原因4: containerd问题
sudo systemctl restart containerd
sudo systemctl restart docker

# 原因5: 配置冲突
# 检查是否有重复配置
cat /etc/docker/daemon.json
cat /etc/systemd/system/docker.service.d/*.conf

# 3. 调试模式启动
sudo dockerd --debug

# 4. 重置Docker配置(最后手段)
sudo mv /etc/docker/daemon.json /etc/docker/daemon.json.bak
sudo systemctl restart docker

10.2 Docker服务无法启动排查

# 完整的Docker服务排查流程

# 步骤1: 检查Docker服务状态
sudo systemctl status docker

# 步骤2: 查看Docker日志
sudo journalctl -u docker -n 100 --no-pager

# 步骤3: 检查Docker进程
ps aux | grep dockerd

# 步骤4: 检查Docker socket
ls -la /var/run/docker.sock
file /var/run/docker.sock

# 步骤5: 检查containerd
sudo systemctl status containerd
sudo journalctl -u containerd -n 50 --no-pager

# 步骤6: 检查内核模块
lsmod | grep -E "overlay|br_netfilter"
sudo modprobe overlay
sudo modprobe br_netfilter

# 步骤7: 检查cgroup
mount | grep cgroup
cat /proc/cgroups

# 步骤8: 检查磁盘空间
df -h
df -i

# 步骤9: 检查内存
free -h

# 步骤10: 手动启动dockerd查看错误
sudo dockerd --debug 2>&1 | head -50

# 步骤11: 检查daemon.json语法
python3 -c "import json; json.load(open('/etc/docker/daemon.json'))"

# 步骤12: 恢复默认配置
sudo cp /etc/docker/daemon.json /etc/docker/daemon.json.bak
echo '{}' | sudo tee /etc/docker/daemon.json
sudo systemctl restart docker

10.3 权限问题解决

# Docker权限相关问题的完整解决方案

# 问题1: docker命令需要sudo
# 原因: 当前用户不在docker组中
sudo usermod -aG docker $USER
newgrp docker

# 问题2: 容器内无法访问挂载的文件
# 原因: 宿主机和容器的UID/GID不匹配
# 解决方案1: 在容器中使用正确的UID
docker run -u $(id -u):$(id -g) -v /host/data:/data alpine ls /data

# 解决方案2: 使用userns-remap
# 编辑 /etc/docker/daemon.json
{
  "userns-remap": "default"
}

# 问题3: Docker数据目录权限错误
sudo chown -R root:root /var/lib/docker
sudo chmod -R 755 /var/lib/docker

# 问题4: SELinux阻止Docker操作
# 查看SELinux状态
getenforce
# 临时设置为permissive模式
sudo setenforce 0
# 永久设置
sudo vi /etc/selinux/config
# SELINUX=permissive

# 问题5: AppArmor阻止容器运行
sudo aa-status
sudo systemctl stop apparmor
sudo systemctl disable apparmor

10.4 磁盘空间不足处理

# 检查磁盘使用情况
docker system df -v

# 步骤1: 清理停止的容器
docker container prune -f

# 步骤2: 清理悬空镜像
docker image prune -f

# 步骤3: 清理所有未使用的镜像
docker image prune -a -f

# 步骤4: 清理未使用的网络
docker network prune -f

# 步骤5: 清理未使用的数据卷(谨慎操作!)
docker volume prune -f

# 步骤6: 清理构建缓存
docker builder prune -a -f

# 步骤7: 一键清理所有无用资源
docker system prune -a --volumes -f

# 步骤8: 清理容器日志文件
# 查看容器日志文件位置
docker inspect --format '{{.LogPath}}' $(docker ps -aq)

# 清空日志文件
sudo sh -c 'truncate -s 0 /var/lib/docker/containers/*/*-json.log'

# 步骤9: 设置日志大小限制(防止日志占满磁盘)
# 编辑 /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

# 步骤10: 迁移Docker数据目录到更大的磁盘
# 参考7.2节

# 步骤11: 查找大文件
sudo find /var/lib/docker -type f -size +100M -exec ls -lh {} \;

10.5 网络连接问题排查

# Docker网络问题排查流程

# 问题1: 容器无法访问外网
# 排查:
docker exec -it my-container ping 8.8.8.8
docker exec -it my-container nslookup google.com

# 解决方案:
# 检查IP转发
sysctl net.ipv4.ip_forward
# 如果为0,设置为1
sudo sysctl -w net.ipv4.ip_forward=1

# 检查iptables
sudo iptables -t nat -L -n -v
sudo iptables -L DOCKER -n -v

# 重启Docker网络
sudo systemctl restart docker

# 问题2: 容器之间无法通信
# 排查:
docker network inspect bridge
docker exec -it container1 ping container2

# 解决方案:
# 检查icc设置
docker info | grep "Inter Container Communication"
# 确保icc为true

# 将容器放在同一网络中
docker network create my-net
docker network connect my-net container1
docker network connect my-net container2

# 问题3: 外部无法访问容器端口
# 排查:
docker port my-container
curl http://localhost:<端口>

# 解决方案:
# 检查端口映射
docker inspect my-container | grep -A 10 PortBindings

# 检查防火墙
sudo ufw status
sudo firewall-cmd --list-all

# 检查iptables
sudo iptables -t nat -L -n | grep <端口>

# 问题4: DNS解析失败
# 排查:
docker exec -it my-container cat /etc/resolv.conf

# 解决方案:
# 在daemon.json中配置DNS
{
  "dns": ["8.8.8.8", "114.114.114.114"]
}

# 或在docker run时指定
docker run --dns 8.8.8.8 nginx:latest

# 问题5: 容器IP冲突
# 排查:
docker network inspect bridge | grep -A 5 IPAM

# 解决方案:
# 修改默认网桥IP段
{
  "bip": "10.200.0.1/24"
}

10.6 Docker环境配置最佳实践清单

10.6.1 安全最佳实践
// 安全配置清单
{
  "userns-remap": "default",           // 用户命名空间重映射
  "no-new-privileges": true,           // 禁止提权
  "live-restore": true,                // 守护进程重启不影响容器
  "userland-proxy": false,             // 禁用用户态代理
  "seccomp-profile": "",               // 使用默认seccomp配置
  "icc": false                         // 禁止默认容器间通信(按需开放)
}
# 容器安全最佳实践
# 1. 不使用特权模式
# 避免: --privileged
# 使用: --cap-add=NET_ADMIN(只添加需要的能力)

# 2. 以非root用户运行
docker run --user 1000:1000 nginx:latest

# 3. 只读文件系统
docker run --read-only --tmpfs /tmp nginx:latest

# 4. 限制资源
docker run --memory="512m" --cpus="1.0" --pids-limit=100 nginx:latest

# 5. 使用安全选项
docker run \
    --security-opt no-new-privileges \
    --security-opt apparmor=docker-default \
    --cap-drop ALL \
    --cap-add NET_BIND_SERVICE \
    nginx:latest
10.6.2 性能最佳实践
// 性能配置清单
{
  "storage-driver": "overlay2",         // 最佳存储驱动
  "features": {
    "buildkit": true                    // 启用BuildKit
  },
  "max-concurrent-downloads": 10,       // 并行下载
  "max-concurrent-uploads": 5,          // 并行上传
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "50m",                  // 日志大小限制
    "max-file": "5"
  },
  "builder": {
    "gc": {
      "enabled": true,                  // 自动清理构建缓存
      "defaultKeepStorage": "20GB"
    }
  }
}
# 容器性能最佳实践
# 1. 使用alpine或slim基础镜像
docker pull alpine:latest       # ~5MB
docker pull nginx:alpine        # ~40MB

# 2. 多阶段构建减小镜像大小
# Dockerfile
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html

# 3. 合并RUN指令减少镜像层
RUN apt-get update && \
    apt-get install -y curl git && \
    rm -rf /var/lib/apt/lists/*

# 4. 使用.dockerignore
# .dockerignore
node_modules
.git
*.log
.env

# 5. 合理设置健康检查
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
    CMD curl -f http://localhost/ || exit 1
10.6.3 运维最佳实践
# 1. 配置日志轮转
# daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "50m",
    "max-file": "5"
  }
}

# 2. 定期清理任务(crontab)
# 编辑 crontab
sudo crontab -e

# 每周日凌晨2点清理Docker无用资源
0 2 * * 0 docker system prune -a --volumes -f >> /var/log/docker-prune.log 2>&1

# 3. 监控Docker状态
# 创建监控脚本
#!/bin/bash
# docker-health-check.sh
echo "=== Docker Health Check ==="
echo "Time: $(date)"
echo ""
echo "Docker Status:"
systemctl is-active docker
echo ""
echo "Container Status:"
docker ps --format "table {{.Names}}\t{{.Status}}"
echo ""
echo "Disk Usage:"
docker system df
echo ""
echo "Running Containers: $(docker ps -q | wc -l)"
echo "Total Containers: $(docker ps -aq | wc -l)"
echo "Total Images: $(docker images -q | wc -l)"

# 4. 备份策略
#!/bin/bash
# docker-backup.sh
BACKUP_DIR=/backup/docker/$(date +%Y%m%d)
mkdir -p $BACKUP_DIR

# 备份配置文件
cp /etc/docker/daemon.json $BACKUP_DIR/
cp /etc/containerd/config.toml $BACKUP_DIR/

# 备份数据卷
for volume in $(docker volume ls -q); do
    docker run --rm -v ${volume}:/data -v $BACKUP_DIR:/backup alpine \
        tar czf /backup/${volume}.tar.gz -C /data .
done

# 保留最近7天的备份
find /backup/docker/ -type d -mtime +7 -exec rm -rf {} \;

# 5. 使用Docker Compose管理多容器应用
# docker-compose.yml
version: '3.8'
services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    depends_on:
      - app
    restart: unless-stopped
    
  app:
    image: myapp:latest
    environment:
      - DB_HOST=db
    depends_on:
      - db
    restart: unless-stopped
    
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
    volumes:
      - db-data:/var/lib/mysql
    restart: unless-stopped

volumes:
  db-data:
10.6.4 开发环境最佳实践
# 1. 使用Docker Compose开发
# docker-compose.dev.yml
version: '3.8'
services:
  app:
    build: 
      context: .
      dockerfile: Dockerfile.dev
    volumes:
      - .:/app              # 挂载源代码
      - /app/node_modules   # 匿名卷避免覆盖
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=development
      - CHOKIDAR_USEPOLLING=true  # 文件监听(WSL 2需要)
    command: npm run dev

# 2. 使用多阶段Dockerfile
# Dockerfile
FROM node:20-alpine AS development
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]

FROM development AS builder
RUN npm run build

FROM nginx:alpine AS production
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

# 3. 使用.dockerignore
# .dockerignore
.git
.gitignore
node_modules
npm-debug.log
Dockerfile
docker-compose.yml
.dockerignore
.env
*.md
test
coverage

10.7 本章总结与下一期预告

本章总结

本章汇总了Docker使用过程中最常见的问题及其解决方案,包括:

  • Docker守护进程连接问题
  • 镜像拉取失败问题
  • 端口冲突问题
  • 权限问题
  • 服务启动失败问题
  • 磁盘空间不足问题
  • 网络连接问题

同时提供了安全、性能和运维三个方面的最佳实践清单,帮助你构建稳定、高效、安全的Docker环境。

常见问题快速解决参考表:

问题 快速解决命令
Docker无法连接 sudo systemctl restart docker
权限拒绝 sudo usermod -aG docker $USER && newgrp docker
镜像拉取慢 配置registry-mirrors
端口冲突 lsof -i :端口号 查找并终止
磁盘不足 docker system prune -a --volumes -f
容器无法联网 sysctl -w net.ipv4.ip_forward=1
日志过大 配置log-opts限制大小

总结

本文系统地讲解了Docker在Windows、macOS和Linux三大平台上的安装方法与环境配置,涵盖了从安装前准备、平台安装、版本管理、镜像加速、核心配置、命令大全到图形化管理工具的完整知识体系。

核心要点回顾:

  1. 安装前准备:评估系统要求、规划硬件资源、启用BIOS虚拟化、检查内核版本、卸载旧版本、配置网络环境,这些准备工作是成功安装Docker的前提。

  2. Linux安装:掌握apt(Ubuntu/Debian)和yum(CentOS/RHEL)两种安装方式,了解官方脚本安装和二进制安装方法,学会验证安装结果和配置开机自启。

  3. Windows安装:理解WSL 2后端的优势,掌握Docker Desktop的安装和配置,学会资源分配、文件共享和常见问题排查。

  4. macOS安装:了解Intel和Apple Silicon的差异,掌握Homebrew安装方式,学会使用Colima等轻量级替代方案。

  5. 版本管理:理解Docker CE/EE的区别、版本号规则和发布通道,掌握版本选择策略和升级回滚方法。

  6. 镜像加速:理解镜像加速原理,掌握多镜像源配置和故障转移,了解企业级私有镜像代理搭建。

  7. 核心配置:深入理解daemon.json的每个配置项,掌握数据目录、日志、网络、存储驱动、安全和资源限制的配置方法。

  8. 命令大全:系统掌握Docker的系统信息、镜像、容器、网络、数据卷和系统管理命令,理解每个命令的参数和用法。

  9. 管理工具:了解Portainer、Docker Desktop、Lazydocker、cAdvisor和Rancher等图形化管理工具的特点和适用场景。

  10. 问题排查:掌握常见问题的排查方法和解决方案,建立安全、性能和运维的最佳实践意识。

Docker的安装与配置是容器化之旅的第一步。通过本文的学习,你应该已经具备了在不同平台上安装和配置Docker的能力。在实际使用中,建议根据具体场景选择合适的配置方案,并持续关注Docker的版本更新和安全公告。

本文涉及的命令和配置均在Docker 27.x版本上验证通过。由于Docker版本更新较快,部分命令和配置可能在新版本中有所变化,请以官方文档为准。

官方文档地址:https://docs.docker.com/

附录A:Docker网络模式详解

Docker提供了多种网络模式,理解每种模式的特点和适用场景对于正确配置容器网络至关重要。

A.1 Bridge网络模式(默认)

Bridge模式是Docker的默认网络模式。在这种模式下,Docker会在宿主机上创建一个名为docker0的虚拟网桥,所有使用Bridge模式的容器都会连接到这个网桥上。

# 查看默认的bridge网络
docker network inspect bridge

# 创建自定义bridge网络
docker network create --driver bridge \
    --subnet 172.20.0.0/16 \
    --gateway 172.20.0.1 \
    my-bridge-network

# 使用自定义bridge网络运行容器
docker run -d --network my-bridge-network --name app1 nginx:latest
docker run -d --network my-bridge-network --name app2 nginx:latest

# 在自定义bridge网络中,容器可以通过名称互相访问
docker exec app1 ping app2

Bridge模式的特点:

  • 容器通过NAT(网络地址转换)访问外部网络
  • 外部网络通过端口映射访问容器
  • 自定义bridge网络支持容器间通过名称互相通信(DNS解析)
  • 默认bridge网络不支持自动DNS解析(需使用–link,已不推荐)

A.2 Host网络模式

Host模式下,容器直接使用宿主机的网络栈,没有网络隔离。容器的网络配置与宿主机完全相同。

# 使用host网络模式运行容器
docker run -d --network host --name my-nginx nginx:latest

# 在host模式下,容器直接使用宿主机的端口
# 不需要-p参数进行端口映射
# 容器内的80端口直接映射到宿主机的80端口

Host模式的特点:

  • 网络性能最佳(没有NAT和网桥的开销)
  • 没有网络隔离(容器可以看到宿主机的所有网络接口)
  • 端口冲突风险(容器和宿主机不能使用相同端口)
  • 适合对网络性能要求极高的场景

A.3 None网络模式

None模式下,容器没有网络接口(只有lo回环接口),完全隔离于外部网络。

# 使用none网络模式运行容器
docker run -d --network none --name isolated-app alpine:latest

# 验证容器没有网络
docker exec isolated-app ip addr
# 只有lo接口

None模式的特点:

  • 完全的网络隔离
  • 适合不需要网络的安全敏感应用
  • 可以通过docker exec在容器内执行命令

A.4 Container网络模式

Container模式下,新容器与另一个已存在的容器共享网络栈。

# 创建第一个容器
docker run -d --name web-server -p 8080:80 nginx:latest

# 创建第二个容器,与第一个容器共享网络
docker run -d --name sidecar --network container:web-server alpine:latest

# 第二个容器可以通过localhost访问第一个容器的服务
docker exec sidecar curl http://localhost:80

Container模式的特点:

  • 多个容器共享同一个网络命名空间
  • 容器之间通过localhost互相通信
  • 适合Sidecar模式的微服务架构

A.5 Overlay网络模式

Overlay模式用于Docker Swarm集群中,允许不同宿主机上的容器互相通信。

# 在Swarm集群中创建overlay网络
docker network create --driver overlay --attachable my-overlay-net

# 在overlay网络中运行服务
docker service create --name my-service --network my-overlay-net nginx:latest

A.6 Macvlan网络模式

Macvlan模式为容器分配真实的MAC地址,使容器在网络上表现为独立的物理设备。

# 创建macvlan网络
docker network create -d macvlan \
    --subnet=192.168.1.0/24 \
    --gateway=192.168.1.1 \
    -o parent=eth0 \
    my-macvlan-net

# 使用macvlan网络运行容器
docker run -d --network my-macvlan-net --ip=192.168.1.100 nginx:latest

Macvlan模式的特点:

  • 容器获得独立的MAC地址和IP地址
  • 网络性能接近物理机
  • 适合需要直接接入物理网络的场景
  • 需要交换机支持promiscuous mode

附录B:Docker数据持久化方案对比

Docker提供了多种数据持久化方案,选择合适的方案对于保证数据安全和应用可靠性至关重要。

B.1 数据持久化方案对比表

方案 存储位置 性能 可移植性 适用场景
Bind Mount(绑定挂载) 宿主机指定路径 好(本地文件系统) 差(依赖宿主机路径) 开发环境、配置文件
Volume(命名卷) Docker管理目录 好(Docker管理) 生产环境、数据持久化
tmpfs Mount 内存 极快 不可持久化 敏感数据、临时文件
NFS Volume NFS服务器 取决于网络 好(网络共享) 多主机共享数据

B.2 选择建议

开发环境:使用Bind Mount,方便直接编辑宿主机上的文件。

# 开发环境:挂载源代码到容器
docker run -d \
    -v /home/user/project:/app \
    -p 3000:3000 \
    node:20 npm run dev

生产环境:使用命名Volume,由Docker统一管理。

# 生产环境:使用命名卷存储数据
docker run -d \
    -v mysql-data:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=password \
    mysql:8.0

多主机共享:使用NFS Volume或分布式存储。

# 创建NFS卷
docker volume create \
    --driver local \
    --opt type=nfs \
    --opt o=addr=10.0.0.100,rw \
    --opt device=:/data/shared \
    shared-data

# 使用NFS卷
docker run -d -v shared-data:/data nginx:latest

临时数据:使用tmpfs,数据存储在内存中,容器停止后消失。

# 使用tmpfs存储临时数据
docker run -d \
    --tmpfs /tmp:rw,size=100m \
    --tmpfs /run \
    nginx:latest

附录C:Docker安全检查清单

在将Docker部署到生产环境之前,建议按照以下清单进行安全检查:

C.1 镜像安全

  • 使用可信的基础镜像(官方镜像或经过审计的私有镜像)
  • 定期更新基础镜像以修复安全漏洞
  • 使用镜像扫描工具(如Trivy、Clair)检查已知漏洞
  • 不在镜像中硬编码敏感信息(密码、密钥等)
  • 使用多阶段构建减小镜像体积,减少攻击面
  • 使用.dockerignore排除敏感文件

C.2 容器运行安全

  • 以非root用户运行容器
  • 不使用–privileged特权模式
  • 使用–cap-drop ALL并只添加必要的能力
  • 启用–security-opt no-new-privileges
  • 设置资源限制(CPU、内存、PID等)
  • 配置只读文件系统(–read-only)
  • 为容器配置健康检查

C.3 网络安全

  • 不将数据库端口直接暴露到公网
  • 使用自定义bridge网络隔离容器
  • 配置适当的防火墙规则
  • 使用TLS加密Docker API通信
  • 不使用insecure-registries(除非内网测试)

C.4 宿主机安全

  • 保持系统和Docker版本更新
  • 限制Docker socket的访问权限
  • 启用审计日志
  • 配置SELinux或AppArmor
  • 定期备份Docker数据和配置
# 使用Trivy扫描镜像安全漏洞
trivy image nginx:latest

# 使用Docker Bench for Security进行安全检查
docker run --rm --net host --pid host --userns host --cap-add audit_control \
    -e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
    -v /var/lib:/var/lib:ro \
    -v /var/run/docker.sock:/var/run/docker.sock:ro \
    -v /etc:/etc:ro \
    --label docker_bench_security \
    docker/docker-bench-security

附录D:Docker性能监控与调优

D.1 关键性能指标

在生产环境中运行Docker时,以下性能指标需要重点关注:

指标类别 具体指标 监控方法 告警阈值
CPU 容器CPU使用率 docker stats / cAdvisor >80%持续5分钟
内存 容器内存使用率 docker stats / cAdvisor >90%持续5分钟
磁盘 磁盘空间使用率 df -h / docker system df >85%
磁盘IO 读写IOPS iostat / cAdvisor 根据磁盘规格
网络 网络吞吐量 iftop / cAdvisor 根据带宽规格
网络 网络延迟 ping / 容器健康检查 >100ms
容器 容器重启次数 docker events >3次/小时
容器 容器健康状态 docker inspect unhealthy

D.2 性能调优建议

# 1. 调整Docker守护进程的并发设置
# daemon.json
{
  "max-concurrent-downloads": 10,    # 默认3,增大可加速镜像拉取
  "max-concurrent-uploads": 5,       # 默认5
  "max-download-attempts": 5         # 默认5
}

# 2. 调整容器资源限制
docker run -d \
    --cpus="2.0" \                   # 限制CPU
    --memory="4g" \                  # 限制内存
    --memory-reservation="2g" \      # 内存软限制
    --pids-limit="200" \             # 限制进程数
    --blkio-weight="500" \           # IO权重(10-1000)
    my-app:latest

# 3. 调整日志配置避免IO瓶颈
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "50m",
    "max-file": "3",
    "compress": "true"
  }
}

# 4. 使用local存储驱动优化性能
# 确保使用overlay2并启用d_type支持

# 5. 优化网络性能
# 使用host网络模式(如果安全允许)
docker run --network host nginx:latest

# 或调整MTU
{
  "mtu": 1450
}

# 6. 启用BuildKit加速构建
{
  "features": {
    "buildkit": true
  }
}

# 7. 定期清理无用资源
# 设置crontab定期执行
0 2 * * 0 docker system prune -a -f --filter "until=168h"

D.3 容器性能分析工具

# 使用docker stats实时监控
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}"

# 使用perf进行性能分析(需要特权模式)
docker run --rm --privileged -it \
    -v /tmp:/tmp \
    --pid=host \
    alpine sh -c "apk add perf && perf top"

# 使用sysdig进行系统级监控
docker run --rm -i --privileged \
    --name sysdig \
    --volume /var/run/docker.sock:/host/var/run/docker.sock \
    --volume /dev:/host/dev \
    --volume /proc:/host/proc:ro \
    --volume /boot:/host/boot:ro \
    --volume /lib/modules:/host/lib/modules:ro \
    --volume /usr:/host/usr:ro \
    sysdig/sysdig:latest

# 查看容器的资源限制和实际使用
docker inspect --format 'CPU: {{.HostConfig.NanoCpus}} Mem: {{.HostConfig.Memory}}' my-container

附录E:常用Docker配置文件速查表

E.1 Docker配置文件位置

文件 路径(Linux) 路径(Windows/macOS) 说明
daemon.json /etc/docker/daemon.json Docker Desktop设置界面 Docker守护进程配置
containerd配置 /etc/containerd/config.toml Docker内部 containerd运行时配置
Docker CLI配置 ~/.docker/config.json ~/.docker/config.json Docker CLI配置
Docker context ~/.docker/contexts/ ~/.docker/contexts/ Docker上下文配置
systemd服务 /etc/systemd/system/docker.service.d/ 不适用 systemd覆盖配置
WSL配置 不适用 %USERPROFILE%.wslconfig WSL 2资源限制

E.2 快速配置模板

以下是不同场景下推荐的daemon.json配置模板:

开发环境配置:

{
  "registry-mirrors": ["https://xxxxxxxx.mirror.aliyuncs.com"],
  "log-driver": "json-file",
  "log-opts": {"max-size": "10m", "max-file": "3"},
  "features": {"buildkit": true}
}

测试环境配置:

{
  "data-root": "/data/docker",
  "registry-mirrors": ["https://xxxxxxxx.mirror.aliyuncs.com"],
  "log-driver": "json-file",
  "log-opts": {"max-size": "20m", "max-file": "3"},
  "storage-driver": "overlay2",
  "live-restore": true,
  "features": {"buildkit": true},
  "builder": {"gc": {"enabled": true, "defaultKeepStorage": "10GB"}}
}

生产环境配置:

{
  "data-root": "/data/docker",
  "log-driver": "json-file",
  "log-opts": {"max-size": "50m", "max-file": "5", "compress": "true"},
  "storage-driver": "overlay2",
  "live-restore": true,
  "max-concurrent-downloads": 10,
  "max-concurrent-uploads": 5,
  "userland-proxy": false,
  "no-new-privileges": true,
  "default-ulimits": {
    "nofile": {"Name": "nofile", "Hard": 65536, "Soft": 65536},
    "nproc": {"Name": "nproc", "Hard": 4096, "Soft": 2048}
  },
  "registry-mirrors": ["https://xxxxxxxx.mirror.aliyuncs.com"],
  "features": {"buildkit": true},
  "builder": {"gc": {"enabled": true, "defaultKeepStorage": "20GB"}},
  "default-address-pools": [{"base": "172.20.0.0/16", "size": 24}]
}

以上配置模板可根据实际需求进行调整。建议在生产环境部署前,先在测试环境中验证配置的有效性。

附录F:Docker Compose安装与基础使用

F.1 什么是Docker Compose

Docker Compose是Docker官方提供的多容器编排工具,它允许用户通过一个YAML格式的配置文件来定义、运行和管理多个相互关联的容器。在实际开发和生产环境中,一个完整的应用往往由多个服务组成,例如Web服务器、数据库、缓存服务等。如果逐个使用docker run命令来启动这些容器,不仅命令冗长容易出错,而且难以管理容器之间的依赖关系和网络通信。Docker Compose完美解决了这个问题,它将所有容器的配置集中在一个docker-compose.yml文件中,通过简单的命令就能完成全部服务的启动、停止和重建。

Docker Compose的核心价值在于声明式配置和一键部署。开发者只需要描述清楚每个服务应该是什么样子,Compose就会负责创建网络、启动容器、设置依赖关系等所有细节。这种方式特别适合开发环境、持续集成流水线以及中小规模的容器化部署场景。

F.2 Docker Compose安装

F.2.1 Linux系统安装Docker Compose

从Docker Compose V2开始,它已经作为Docker CLI的插件集成到了Docker中,安装方式与V1有所不同。以下是完整的安装步骤:

# 方法一:通过Docker官方仓库安装(推荐)
# 如果已经按照第二章的方法添加了Docker官方仓库,直接安装即可
sudo apt-get update
sudo apt-get install docker-compose-plugin

# 验证安装
docker compose version
# 输出示例:Docker Compose version v2.21.0

# 方法二:手动下载二进制文件安装
# 下载最新版本的Docker Compose二进制文件
DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
mkdir -p $DOCKER_CONFIG/cli-plugins
curl -SL "https://github.com/docker/compose/releases/download/v2.21.0/docker-compose-linux-$(uname -m)" \
  -o $DOCKER_CONFIG/cli-plugins/docker-compose

# 赋予执行权限
chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose

# 验证安装
docker compose version

# 方法三:使用pip安装(适用于Python环境)
pip3 install docker-compose
# 注意:pip安装的是V1版本,命令为 docker-compose(带连字符)
F.2.2 Windows和macOS安装

在Windows和macOS平台上,Docker Desktop已经内置了Docker Compose V2,无需单独安装。只需要确保Docker Desktop正常安装并运行即可。

# 在Windows PowerShell或macOS终端中验证
docker compose version
F.2.3 Docker Compose V1与V2的区别
特性 Docker Compose V1 Docker Compose V2
实现语言 Python Go
命令格式 docker-compose(带连字符) docker compose(空格分隔)
安装方式 独立二进制文件 Docker CLI插件
性能 较慢 显著提升
兼容性 广泛 向后兼容V1的大部分功能
维护状态 已停止维护 活跃开发中

F.3 Docker Compose基础使用

F.3.1 编写docker-compose.yml文件

以下是一个完整的Web应用示例,包含Nginx前端、Python后端和MySQL数据库三个服务:

# docker-compose.yml
version: "3.9"  # Compose文件格式版本

services:
  # Nginx前端服务
  web:
    image: nginx:alpine
    container_name: my-nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./nginx/html:/usr/share/nginx/html
      - ./nginx/logs:/var/log/nginx
    depends_on:
      - app
    restart: unless-stopped
    networks:
      - frontend

  # Python后端服务
  app:
    build:
      context: ./app
      dockerfile: Dockerfile
    container_name: my-app
    environment:
      - DB_HOST=db
      - DB_PORT=3306
      - DB_NAME=myapp
      - DB_USER=root
      - DB_PASSWORD=secret123
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped
    networks:
      - frontend
      - backend

  # MySQL数据库服务
  db:
    image: mysql:8.0
    container_name: my-mysql
    environment:
      MYSQL_ROOT_PASSWORD: secret123
      MYSQL_DATABASE: myapp
      MYSQL_USER: appuser
      MYSQL_PASSWORD: userpass
    volumes:
      - db_data:/var/lib/mysql
      - ./mysql/init:/docker-entrypoint-initdb.d
    ports:
      - "3306:3306"
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped
    networks:
      - backend

# 定义数据卷
volumes:
  db_data:
    driver: local

# 定义网络
networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true  # 内部网络,不对外暴露
F.3.2 常用Docker Compose命令
# 在后台启动所有服务
docker compose up -d

# 查看服务状态
docker compose ps

# 查看日志(所有服务)
docker compose logs -f

# 查看指定服务的日志
docker compose logs -f web

# 重新构建并启动服务
docker compose up -d --build

# 停止并删除所有容器、网络
docker compose down

# 停止并删除所有容器、网络、数据卷(谨慎使用)
docker compose down -v

# 仅停止服务(不删除容器)
docker compose stop

# 启动已停止的服务
docker compose start

# 重启服务
docker compose restart

# 查看服务资源使用情况
docker compose top
docker compose stats

# 在运行中的服务中执行命令
docker compose exec app bash

# 扩展服务实例数
docker compose up -d --scale app=3

F.4 Docker Compose实战技巧

F.4.1 使用环境变量文件
# .env文件
DB_ROOT_PASSWORD=secret123
APP_PORT=8080
MYSQL_VERSION=8.0
# docker-compose.yml 中引用环境变量
version: "3.9"
services:
  db:
    image: mysql:${MYSQL_VERSION}
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
  app:
    ports:
      - "${APP_PORT}:80"
F.4.2 使用多个Compose文件覆盖配置
# 基础配置 docker-compose.yml
# 开发覆盖 docker-compose.override.yml(默认自动加载)
# 生产覆盖 docker-compose.prod.yml

# 启动生产环境配置
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

这种多文件覆盖机制使得同一套服务定义可以在不同环境中灵活使用,开发环境和生产环境的差异只需要通过覆盖文件来体现,极大提高了配置的复用性和可维护性。

附录G:Docker容器日志管理最佳实践

G.1 Docker日志机制详解

Docker容器的日志管理是容器运维中至关重要的一环。当容器运行时,其标准输出(stdout)和标准错误(stderr)会被Docker守护进程捕获并存储。Docker提供了多种日志驱动来处理这些日志数据,每种驱动都有其适用的场景和特点。

理解Docker的日志机制对于排查问题、监控容器状态以及满足合规审计要求都至关重要。默认情况下,Docker使用json-file日志驱动,它将容器日志以JSON格式写入磁盘文件。如果不做任何限制,这些日志文件会随时间无限增长,最终耗尽磁盘空间导致系统崩溃。

G.2 日志驱动类型与选择

日志驱动 说明 适用场景
json-file 默认驱动,JSON格式写入文件 开发测试、单机部署
local 优化的本地存储格式 推荐用于生产单机
syslog 写入syslog系统日志 传统系统集成
journald 写入systemd journal systemd环境
fluentd 发送到Fluentd 集中式日志收集
awslogs 发送到AWS CloudWatch AWS云环境
gcplogs 发送到Google Cloud Logging GCP云环境
none 禁用日志 不需要日志的场景

G.3 日志轮转配置实践

# 查看容器日志
docker logs <容器名或ID>

# 查看最近100行日志
docker logs --tail 100 <容器名>

# 实时跟踪日志输出
docker logs -f <容器名>

# 查看指定时间之后的日志
docker logs --since "2026-01-01T00:00:00" <容器名>

# 查看最近30分钟的日志
docker logs --since 30m <容器名>

# 查看指定时间段的日志
docker logs --since "2026-01-01T00:00:00" --until "2026-01-01T12:00:00" <容器名>

# 显示时间戳
docker logs -t <容器名>

G.4 企业级日志收集方案

在多节点、多容器的生产环境中,单纯依赖Docker自带的日志功能是远远不够的。企业通常需要构建集中式日志收集系统,将所有容器的日志统一收集、存储和分析。业界最流行的方案是ELK(Elasticsearch、Logstash、Kibana)或EFK(Elasticsearch、Fluentd/Fluent Bit、Kibana)技术栈。

以下是一个使用Fluent Bit作为日志收集器的Docker Compose配置示例:

version: "3.9"

services:
  # 应用服务,使用fluentd日志驱动
  app:
    image: myapp:latest
    logging:
      driver: fluentd
      options:
        fluentd-address: localhost:24224
        tag: myapp.service
    depends_on:
      - fluentbit

  # Fluent Bit日志收集器
  fluentbit:
    image: fluent/fluent-bit:latest
    ports:
      - "24224:24224"
      - "24224:24224/udp"
    volumes:
      - ./fluent-bit.conf:/fluent-bit/etc/fluent-bit.conf
      - ./parsers.conf:/fluent-bit/etc/parsers.conf
    restart: always

  # Elasticsearch日志存储
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0
    environment:
      - discovery.type=single-node
      - ES_JAVA_OPTS=-Xms512m -Xmx512m
      - xpack.security.enabled=false
    volumes:
      - es_data:/usr/share/elasticsearch/data
    ports:
      - "9200:9200"

  # Kibana日志可视化
  kibana:
    image: docker.elastic.co/kibana/kibana:8.11.0
    ports:
      - "5601:5601"
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    depends_on:
      - elasticsearch

volumes:
  es_data:

这种集中式日志方案的优势在于:所有容器的日志都会被实时收集到统一存储中,运维人员可以通过Kibana的Web界面进行全文检索、日志过滤和可视化分析,极大提高了问题排查的效率。同时,通过Fluent Bit的灵活配置,可以对日志进行解析、过滤和格式转换,满足不同业务场景的日志处理需求。

附录H:Dockerfile编写基础指南

H.1 Dockerfile概述

Dockerfile是一个纯文本文件,包含了一系列指令,用于自动化构建Docker镜像。它是基础设施即代码理念在容器领域的具体体现,让镜像的构建过程变得可追溯、可版本化、可复现。掌握Dockerfile的编写是使用Docker的核心技能之一。

一个优秀的Dockerfile应该追求以下目标:构建速度快、镜像体积小、安全性高、可维护性好。这些目标需要通过合理的指令选择、层缓存优化、多阶段构建等技巧来实现。

H.2 Dockerfile常用指令详解

# Dockerfile示例:构建一个Python Web应用镜像

# 指定基础镜像(必须放在第一行)
FROM python:3.11-slim

# 设置维护者信息(已废弃,推荐使用LABEL)
LABEL maintainer="dev@example.com"
LABEL version="1.0"
LABEL description="Python Web Application"

# 设置环境变量
ENV PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    APP_HOME=/app

# 设置工作目录
WORKDIR $APP_HOME

# 安装系统依赖(利用缓存,先复制依赖文件)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 复制应用代码
COPY . .

# 声明暴露端口
EXPOSE 8000

# 创建非root用户运行应用(安全最佳实践)
RUN groupadd -r appuser && useradd -r -g appuser appuser
USER appuser

# 设置健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:8000/health || exit 1

# 容器启动命令
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "myapp.wsgi:application"]

H.3 多阶段构建优化镜像大小

多阶段构建是Dockerfile中最重要的优化技巧之一。它允许在一个Dockerfile中使用多个FROM指令,每个FROM开始一个新的构建阶段。最终镜像只会包含最后一个阶段的文件,前面阶段的中间产物会被自动丢弃。这种方式特别适合编译型语言(如Go、Java、C++),可以将编译环境和运行环境分离,大幅减小最终镜像的体积。

# 多阶段构建示例:Go应用

# 第一阶段:构建阶段
FROM golang:1.21-alpine AS builder

WORKDIR /build

# 下载依赖(利用缓存)
COPY go.mod go.sum ./
RUN go mod download

# 复制源码并编译
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o myapp .

# 第二阶段:运行阶段
FROM alpine:3.18

# 安装必要的CA证书
RUN apk --no-cache add ca-certificates

WORKDIR /app

# 从构建阶段复制编译好的二进制文件
COPY --from=builder /build/myapp .
# 复制配置文件
COPY --from=builder /build/configs ./configs

# 创建非root用户
RUN adduser -D -u 10001 appuser
USER appuser

EXPOSE 8080

CMD ["./myapp"]

通过多阶段构建,Go应用的镜像体积可以从编译镜像的数百MB缩小到运行镜像的十几MB,这种优化对于大规模部署和快速镜像拉取都具有重要意义。

H.4 Dockerfile最佳实践清单

最佳实践 说明 效果
使用小基础镜像 选择alpine或slim变体 减小镜像体积
合并RUN指令 使用&&连接多个命令 减少镜像层数
利用构建缓存 将不常变化的指令放前面 加快构建速度
使用.dockerignore 排除不必要文件 加快构建上下文传输
多阶段构建 分离编译和运行环境 大幅减小镜像体积
使用特定标签 避免使用latest标签 保证可复现性
非root用户运行 创建专用用户 提高安全性
设置健康检查 使用HEALTHCHECK指令 便于容器编排

附录I:Docker网络深度解析与实战

I.1 Docker网络架构概述

Docker的网络子系统是容器化应用中最为复杂的部分之一。它负责容器之间、容器与宿主机之间、容器与外部世界之间的网络通信。Docker采用了基于Linux网络命名空间、虚拟网桥、iptables和veth pair等内核技术构建了一套灵活的网络模型。

深入理解Docker网络对于设计微服务架构、排查网络连通性问题以及优化网络性能都至关重要。每种网络模式都有其特定的使用场景和优缺点,开发者需要根据实际需求选择最合适的网络方案。

I.2 自定义网络创建与管理

# 创建桥接网络(最常用)
docker network create --driver bridge \
  --subnet 172.25.0.0/16 \
  --ip-range 172.25.0.0/24 \
  --gateway 172.25.0.1 \
  my-network

# 创建网络并指定容器名称解析
docker network create --driver bridge \
  --subnet 10.0.0.0/24 \
  --internal \  # 内部网络,不允许外部访问
  secure-internal

# 创建overlay网络(用于Swarm集群跨主机通信)
docker network create --driver overlay \
  --subnet 10.1.0.0/16 \
  --attachable \  # 允许独立容器加入
  my-overlay

# 创建macvlan网络(容器获得独立MAC地址)
docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 \
  my-macvlan

# 查看网络列表
docker network ls

# 查看网络详情
docker network inspect my-network

# 将容器连接到网络
docker network connect my-network my-container

# 断开容器与网络的连接
docker network disconnect my-network my-container

# 删除未使用的网络
docker network prune

# 删除指定网络
docker network rm my-network

I.3 容器间通信实战

# 场景:创建一个Web应用和数据库,通过网络互联

# 步骤1:创建自定义网络
docker network create app-network

# 步骤2:启动数据库容器并加入网络
docker run -d \
  --name database \
  --network app-network \
  --network-alias db \
  -e MYSQL_ROOT_PASSWORD=secret \
  -e MYSQL_DATABASE=myapp \
  mysql:8.0

# 步骤3:启动Web应用并加入同一网络
docker run -d \
  --name webapp \
  --network app-network \
  --network-alias app \
  -p 8080:80 \
  -e DB_HOST=db \
  myapp:latest

# 此时,webapp容器可以通过以下方式访问数据库:
# 1. 使用容器名:database:3306
# 2. 使用网络别名:db:3306
# Docker内置DNS会自动解析容器名和网络别名

# 验证容器间连通性
docker exec webapp ping database
docker exec webapp ping db
docker exec webapp curl -I http://database:3306

I.4 Docker DNS服务详解

Docker在自定义网络中内置了DNS服务,容器之间可以通过容器名称或网络别名互相访问,无需知道对方的IP地址。这是一个非常实用的功能,因为容器的IP地址在每次重启后都可能发生变化,而容器名称和别名是固定的。

需要注意的是,默认的bridge网络(即使用docker run时不指定--network创建的容器所在的网络)不支持自动DNS解析。只有在用户自定义的bridge网络中,Docker才会提供DNS服务。这是推荐使用自定义网络的重要原因之一。

I.5 端口映射与发布

# Docker端口映射的几种方式

# 1. 随机映射宿主机端口到容器端口
docker run -d -P nginx
# Docker会随机选择一个49153-65535之间的端口

# 2. 指定宿主机端口映射到容器端口
docker run -d -p 8080:80 nginx

# 3. 映射到指定IP地址的端口
docker run -d -p 127.0.0.1:8080:80 nginx

# 4. 映射UDP端口
docker run -d -p 53:53/udp dns-server

# 5. 映射多个端口
docker run -d -p 80:80 -p 443:443 -p 8080:8080 nginx

# 6. 查看容器端口映射
docker port my-container

端口映射是Docker网络中最常用的功能之一。通过-p参数,可以将容器内部的服务端口映射到宿主机上,使得外部网络可以访问容器提供的服务。理解端口映射的工作原理对于排查网络访问问题非常重要。当映射不生效时,通常需要检查宿主机防火墙规则、端口是否被占用以及容器内部服务是否正常监听等方面。

附录J:Docker存储卷管理进阶

J.1 Docker存储概念深入

Docker的存储系统是容器持久化数据的基石。在Docker中,容器的文件系统是基于镜像层创建的可写层,这种设计带来了一个重要问题:当容器被删除时,其可写层中的所有数据都会随之丢失。为了解决这个问题,Docker提供了三种数据持久化机制:Volumes(数据卷)、Bind Mounts(绑定挂载)和tmpfs Mounts(临时文件系统)。

数据卷是Docker推荐的数据持久化方式,它由Docker引擎管理,存储在宿主机的特定目录中,与宿主机的文件系统解耦。绑定挂载则直接将宿主机的文件或目录挂载到容器中,适合开发环境中的代码热重载场景。tmpfs将数据存储在宿主机的内存中,适用于存储敏感信息或需要极高性能的临时数据。

J.2 数据卷高级操作

# 创建命名数据卷
docker volume create my-data

# 创建数据卷并指定驱动和选项
docker volume create \
  --driver local \
  --opt type=nfs \
  --opt o=addr=192.168.1.100,rw \
  --opt device=:/path/to/nfs/share \
  nfs-data

# 列出所有数据卷
docker volume ls

# 查看数据卷详情
docker volume inspect my-data

# 使用数据卷启动容器
docker run -d \
  --name app \
  -v my-data:/app/data \
  myapp:latest

# 挂载为只读数据卷
docker run -d \
  --name app \
  -v my-data:/app/data:ro \
  myapp:latest

# 使用绑定挂载(绝对路径方式)
docker run -d \
  --name app \
  -v /home/user/project:/app \
  -v /home/user/config/app.conf:/etc/app/app.conf \
  myapp:latest

# 使用--mount语法(更明确,推荐)
docker run -d \
  --name app \
  --mount type=volume,src=my-data,dst=/app/data \
  --mount type=bind,src=/home/user/config,dst=/etc/app,readonly \
  myapp:latest

# 在容器之间共享数据卷
docker run -d --name app1 -v shared-data:/data myapp
docker run -d --name app2 -v shared-data:/data myapp

# 备份数据卷
docker run --rm \
  -v my-data:/source:ro \
  -v /backup:/backup \
  alpine tar czf /backup/my-data-backup.tar.gz -C /source .

# 恢复数据卷
docker volume create my-data-restored
docker run --rm \
  -v my-data-restored:/target \
  -v /backup:/backup \
  alpine tar xzf /backup/my-data-backup.tar.gz -C /target

# 迁移数据卷到新位置
docker run --rm \
  -v old-volume:/source:ro \
  -v new-volume:/target \
  alpine sh -c "cp -a /source/. /target/"

# 删除未使用的数据卷
docker volume prune

# 删除所有数据卷(谨慎使用)
docker volume prune -a

# 删除指定数据卷(必须先无容器使用)
docker volume rm my-data

J.3 存储驱动与性能

Docker的存储驱动决定了镜像层和容器可写层的实现方式,直接影响容器的启动速度、磁盘使用效率和I/O性能。目前推荐的存储驱动是overlay2,它在性能和稳定性方面都优于早期的devicemapperaufs

# 查看当前存储驱动
docker info | grep "Storage Driver"

# 查看存储驱动详细信息
docker info | grep -A 10 "Storage Driver"

# 检查overlay2是否正常工作
docker info | grep "Backing Filesystem"

# 查看Docker磁盘使用情况
docker system df -v

# 查看容器可写层大小
docker ps -s

选择合适的存储驱动需要考虑宿主机的文件系统类型、内核版本以及使用场景。在ext4或xfs文件系统上,overlay2是最佳选择。对于生产环境,建议将Docker的数据目录放在独立的磁盘或分区上,使用SSD存储以获得更好的I/O性能。同时,定期监控Docker的磁盘使用情况,及时清理无用的镜像和容器,避免磁盘空间耗尽影响系统运行。

附录K:Docker Registry私有仓库搭建

K.1 Docker Registry概述

Docker Registry是Docker镜像的存储和分发服务。Docker Hub是Docker官方提供的公共镜像仓库,但在企业环境中,出于安全合规、网络带宽、访问控制等方面的考虑,通常需要搭建私有镜像仓库。Docker Registry官方开源版本提供了基础的镜像存储和分发功能,而Harbor则在其基础上增加了用户管理、访问控制、镜像扫描、镜像复制等企业级功能。

搭建私有镜像仓库是企业容器化进程中的一项基础性工作。它不仅能够加速内部镜像的分发,还能有效保护企业的核心代码和商业机密,避免将包含敏感信息的镜像推送到公共仓库中。对于需要在多个数据中心或多个Kubernetes集群之间同步镜像的场景,私有仓库的镜像复制功能也是不可或缺的。

K.2 搭建Docker Registry

# 拉取Docker Registry官方镜像
docker pull registry:2

# 启动Docker Registry容器
docker run -d \
  --name registry \
  -p 5000:5000 \
  -v /data/registry:/var/lib/registry \
  -e REGISTRY_STORAGE_DELETE_ENABLED=true \
  --restart=always \
  registry:2

# 配置Docker客户端允许HTTP连接(非HTTPS)
# 编辑 /etc/docker/daemon.json
# {
#   "insecure-registries": ["192.168.1.100:5000"]
# }

# 重启Docker服务
sudo systemctl restart docker

# 为镜像打标签
docker tag myapp:latest 192.168.1.100:5000/myapp:latest

# 推送镜像到私有仓库
docker push 192.168.1.100:5000/myapp:latest

# 从私有仓库拉取镜像
docker pull 192.168.1.100:5000/myapp:latest

# 查看仓库中的镜像列表
curl -X GET http://192.168.1.100:5000/v2/_catalog

# 查看指定镜像的标签列表
curl -X GET http://192.168.1.100:5000/v2/myapp/tags/list

K.3 配置带TLS认证的Registry

在生产环境中,使用HTTP明文传输镜像数据存在严重的安全隐患。标准的做法是为Registry配置TLS证书,启用HTTPS加密通信。证书可以从权威CA机构申请,也可以使用自签名证书。以下是配置TLS认证Registry的完整步骤:

# 步骤1:生成自签名证书
mkdir -p /data/registry/certs
openssl req -newkey rsa:4096 -nodes -sha256 \
  -keyout /data/registry/certs/domain.key \
  -x509 -days 365 \
  -out /data/registry/certs/domain.crt \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/CN=registry.mycompany.com"

# 步骤2:创建密码认证文件
mkdir -p /data/registry/auth
docker run --rm \
  --entrypoint htpasswd \
  httpd:2 \
  -Bbn admin password123 > /data/registry/auth/htpasswd

# 步骤3:启动带TLS和认证的Registry
docker run -d \
  --name registry \
  -p 443:443 \
  -v /data/registry/data:/var/lib/registry \
  -v /data/registry/certs:/certs \
  -v /data/registry/auth:/auth \
  -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
  -e REGISTRY_AUTH=htpasswd \
  -e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  --restart=always \
  registry:2

# 步骤4:将证书复制到Docker客户端
sudo mkdir -p /etc/docker/certs.d/registry.mycompany.com
sudo cp /data/registry/certs/domain.crt /etc/docker/certs.d/registry.mycompany.com/ca.crt

# 步骤5:登录私有仓库
docker login registry.mycompany.com
# 输入用户名和密码

# 步骤6:推送和拉取镜像
docker tag myapp:latest registry.mycompany.com/myapp:latest
docker push registry.mycompany.com/myapp:latest
docker pull registry.mycompany.com/myapp:latest

K.4 使用Docker Compose部署Registry

对于更复杂的部署需求,使用Docker Compose可以更方便地管理Registry服务的配置和生命周期。以下是一个包含TLS认证、用户认证、数据持久化和自动重启的完整Compose配置:

version: "3.9"

services:
  registry:
    image: registry:2
    container_name: private-registry
    ports:
      - "443:443"
    volumes:
      - ./data:/var/lib/registry
      - ./certs:/certs
      - ./auth:/auth
    environment:
      REGISTRY_HTTP_ADDR: 0.0.0.0:443
      REGISTRY_HTTP_TLS_CERTIFICATE: /certs/domain.crt
      REGISTRY_HTTP_TLS_KEY: /certs/domain.key
      REGISTRY_AUTH: htpasswd
      REGISTRY_AUTH_HTPASSWD_REALM: "Registry Realm"
      REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
      REGISTRY_STORAGE_DELETE_ENABLED: "true"
      # 配置镜像存储后端(可选)
      # REGISTRY_STORAGE: s3
      # REGISTRY_STORAGE_S3_REGION: us-east-1
      # REGISTRY_STORAGE_S3_BUCKET: my-registry-bucket
      # REGISTRY_STORAGE_S3_ACCESSKEY: YOUR_ACCESS_KEY
      # REGISTRY_STORAGE_S3_SECRETKEY: YOUR_SECRET_KEY
    restart: always
    healthcheck:
      test: ["CMD", "wget", "-q", "--spider", "https://localhost:443/v2/"]
      interval: 30s
      timeout: 10s
      retries: 3

K.5 Registry镜像清理策略

随着时间推移,私有仓库中会积累大量旧版本的镜像,占用大量存储空间。定期清理无用镜像是仓库维护的重要工作。Registry V2提供了垃圾回收机制来清理未被任何标签引用的镜像层。

# 步骤1:将Registry设为只读模式(防止清理过程中有新镜像推送)
# 在docker-compose.yml中添加环境变量:
# REGISTRY_STORAGE_MAINTENANCE_READONLY_ENABLED: "true"
# 然后重启Registry服务

# 步骤2:列出所有镜像和标签
curl -X GET https://registry.mycompany.com/v2/_catalog
curl -X GET https://registry.mycompany.com/v2/myapp/tags/list

# 步骤3:删除不需要的镜像标签
curl -X DELETE \
  -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
  -u admin:password123 \
  https://registry.mycompany.com/v2/myapp/manifests/<digest>

# 步骤4:执行垃圾回收
docker exec -it private-registry registry garbage-collect \
  /etc/docker/registry/config.yml --delete-untagged

# 步骤5:取消只读模式并重启Registry

K.6 Harbor企业级镜像仓库简介

Harbor是由VMware开源的企业级Docker Registry服务,在Docker Registry的基础上增加了丰富的企业级功能。Harbor的主要特性包括:基于角色的访问控制(RBAC)、LDAP/AD集成、镜像漏洞扫描、镜像签名验证、镜像复制(跨数据中心同步)、图形化管理界面以及操作审计日志等。对于有较高安全合规要求的企业,Harbor是搭建私有镜像仓库的首选方案。Harbor的安装可以使用官方提供的离线安装包,也可以通过Helm Chart部署到Kubernetes集群中,具体安装步骤可以参考Harbor官方文档。

附录L:Docker容器资源限制与Cgroups详解

L.1 Cgroups基础概念

Cgroups(Control Groups)是Linux内核提供的资源限制和隔离机制,Docker正是通过Cgroups来实现对容器CPU、内存、磁盘I/O等资源的限制。理解Cgroups的工作原理对于合理配置容器资源、避免资源争抢以及排查性能问题都非常重要。

在Docker中,每个容器都会被分配到一个独立的Cgroup中,Docker通过向Cgroup的配置文件写入相应的参数来限制容器的资源使用。当容器尝试使用超过限制的资源时,内核会根据配置采取相应的措施,例如限制CPU时间片、触发OOM Killer杀死进程或者阻塞I/O操作等。

L.2 CPU资源限制详解

# 限制容器使用的CPU核心数(可以是小数)
docker run -d --cpus="1.5" myapp
# 该容器最多可以使用1.5个CPU核心

# 指定容器可以使用的CPU核心
docker run -d --cpuset-cpus="0,1,2" myapp
# 该容器只能使用第0、1、2号CPU核心

# 设置CPU份额(相对权重,默认1024)
docker run -d --cpu-shares=512 myapp
# 当CPU资源紧张时,该容器获得的CPU时间是默认值的一半

# 设置CPU配额和周期
docker run -d --cpu-quota=50000 --cpu-period=100000 myapp
# 每100000微秒(100毫秒)的周期内,最多使用50000微秒(50毫秒)CPU时间
# 相当于限制为0.5个CPU核心

# 实时CPU调度配置(需要内核支持)
docker run -d \
  --cpu-rt-runtime=950000 \
  --cpu-rt-period=1000000 \
  myapp

L.3 内存资源限制详解

# 限制容器最大可用内存
docker run -d --memory="512m" myapp

# 限制内存和Swap总量
docker run -d --memory="512m" --memory-swap="1g" myapp
# 容器最多使用512MB内存和512MB Swap

# 设置内存软限制(仅在系统内存紧张时生效)
docker run -d --memory="1g" --memory-reservation="512m" myapp

# 设置OOM Killer行为
docker run -d --memory="256m" --oom-kill-disable myapp
# 禁止OOM Killer杀死该容器(谨慎使用,可能导致系统不稳定)

# 更精细的内存控制
docker run -d \
  --memory="512m" \
  --memory-swap="512m" \
  --memory-swappiness=0 \
  --kernel-memory="100m" \
  --oom-kill-disable \
  myapp

L.4 磁盘I/O限制

# 限制读写速率(每秒字节数)
docker run -d \
  --device-read-bps /dev/sda:10mb \
  --device-write-bps /dev/sda:10mb \
  myapp

# 限制读写IOPS(每秒IO操作次数)
docker run -d \
  --device-read-iops /dev/sda:100 \
  --device-write-iops /dev/sda:100 \
  myapp

# 设置IO权重(相对优先级,默认500,范围10-1000)
docker run -d --blkio-weight=600 myapp

L.5 资源限制监控与调优

合理设置容器资源限制是保障系统稳定运行的关键。资源限制设置过低会导致应用性能下降甚至无法正常运行,设置过高则无法起到资源隔离的作用。建议先通过压力测试确定应用正常运行的资源需求,然后在此基础上设置一定的冗余作为资源限制值。同时,应该结合监控系统实时跟踪容器的资源使用情况,根据实际运行数据动态调整资源限制。

# 实时监控所有容器的资源使用情况
docker stats

# 监控指定容器
docker stats my-container

# 以特定格式输出监控数据
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}"

# 查看容器的资源限制配置
docker inspect my-container | grep -A 20 "HostConfig"

# 查看容器的Cgroup配置
docker exec my-container cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us
docker exec my-container cat /sys/fs/cgroup/memory/memory.limit_in_bytes

附录M:Docker安全加固完整指南

M.1 Docker安全威胁模型

在容器化部署中,安全问题是不容忽视的重要方面。Docker容器的安全涉及多个层面,包括宿主机安全、镜像安全、容器运行时安全、网络安全和数据安全等。容器与传统虚拟机最大的区别在于容器共享宿主机内核,这意味着如果容器内的进程逃逸到宿主机,将会对整个系统造成严重威胁。因此,在生产环境中部署Docker时,必须采取多层防御策略,从镜像构建、容器配置到运行时监控,每个环节都需要考虑安全因素。

容器安全的核心原则是最小权限原则,即容器只应该拥有完成其功能所必需的最小权限。这包括使用非root用户运行应用、只挂载必要的文件和目录、限制网络访问范围、限制系统调用能力等方面。通过遵循最小权限原则,即使容器被攻破,攻击者能够造成的损害也被限制在最小范围内。

M.2 镜像安全最佳实践

# 1. 使用可信镜像源
# 优先使用官方镜像,避免使用来源不明的第三方镜像
docker pull nginx:1.25-alpine  # 指定具体版本,避免使用latest标签

# 2. 扫描镜像漏洞
# 使用Docker Scout或Trivy扫描镜像中的已知漏洞
docker scout cves myapp:latest

# 使用Trivy扫描
trivy image myapp:latest

# 3. 验证镜像签名
# 启用Docker Content Trust验证镜像签名
export DOCKER_CONTENT_TRUST=1
docker pull myapp:latest

# 4. 定期更新基础镜像
# 检查基础镜像是否有更新版本
docker pull alpine:latest
docker image inspect alpine:latest --format '{{.Created}}'

# 5. 使用多阶段构建减小攻击面
# 参见附录H中的多阶段构建示例

M.3 容器运行时安全加固

# 安全加固的容器启动命令示例
docker run -d \
  --name secure-app \
  # 以非root用户运行
  --user 10001:10001 \
  # 只读根文件系统
  --read-only \
  # 临时文件系统挂载(用于需要写入的目录)
  --tmpfs /tmp \
  # 限制能力(删除所有能力后只添加必要的)
  --cap-drop ALL \
  --cap-add NET_BIND_SERVICE \
  # 防止权限提升
  --security-opt no-new-privileges \
  # 限制系统调用
  --security-opt seccomp=/etc/docker/seccomp-profile.json \
  # 设置只读挂载
  -v /etc/nginx/conf.d:/etc/nginx/conf.d:ro \
  # 限制资源
  --memory="512m" \
  --cpus="1.0" \
  --pids-limit=100 \
  # 限制重启次数
  --restart=on-failure:3 \
  # 指定网络
  --network=internal \
  # 健康检查
  --health-cmd="curl -f http://localhost:8080/health || exit 1" \
  --health-interval=30s \
  --health-timeout=3s \
  --health-retries=3 \
  myapp:1.0

M.4 Docker守护进程安全配置

Docker守护进程本身的安全同样重要,因为守护进程以root权限运行,如果被攻击者利用,将完全控制宿主机。以下是在daemon.json中推荐的安全配置项,以及通过systemd进行额外加固的方法:

# /etc/docker/daemon.json 安全相关配置
{
  "userns-remap": "default",           // 启用用户命名空间重映射
  "no-new-privileges": true,            // 禁止权限提升
  "live-restore": true,                 // 守护进程崩溃时容器继续运行
  "userland-proxy": false,              // 禁用用户态代理
  "icc": false,                         // 禁止容器间默认通信
  "log-level": "info",                  // 设置适当的日志级别
  "max-concurrent-downloads": 10,       // 限制并发下载数
  "max-concurrent-uploads": 5,          // 限制并发上传数
  "default-ulimits": {                  // 设置默认资源限制
    "nofile": {"Hard": 65536, "Soft": 65536},
    "nproc": {"Hard": 4096, "Soft": 2048}
  }
}

# systemd服务加固(/etc/systemd/system/docker.service.d/override.conf)
[Service]
# 保护内核调整
ProtectKernelModules=true
# 保护内核调整参数
ProtectKernelTunables=true
# 保护控制组
ProtectControlGroups=true
# 限制内核日志访问
ProtectKernelLogs=true
# 禁止容器获取新权限
NoNewPrivileges=true
# 限制地址空间布局随机化
LockPersonality=true
# 限制实时优先级
RestrictRealtime=true

M.5 Docker安全审计与合规

在企业环境中,容器安全还需要满足合规审计的要求。建议定期执行安全审计,检查Docker环境和容器配置是否符合安全基线标准。可以使用开源工具如Docker Bench for Security来自动化执行安全检查,该工具基于CIS Docker Benchmark标准,能够检测出大量常见的安全配置问题并给出修复建议。同时,建议建立容器安全策略文档,明确镜像来源、资源限制、网络隔离、日志审计等方面的要求,并在CI/CD流水线中集成安全扫描步骤,确保每个镜像在部署前都通过安全检查。

# 运行Docker Bench for Security
docker run --rm --net host --pid host --userns host --cap-add audit_control \
  -e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
  -v /var/lib:/var/lib:ro \
  -v /var/run/docker.sock:/var/run/docker.sock:ro \
  -v /etc:/etc:ro \
  --label docker_bench_security \
  docker/docker-bench-security

通过以上多层安全措施的配合使用,可以构建起一个相对安全的Docker运行环境。需要强调的是,安全是一个持续的过程,而不是一次性的配置。随着新漏洞的不断发现和攻击手段的持续演进,安全策略也需要不断更新和完善。建议定期关注Docker官方安全公告,及时更新Docker版本和基础镜像,保持安全防护措施的有效性。

M.6 容器逃逸防护与检测

容器逃逸是指攻击者从容器内部突破隔离边界,获取宿主机或其他容器访问权限的攻击行为。这是容器安全中最严重的威胁之一。容器逃逸的常见途径包括利用内核漏洞、滥用Docker socket挂载、利用特权容器能力、通过Capabilities提权等。防护容器逃逸需要从多个层面采取措施。

首先,绝对不要以--privileged模式运行容器,特权容器拥有几乎所有内核能力,几乎等同于在宿主机上直接运行进程,极其危险。其次,不要将Docker socket挂载到容器中,这等同于将宿主机的完全控制权交给容器内的进程。如果确实需要在容器中管理其他容器,应该使用Docker API代理或受限的套接字权限。第三,严格限制容器的Linux Capabilities,默认删除所有能力后只添加应用运行所必需的能力。第四,启用seccomp和AppArmor配置,限制容器可以发起的系统调用和文件访问范围。第五,保持内核和Docker版本的及时更新,及时修复已知的安全漏洞。在检测方面,建议部署运行时安全监控工具如Falco,它可以实时监控容器的系统调用行为,在检测到可疑活动时发出告警。

M.7 本章安全配置检查总结

综合以上各节内容,我们可以将Docker安全配置的关键要点总结为以下几个方面:在镜像层面,使用可信镜像源、指定具体版本标签、定期扫描漏洞、启用镜像签名验证;在容器运行层面,使用非root用户、只读文件系统、最小化Capabilities、启用seccomp和AppArmor、设置资源限制;在网络层面,使用自定义网络隔离容器、限制端口暴露、配置网络策略;在守护进程层面,启用用户命名空间重映射、配置TLS通信、限制并发连接数、设置审计日志。这些措施共同构成了Docker安全防御的纵深体系,建议读者根据实际部署环境有选择地实施,在安全性和易用性之间找到合适的平衡点。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐