一、Docker 是什么?容器化技术的革命
1.1 从物理机到容器的演进
┌────────────────────────────────────────────────────────────────┐
│ 时代一:物理机时代(2000年前) │
│ ├── 一台服务器运行一个应用 │
│ ├── 资源利用率 < 10% │
│ └── 部署周期:数周(采购→上架→装系统→配置环境) │
├────────────────────────────────────────────────────────────────┤
│ 时代二:虚拟机时代(2000-2013) │
│ ├── 一台物理机运行多个 VM(VMware/KVM/Xen) │
│ ├── 资源利用率提升至 30-50% │
│ ├── 每个 VM 需完整操作系统(GB级镜像) │
│ └── 启动时间:分钟级 │
├──────────────────────────────────────────────────────────────────┤
│ 时代三:容器时代(2013至今) │
│ ├── 一台物理机运行数百容器,共享宿主机内核 │
│ ├── 资源利用率 > 80% │
│ ├── 镜像仅包含应用+依赖(MB级),秒级启动 │
│ └── 部署周期:秒级,DevOps 成为可能 │
└───────────────────────────────────────────────────────────────────┘
1.2 Docker 的诞生与里程碑
| 时间 | 事件 | 意义 |
|---|
| 2008 | LXC(Linux Containers)发布 | 内核级容器技术雏形 |
| 2013.3 | Docker 0.1 发布(DotCloud公司) | 首次封装易用工具链 |
| 2013.10 | Docker 0.6 支持非 LXC 驱动 | 解耦底层实现 |
| 2014.6 | Docker 1.0 正式发布 | 生产就绪声明 |
| 2015.6 | OCI(Open Container Initiative)成立 | 容器标准化 |
| 2016 | containerd 捐赠给 CNCF | 运行时与编排分离 |
| 2017 | Moby 项目拆分 | 社区版 vs 企业版架构 |
| 2019 | Docker Desktop 企业化 | 开发者体验优先 |
关键人物:Solomon Hykes(Docker 创始人)在 2013 年 PyCon 的 5 分钟闪电演讲,展示了"Build, Ship, Run"理念,引爆容器革命。
1.3 为什么选择 Docker?
| 对比维度 | 传统虚拟机 | Docker 容器 |
|---|
| 启动速度 | 分钟级(需引导完整 OS) | 秒级(进程级启动) |
| 镜像大小 | GB 级(完整系统盘) | MB 级(仅应用+依赖) |
| 性能损耗 | 10-20%(虚拟化层) | < 5%(内核原生支持) |
| 密度 | 单台 10-50 个 VM | 单台 100-1000 个容器 |
| 隔离级别 | 强隔离(硬件虚拟化) | 进程级隔离(Namespace/Cgroups) |
| 可移植性 | 依赖特定虚拟化平台 | 一次构建,到处运行 |
| 版本管理 | 快照笨重 | 分层镜像,版本控制如 Git |
二、Docker 核心架构与原理
2.1 整体架构图
┌─────────────────────────────────────────────────────────────────┐
│ Docker Client(CLI/GUI) │
│ docker build / run / ps / exec / logs ... │
└─────────────────────────────────────────────────────────────────┘
↓ HTTP/Unix Socket
┌─────────────────────────────────────────────────────────────────┐
│ Docker Daemon(dockerd) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ Image │ │ Container │ │ Network/Volume/Plugin │ │
│ │ Management │ │ Runtime │ │ Management │ │
│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
↓ containerd gRPC
┌─────────────────────────────────────────────────────────────────┐
│ containerd(容器运行时) │
│ 镜像拉取/存储管理 → 解包 → 传递给 runc 执行 │
└─────────────────────────────────────────────────────────────────┘
↓ OCI Runtime Spec
┌─────────────────────────────────────────────────────────────────┐
│ runc(低层运行时) │
│ 创建 Namespace → 配置 Cgroups → 启动进程 │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ Linux Kernel(Namespace/Cgroups) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ PID NS │ │ NET NS │ │ IPC NS │ │ MNT NS │ 隔离 │
│ │ 进程树 │ │ 网络栈 │ │ 信号量 │ │ 文件系统 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Cgroups v1/v2(资源限制) │ │
│ │ CPU/内存/IO/网络带宽/PID 数量限制 │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
2.2 核心技术:Namespace 隔离
| Namespace | 隔离资源 | 系统调用 | 用途 |
|---|
| PID | 进程 ID | CLONE_NEWPID | 容器内 PID 1 是独立进程树 |
| NET | 网络设备、端口、路由 | CLONE_NEWNET | 每个容器独立 IP/网卡 |
| IPC | 信号量、消息队列、共享内存 | CLONE_NEWIPC | 容器间 IPC 隔离 |
| MNT | 挂载点 | CLONE_NEWNS | 容器根文件系统独立 |
| UTS | 主机名/域名 | CLONE_NEWUTS | 容器可设独立 hostname |
| USER | 用户/组 ID | CLONE_NEWUSER | root 映射为非特权用户 |
| CGROUP | 控制组信息 | CLONE_NEWCGROUP | 隐藏宿主机 cgroup 层级 |
# 查看容器的 Namespace
ls -la /proc/$(docker inspect -f '{{.State.Pid}}' container_name)/ns/
# 输出:ipc mnt net pid user uts
# 对比宿主机 Namespace
ls -la /proc/self/ns/
2.3 核心技术:Cgroups 资源限制
# 查看容器 cgroup 配置
docker run -d --name test --memory 512m --cpus 1.5 nginx
# 宿主机查看对应 cgroup
cat /sys/fs/cgroup/memory/docker/$(docker inspect -f '{{.Id}}' test)/memory.limit_in_bytes
# 536870912 = 512MB
cat /sys/fs/cgroup/cpu/docker/$(docker inspect -f '{{.Id}}' test)/cpu.cfs_quota_us
# 150000 = 1.5 核(每 100ms 周期内可用 150ms)
2.4 镜像分层存储:UnionFS
镜像分层结构(以 nginx 为例):
┌─────────────────────────────────────┐ ← 可写层(容器层)
│ 容器运行时修改(新增/删除/修改文件) │ Copy-on-Write
├─────────────────────────────────────┤
│ Layer 5: EXPOSE 80 │ 元数据层
├─────────────────────────────────────┤
│ Layer 4: COPY nginx.conf │ 配置层
├─────────────────────────────────────┤
│ Layer 3: RUN apt-get install nginx │ 应用层
├─────────────────────────────────────┤
│ Layer 2: FROM debian:bullseye │ 基础系统层
├─────────────────────────────────────┤
│ Layer 1: 基础镜像层(scratch) │ 根文件系统
└─────────────────────────────────────┘
优势:
- 分层复用:多个镜像共享基础层,节省磁盘
- 版本控制:每层有唯一哈希,可追溯
- 快速部署:只需拉取变更层
三、Docker 生态体系
3.1 核心组件演进
2013-2016: Docker 单体架构
Docker Daemon 包揽所有(构建、运行、网络、卷)
2016-至今: 标准化拆分(OCI 规范)
┌─────────────────────────────────────────┐
│ Docker Desktop / Docker Engine │ ← 用户体验层
├─────────────────────────────────────────┤
│ Docker CLI + Docker Compose │ ← 客户端工具
├─────────────────────────────────────────┤
│ Docker Daemon (dockerd) │ ← 守护进程
├─────────────────────────────────────────┤
│ containerd(CNCF 毕业项目) │ ← 容器运行时管理
├─────────────────────────────────────────┤
│ runc(OCI 标准实现) │ ← 低层容器创建
├─────────────────────────────────────────┤
│ Linux Kernel(Namespace/Cgroups) │ ← 系统支持
└─────────────────────────────────────────┘
3.2 云原生生态关联
| 项目 | 组织 | 与 Docker 关系 | 用途 |
|---|
| Kubernetes | CNCF | 替代 Docker Swarm 成为编排标准 | 大规模容器编排 |
| containerd | CNCF | Docker 捐赠,成为 K8s 默认运行时 | 容器生命周期管理 |
| runc | OCI | Docker 主导开发 | 低层容器创建 |
| BuildKit | Docker/Moby | Docker 18.09+ 默认构建引擎 | 高效并行镜像构建 |
| Podman | RedHat | Docker 兼容替代品 | 无守护进程、rootless |
| cri-o | CNCF | Kubernetes 专用运行时 | 轻量,仅支持 OCI |
3.3 Docker vs Kubernetes 定位
┌─────────────────────────────────────────────────────────────┐
│ 开发者视角 │
│ Docker: "我把应用打包成镜像,能在笔记本上跑" │
│ └── Dockerfile → docker build → docker run │
├─────────────────────────────────────────────────────────────┤
│ 运维视角 │
│ Kubernetes: "我管理1000个容器,自动扩缩容、自愈、灰度发布" │
│ └── Deployment → Service → Ingress → HPA │
├─────────────────────────────────────────────────────────────┤
│ 关系:Docker 是 K8s 的"运行时"之一(通过 containerd 对接) │
│ K8s 1.24+ 移除 dockershim,直接使用 containerd/CRI-O │
└─────────────────────────────────────────────────────────────┘
四、Docker 镜像管理详解
4.1 镜像生命周期管理
# 搜索镜像(Docker Hub 官方仓库)
docker search nginx
# NAME DESCRIPTION STARS OFFICIAL AUTOMATED
# nginx Official build of Nginx. 18000 [OK]
# bitnami/nginx Bitnami nginx Docker Image 100 [OK]
# 拉取镜像(推荐明确版本标签,避免 latest 陷阱)
docker pull nginx:1.24.0-alpine # Alpine 版:轻量、安全,仅 5MB 基础
docker pull nginx:1.24.0 # Debian 版:兼容性好,约 50MB
docker pull nginx@sha256:abc123... # 按摘要拉取,确保不可变
# 查看本地镜像
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}\t{{.CreatedAt}}"
# REPOSITORY TAG SIZE CREATED AT
# nginx 1.24.0 52.1MB 2023-10-25 08:23:45 +0000 UTC
# mysql 8.0.35 632MB 2023-11-02 14:15:22 +0000 UTC
# 查看镜像历史(分析构建过程,排查安全问题)
docker history --no-trunc nginx:1.24.0
# IMAGE CREATED BY SIZE COMMENT
# 605c77e624dd /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon… 0B 元数据层
# <missing> /bin/sh -c #(nop) EXPOSE 80 0B 暴露端口
# <missing> /bin/sh -c #(nop) COPY file:xxx in /etc/nginx 4.2kB 拷贝配置
# <missing> /bin/sh -c apt-get update && apt-get install… 45.6MB 安装软件
# <missing> /bin/sh -c #(nop) FROM debian:bullseye-slim 45.2MB 基础镜像
# 删除镜像(需无容器引用)
docker rmi nginx:1.24.0
docker rmi -f nginx:1.24.0 # 强制删除(有容器时也删)
# 清理悬空镜像(无标签、无容器引用)
docker image prune -f
# 清理全部未使用镜像(谨慎!)
docker image prune -a -f --filter "until=240h" # 保留10天内使用的
4.2 镜像导出与迁移
方案一:save/load(完整镜像,含历史和元数据)
# 导出镜像为 tar 包(适合完整备份、跨平台迁移)
docker save mysql:8.0.35 | gzip > mysql-8.0.35.tar.gz
# 或保留未压缩格式(更快,但更大)
docker save mysql:8.0.35 -o mysql-8.0.35.tar
# 查看 tar 包信息
tar -tf mysql-8.0.35.tar | head -20
# manifest.json repositories 各层 tar 文件...
# 传输到其他机器后导入
gunzip -c mysql-8.0.35.tar.gz | docker load
# 或
docker load -i mysql-8.0.35.tar
# 验证导入成功
docker images mysql:8.0.35
方案二:export/import(仅文件系统,无历史和配置)
# 从运行容器导出(当前状态的快照)
docker run -d --name temp-ubuntu ubuntu:22.04 sleep 3600
docker exec temp-ubuntu apt update
docker exec temp-ubuntu apt install -y vim curl
# 导出容器当前状态(扁平化)
docker export temp-ubuntu -o ubuntu-dev-environment.tar
# 仅 180MB,而原镜像+安装层可能 250MB+
# 导入为镜像(注意:会丢失 ENTRYPOINT/CMD/EXPOSE 等元数据!)
cat ubuntu-dev-environment.tar | docker import - ubuntu:dev-v1
# 查看导入的镜像(单层,无历史)
docker history ubuntu:dev-v1
# IMAGE CREATED CREATED BY SIZE
# abc123def456 30 seconds ago 185MB ← 单层,无构建历史
# 必须手动指定启动命令
docker run -it ubuntu:dev-v1 /bin/bash
# 或创建新镜像时补充元数据
docker import --change "CMD [\"/bin/bash\"]" --change "EXPOSE 8080" \
ubuntu-dev-environment.tar ubuntu:dev-v2
| 对比项 | docker save/load | docker export/import |
|---|
| 导出对象 | 镜像(Image) | 容器(Container) |
| 包含内容 | 完整分层历史、元数据、配置 | 仅扁平化文件系统 |
| 体积 | 较大(保留多层) | 较小(单层压缩) |
| 元数据保留 | ✅ ENTRYPOINT/CMD/EXPOSE/ENV | ❌ 需手动指定或重建 |
| 使用场景 | 镜像分发、版本归档、合规审计 | 容器迁移、系统模板、取证 |
| 安全性 | 可验证每层签名 | 需信任导出时无恶意软件 |
五、Docker 容器生命周期管理
5.1 创建与启动
# 基础运行(前台阻塞,Ctrl+C 停止)
docker run nginx:1.24
# 生产标准用法(后台守护 + 命名 + 端口映射 + 卷挂载 + 资源限制)
docker run -d \
--name web-nginx \
--hostname nginx-server \
-p 8080:80 \
-p 8443:443 \
-v /host/html:/usr/share/nginx/html:ro \
-v /host/nginx.conf:/etc/nginx/nginx.conf:ro \
-v /host/certs:/etc/nginx/certs:ro \
-e NGINX_WORKER_PROCESSES=auto \
-e TZ=Asia/Shanghai \
--memory 512m \
--memory-swap 512m \
--cpus 1.0 \
--pids-limit 100 \
--restart unless-stopped \
--health-cmd="curl -f http://localhost/ || exit 1" \
--health-interval=30s \
--health-retries=3 \
--security-opt no-new-privileges:true \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
nginx:1.24-alpine
# 参数详解:
# -d, --detach 后台运行(daemon模式)
# --name 指定容器名(否则随机生成如:vigilant_babbage)
# --hostname 容器内主机名
# -p 宿主机:容器 端口映射(可多次 -p,支持 UDP:-p 53:53/udp)
# -v 宿主机:容器[:ro] 卷挂载(ro=只读,rw=读写默认)
# -e KEY=VALUE 环境变量
# --memory 内存硬限制(含 --memory-swap 控制交换)
# --cpus CPU 核心数限制(1.5 = 1核半)
# --restart 重启策略:no|on-failure[:max-retries]|always|unless-stopped
# --health-cmd 健康检查命令(支持 HTTP/TCP/自定义)
# --security-opt 安全选项(禁止提权、只读根文件系统等)
# --cap-drop/add 精简 Linux Capabilities(降权)
5.2 重启策略详解
| 策略 | 说明 | 使用场景 | 注意事项 |
|---|
no | 不自动重启(默认) | 一次性任务、批处理作业 | 需手动管理失败 |
on-failure | 退出码非0时重启 | 可能崩溃的应用、依赖外部服务 | 可设最大重试次数 |
always | 总是重启 | 关键服务 | 维护时会反复重启,慎用 |
unless-stopped | 总是重启,除非手动停止 | 推荐生产使用 | 维护时停止,宿主机重启后恢复 |
# 查看容器重启次数
docker inspect -f '{{.RestartCount}}' web-nginx
# 查看最后停止原因
docker inspect -f '{{.State.Error}}' web-nginx
5.3 容器状态管理
# 查看运行中容器
docker ps
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# a1b2c3d4e5f6 nginx:1.24 "/docker-entrypoint.…" 2 hours ago Up 2 hours (healthy) 0.0.0.0:8080->80/tcp, 0.0.0.0:8443->443/tcp web-nginx
# 查看全部容器(包括已停止)
docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
# NAMES STATUS PORTS
# web-nginx Up 2 hours (healthy) 0.0.0.0:8080->80/tcp
# db-mysql Exited (137) 3 hours ago
# cache-redis Restarting (1) 5 seconds ago
# 启动/停止/重启
docker start web-nginx
docker stop web-nginx # 优雅停止:SIGTERM → 10秒 → SIGKILL
docker stop -t 60 web-nginx # 延长优雅期到60秒(数据库等需清理场景)
docker restart web-nginx
# 强制停止(相当于 kill -9,数据可能损坏)
docker kill web-nginx
docker kill -s SIGTERM web-nginx # 发送特定信号
# 暂停/恢复(冻结进程,内存不释放,用于临时资源让渡)
docker pause web-nginx # 所有进程挂起
docker unpause web-nginx # 恢复运行
# 等待容器退出并获取状态码
docker wait web-nginx # 阻塞直到停止,输出退出码
5.4 进入运行中的容器
# 方案一:exec 启动新进程(推荐!不影响主进程,随时进入)
docker exec -it web-nginx /bin/bash
# -i, --interactive 保持 STDIN 打开
# -t, --tty 分配伪终端(支持命令行交互)
# 退出方式:exit 或 Ctrl+D → 仅退出 exec 进程,容器继续运行
# 以特定用户身份进入
docker exec -u www-data -it web-nginx /bin/sh
# 在容器内执行单条命令(无需交互)
docker exec web-nginx nginx -t # 测试配置语法
docker exec web-nginx ps aux # 查看进程
docker exec web-nginx kill -HUP 1 # 发送信号重载配置
# 方案二:attach 附加到主进程(慎用!)
docker attach web-nginx
# 退出方式:
# Ctrl+P,Q 分离(容器继续运行)
# Ctrl+C 发送 SIGINT,容器主进程可能退出!
# 方案三:nsenter(无需 Docker 客户端,底层调试)
# 进入容器的网络命名空间(排查网络问题)
nsenter -t $(docker inspect -f '{{.State.Pid}}' web-nginx) -n /bin/bash
# 进入容器的所有命名空间(完全等同于容器内)
nsenter --target $(docker inspect -f '{{.State.Pid}}' web-nginx) \
--mount --uts --ipc --net --pid -- /bin/bash
5.5 日志与监控
# 查看容器日志
docker logs web-nginx
docker logs -f web-nginx # 实时跟踪(tail -f 效果)
docker logs --tail 100 web-nginx # 最后100行
docker logs --since 10m web-nginx # 最近10分钟
docker logs -t web-nginx # 显示时间戳
docker logs --until 2023-11-01T10:00:00 web-nginx # 直到指定时间
# 清理日志(避免占满磁盘)
echo "" | sudo tee $(docker inspect -f '{{.LogPath}}' web-nginx)
# 查看容器底层信息(JSON格式,含IP、挂载、环境变量等)
docker inspect web-nginx
docker inspect -f '{{.NetworkSettings.IPAddress}}' web-nginx # 提取IP
docker inspect -f '{{range .Mounts}}{{.Source}} -> {{.Destination}}{{printf "\n"}}{{end}}' web-nginx # 挂载点
docker inspect -f '{{.Config.Env}}' web-nginx # 环境变量
# 实时资源监控
docker stats web-nginx # 实时 CPU/内存/网络/IO
docker stats --no-stream # 只输出一次(脚本用)
# 容器内进程列表
docker top web-nginx
docker top web-nginx -aux # 完整格式
5.6 容器清理与维护
# 删除单个容器(需先停止)
docker rm web-nginx
docker rm -f web-nginx # 强制删除(运行中也删)
# 批量删除已停止容器
docker container prune -f
# 或旧写法
docker rm $(docker ps -aq -f status=exited)
# 删除停止+指定标签的容器
docker ps -aq -f status=exited -f label=env=test | xargs docker rm
# 一键清理系统(危险!会删除:)
# - 所有停止的容器
# - 所有悬空镜像(无标签)
# - 所有未使用卷
# - 所有未使用网络
docker system prune -f
# 彻底清理(包括所有未使用镜像,不仅仅是悬空的)
docker system prune -a -f --volumes
# 查看空间占用详情
docker system df -v
# TYPE TOTAL ACTIVE SIZE RECLAIMABLE
# Images 15 5 4.234GB 2.891GB (68%)
# Containers 8 3 1.234GB 890.5MB (72%)
# Local Volumes 12 4 2.456GB 1.789GB (72%)
# Build Cache 20 0 1.123GB 1.123GB (100%)
六、数据持久化与文件传输
6.1 容器与宿主机文件拷贝
# 宿主机 → 容器(文件或目录)
docker cp /host/app.conf web-nginx:/etc/nginx/conf.d/default.conf
docker cp ./static-html/ web-nginx:/usr/share/nginx/html/ # 拷贝目录
# 容器 → 宿主机(即使容器已停止也可拷贝!)
docker cp web-nginx:/etc/nginx/nginx.conf ./backup/nginx-$(date +%Y%m%d).conf
docker cp web-nginx:/var/log/nginx/ ./logs/
# 从已停止容器恢复数据(救命技巧)
docker ps -a -f exited=1 -f name=db # 找到崩溃的数据库容器
docker cp $(docker ps -aq -f exited=1 -f name=db):/var/lib/mysql ./recovered-db/
# 通过 tar 流式传输(适合大文件,显示进度)
tar -cf - ./data | docker exec -i web-nginx tar -xf - -C /app/data
6.2 卷(Volume)管理(推荐的数据持久化)
# 创建命名卷
docker volume create mysql-data
docker volume create --driver local \
--opt type=nfs \
--opt o=addr=192.168.1.100,rw \
--opt device=:/path/to/dir \
nfs-volume # NFS 远程卷
# 查看卷详情
docker volume inspect mysql-data
# [
# {
# "CreatedAt": "2023-11-15T10:30:00Z",
# "Driver": "local",
# "Labels": null,
# "Mountpoint": "/var/lib/docker/volumes/mysql-data/_data",
# "Name": "mysql-data",
# "Options": null,
# "Scope": "local"
# }
# ]
# 使用卷运行容器
docker run -d \
--name mysql-prod \
-v mysql-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/mysql-root \
-e MYSQL_DATABASE=app \
mysql:8.0 \
--default-authentication-plugin=mysql_native_password
# 卷备份(方法一:tar 打包)
docker run --rm \
-v mysql-data:/data \
-v $(pwd):/backup \
alpine tar czf /backup/mysql-$(date +%Y%m%d).tar.gz -C /data .
# 卷备份(方法二:使用卷驱动快照,如 LVM/ceph)
docker volume create --driver vieux/sshfs \
-o sshcmd=user@host:/path \
-o password=secret \
ssh-volume
# 恢复卷数据
docker run --rm \
-v mysql-data:/data \
-v $(pwd):/backup \
alpine sh -c "cd /data && tar xzf /backup/mysql-20231115.tar.gz"
# 清理未使用卷
docker volume ls -f dangling=true
docker volume prune -f
6.3 绑定挂载 vs 卷 vs tmpfs
| 特性 | 绑定挂载(Bind Mount) | 命名卷(Volume) | tmpfs 挂载 |
|---|
| 语法 | -v /host/path:/container/path | -v vol-name:/path | --tmpfs /path |
| 存储位置 | 宿主机任意路径 | Docker 管理目录(/var/lib/docker/volumes/) | 宿主机内存 |
| 生命周期 | 独立于容器 | 容器删除后保留,需手动删 | 容器停止即消失 |
| 备份迁移 | 直接操作文件 | 需 docker cp 或卷插件 | 无需备份 |
| 性能 | 依赖宿主机文件系统 | 原生性能,支持驱动扩展 | 内存速度,无磁盘IO |
| 适用场景 | 开发环境代码挂载 | 生产数据持久化 | 敏感数据、临时缓存 |
七、镜像加速器与生产配置
7.1 国内镜像加速器配置
# 创建/编辑配置文件
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json << 'EOF'
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com",
"https://ccr.ccs.tencentyun.com",
"https://docker.m.daocloud.io"
],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3",
"labels": "production_status,environment",
"env": "OS_VERSION,CUDA_VERSION"
},
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
],
"live-restore": true,
"userland-proxy": false,
"no-new-privileges": true,
"seccomp-profile": "/etc/docker/seccomp-default.json"
}
EOF
# 重载配置并重启
sudo systemctl daemon-reload
sudo systemctl restart docker
# 验证加速器生效
docker info | grep -A 10 "Registry Mirrors"
7.2 生产环境守护进程调优
| 配置项 | 建议值 | 说明 |
|---|
live-restore | true | Docker 重启时容器不停止 |
userland-proxy | false | 减少端口映射性能损耗 |
no-new-privileges | true | 全局禁止容器提权 |
seccomp-profile | 自定义 | 系统调用过滤 |
log-opts.max-size | 100m | 防止日志占满磁盘 |
storage-driver | overlay2 | 当前最佳存储驱动 |
八、Docker 安全最佳实践
# 1. 以非 root 用户运行容器
docker run -d --user 1000:1000 nginx
# 2. 只读根文件系统 + 临时可写层
docker run -d --read-only --tmpfs /tmp --tmpfs /var/run nginx
# 3. 资源限制防止 DoS
docker run -d \
--memory 512m \
--memory-swap 512m \
--cpus 1.0 \
--pids-limit 100 \
--no-new-privileges \
app
# 4. 网络隔离(自定义桥接,非默认 bridge)
docker network create --driver bridge --subnet 172.28.0.0/16 isolated-net
docker run -d --network isolated-net app
# 5. 镜像安全扫描
docker scan myimage:latest # 集成 Snyk
trivy image myimage:latest # 更全面的开源扫描
九、命令速查表
| 操作类别 | 命令 |
|---|
| 镜像管理 | |
| 搜索 | docker search nginx |
| 拉取 | docker pull nginx:1.24 |
| 构建 | docker build -t myapp:v1 . |
| 查看 | docker images |
| 删除 | docker rmi nginx:1.24 |
| 导出 | docker save nginx -o nginx.tar |
| 导入 | docker load -i nginx.tar |
| 容器生命周期 | |
| 运行 | docker run -d -p 80:80 --name web nginx |
| 查看运行 | docker ps |
| 查看全部 | docker ps -a |
| 进入 | docker exec -it web /bin/bash |
| 日志 | docker logs -f web |
| 停止/启动 | docker stop/start web |
| 删除 | docker rm web / docker rm -f web |
| 文件与数据 | |
| 拷贝 | docker cp web:/etc/nginx/nginx.conf ./ |
| 卷创建 | docker volume create myvol |
| 卷使用 | docker run -v myvol:/data app |
| 系统维护 | |
| 清理容器 | docker container prune -f |
| 清理镜像 | docker image prune -a -f |
| 全盘清理 | docker system prune -a --volumes |
| 磁盘使用 | docker system df -v |
十、总结与演进方向
Docker 作为容器化技术的开创者,核心价值在于标准化交付(Build, Ship, Run)。掌握以下关键点,可应对绝大多数生产场景:
- 镜像分层:理解 UnionFS,优化 Dockerfile 层缓存
- 资源隔离:Namespace + Cgroups 是容器安全的根基
- 数据持久化:卷(Volume)优于绑定挂载,生产必备
- 健康检查:--health-cmd 实现自 healing
- 安全降权:非 root、只读文件系统、Capability 裁剪
未来演进:
- Podman:无守护进程、rootless 容器,逐渐替代 Docker CLI
- WebAssembly:更轻量的运行时,启动速度比容器快 100x
- eBPF:内核级可观测性和安全策略,增强容器边界
但无论如何演进,Docker 奠定的容器化思维和OCI 标准将持续影响云原生生态十年以上。