📌 引言:理解Docker的三驾马车

如果说Docker是一艘现代化的货轮,那么:

  • 镜像(Image) 就是标准化的集装箱设计蓝图
  • 容器(Container) 就是实际装载货物的运行中的集装箱
  • 仓库(Registry) 就是全球分布的集装箱码头和仓库

这三者构成了Docker生态系统的核心三角,理解它们的关系是掌握Docker技术的关键。

🏗️ 第一章:Docker镜像(Image)深度解析

1.1 什么是Docker镜像?

官方定义:Docker镜像是用于创建Docker容器的只读模板,包含了运行应用所需的一切——代码、运行时、库、环境变量和配置文件。

通俗理解:镜像就像是软件的安装包,但更强大:

  • ✅ 包含了软件及其所有依赖
  • ✅ 包含了完整的运行环境
  • ✅ 是分层的、只读的
  • ✅ 可版本控制的软件交付物

1.2 镜像分层架构(Layer Architecture)

Docker镜像分层结构

容器可写层
Container Layer
R/W

基础层
Base Layer
R/O

工具层
Tools Layer
R/O

配置层
Config Layer
R/O

应用层
App Layer
R/O

1.3 镜像分层详解与示例

示例:一个Node.js应用的镜像分层
# Dockerfile示例
FROM node:14-alpine           # ← 第1层:基础镜像层 (约110MB)
RUN apk add --no-cache git    # ← 第2层:工具层 (约5MB)
WORKDIR /app                  # ← 第3层:配置层 (元数据)
COPY package*.json ./         # ← 第4层:依赖定义层 (几KB)
RUN npm install              # ← 第5层:依赖安装层 (约200MB)
COPY . .                      # ← 第6层:应用代码层 (约50MB)
CMD ["npm", "start"]         # ← 第7层:启动命令层 (元数据)

实际存储结构:

镜像:myapp:latest
├── Layer 7: sha256:789... (启动命令,几字节)
├── Layer 6: sha256:456... (应用代码,50MB)
├── Layer 5: sha256:345... (node_modules,200MB)
├── Layer 4: sha256:234... (package.json,几KB)
├── Layer 3: sha256:123... (工作目录配置,元数据)
├── Layer 2: sha256:abc... (git工具,5MB)
└── Layer 1: sha256:def... (node:14-alpine,110MB)

1.4 镜像分层的优势

1. 存储效率:共享基础层

# 多个镜像共享相同的基础层
镜像A:ubuntu层(72MB) + 我的应用(10MB) = 82MB
镜像B:ubuntu层(72MB) + 他的应用(15MB) = 87MB
实际存储:72MB + 10MB + 15MB = 97MB(不是159MB!)

2. 构建速度:缓存机制

# Dockerfile构建时的缓存使用
FROM ubuntu:20.04           # ← 如果本地已有,直接使用缓存
RUN apt update              # ← 如果没有更改,使用缓存
RUN apt install -y python3  # ← 如果没有更改,使用缓存
COPY app.py /app/           # ← 文件改变,此层及之后重新构建
CMD ["python3", "/app/app.py"]

3. 可追溯性:每层都有独立ID

# 查看镜像分层信息
docker history myapp:latest

# 输出:
IMAGE          CREATED       CREATED BY                                      SIZE
789def...      2 hours ago   /bin/sh -c #(nop)  CMD ["npm" "start"]         0B
456abc...      2 hours ago   /bin/sh -c COPY . .                             50MB
345ghi...      2 hours ago   /bin/sh -c RUN npm install                      200MB
...

1.5 镜像操作命令大全

# 查看镜像
docker images
docker image ls
docker images --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}\t{{.Size}}"

# 搜索镜像
docker search nginx
docker search --filter stars=1000 --filter is-official=true nginx

# 拉取镜像
docker pull ubuntu:20.04
docker pull nginx:latest
docker pull nginx:alpine  # 更小的Alpine版本

# 构建镜像
docker build -t myapp:1.0 .
docker build -t myapp:latest -f Dockerfile.prod .
docker build --no-cache -t myapp:clean .  # 不使用缓存

# 标记镜像
docker tag myapp:1.0 myregistry.com/team/myapp:1.0
docker tag nginx:latest mynginx:v1

# 删除镜像
docker rmi myapp:1.0
docker image rm ubuntu:18.04
docker rmi $(docker images -q)  # 删除所有镜像(谨慎!)

# 导出导入镜像
docker save -o myapp.tar myapp:1.0
docker load < myapp.tar

# 镜像详细信息
docker image inspect myapp:latest
docker inspect --format='{{.Id}}' myapp:latest

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

🚀 第二章:Docker容器(Container)全面掌握

2.1 什么是Docker容器?

容器定义:容器是镜像的运行实例。你可以创建、启动、停止、移动或删除容器。每个容器都是隔离且安全的应用程序平台。

关键特性:

  • ✅ 轻量级:共享主机内核,资源占用少
  • ✅ 可移植:在任何Docker环境中运行相同
  • ✅ 隔离性:拥有独立的文件系统、网络、进程空间
  • ✅ 临时性:默认情况下,容器停止后数据丢失(除非使用卷)

2.2 容器与镜像的关系

实例化

提交

容器 = 镜像层 + 可写层

镜像层: 只读

容器层: 可读可写

多层结构

基础层 ubuntu

工具层

应用层

Docker镜像
Image
只读模板

Docker容器
Container
运行实例

新镜像
基于容器创建

2.3 容器生命周期完整流程图

docker create

docker start
docker run

docker pause

docker unpause

docker stop
自然结束

docker start

docker rm → docker create

docker rm

docker rm -f

Created

Running

Paused

Stopped

容器已创建但未运行
已分配文件系统、网络配置
但进程未启动

容器正在运行
进程活跃
可提供服务

进程暂停(cgroups冻结)
不消耗CPU资源
内存状态保留

进程已终止
资源未完全释放
文件系统保留
可重新启动

2.4 容器生命周期各阶段详解

阶段1:创建(Created)
# 创建容器但不启动
docker create --name mynginx nginx:latest

# 创建时配置参数
docker create \
  --name webapp \
  -p 8080:80 \
  -v /data:/usr/share/nginx/html \
  -e NGINX_PORT=80 \
  --network mynet \
  nginx:alpine

此时容器状态:

  • 文件系统:基于镜像创建,添加可写层
  • 网络:分配网络接口但未激活
  • 进程:尚未启动
  • 资源:分配但未使用
阶段2:运行(Running)
# 启动已创建的容器
docker start mynginx

# 创建并直接运行(最常用)
docker run -d --name myapp -p 3000:3000 node:14

# 交互式运行容器
docker run -it ubuntu:20.04 /bin/bash

运行中的容器特性:

容器内部视图:
+-------------------------------------------------+
| PID命名空间: 隔离的进程树                       |
|   1: /usr/bin/node app.js (主进程)             |
|   15: nginx worker process                     |
|   16: nginx worker process                     |
+-------------------------------------------------+
| 网络命名空间: 独立的网络栈                      |
|   eth0: 172.17.0.2/16 (虚拟网卡)               |
|   lo: 127.0.0.1 (回环地址)                     |
+-------------------------------------------------+
| Mount命名空间: 独立的文件系统                   |
|   /: 只读镜像层 + 可写层                        |
|   /data: 绑定挂载的主机目录                     |
|   /tmp: 临时文件系统                            |
+-------------------------------------------------+
阶段3:暂停(Paused)
# 暂停运行中的容器
docker pause mynginx

# 恢复暂停的容器
docker unpause mynginx

暂停机制:

  • 使用cgroup freezer技术
  • 暂停所有进程但不释放内存
  • CPU使用率降为0
  • 快速恢复(毫秒级)
阶段4:停止(Stopped)
# 优雅停止容器(发送SIGTERM信号)
docker stop mynginx

# 强制停止容器(发送SIGKILL信号)
docker kill mynginx

# 设置停止超时时间
docker stop -t 30 mynginx  # 30秒后强制停止

停止过程:

优雅停止流程:
1. docker stop → 发送SIGTERM信号
2. 应用收到信号,执行清理操作
3. 等待10秒(默认)
4. 如果仍在运行 → 发送SIGKILL强制终止

强制停止流程:
1. docker kill → 直接发送SIGKILL
2. 进程立即终止,无清理机会
阶段5:删除(Deleted)
# 删除已停止的容器
docker rm mynginx

# 强制删除运行中的容器
docker rm -f mynginx

# 删除所有已停止的容器
docker container prune

删除影响:

  • 容器可写层数据丢失
  • 释放容器占用的资源
  • 网络接口、IP地址回收
  • 卷不会被自动删除(除非使用-v参数)

2.5 容器操作命令大全

# 创建容器
docker create --name mycontainer nginx
docker run -d --name web -p 80:80 nginx

# 查看容器
docker ps                  # 运行中的容器
docker ps -a               # 所有容器
docker ps -l               # 最近创建的容器
docker ps -q               # 只显示容器ID
docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Status}}"

# 启动/停止容器
docker start mycontainer
docker stop mycontainer
docker restart mycontainer
docker kill mycontainer    # 强制停止

# 暂停/恢复容器
docker pause mycontainer
docker unpause mycontainer

# 进入容器
docker exec -it mycontainer /bin/bash
docker exec mycontainer ls /app
docker exec -u root mycontainer whoami

# 查看容器信息
docker logs mycontainer
docker logs -f mycontainer        # 实时日志
docker logs --tail 100 mycontainer
docker logs --since 10m mycontainer

docker stats mycontainer          # 资源使用情况
docker top mycontainer            # 容器内进程
docker inspect mycontainer        # 详细信息
docker port mycontainer           # 端口映射

# 文件操作
docker cp mycontainer:/app/logs ./logs/
docker cp config.json mycontainer:/app/

# 重命名容器
docker rename old_name new_name

# 更新容器配置
docker update --memory 512m mycontainer
docker update --cpus 1.5 mycontainer

# 导出/导入容器
docker export mycontainer > mycontainer.tar
docker import mycontainer.tar myimage:new

# 提交容器为镜像
docker commit mycontainer myapp:v2

# 清理容器
docker container prune
docker rm $(docker ps -aq)        # 删除所有容器

2.6 容器状态监控与管理

# 实时监控容器状态
watch docker ps

# 监控容器资源使用
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"

# 查看容器资源限制
docker inspect --format='{{.HostConfig.Memory}}' mycontainer
docker inspect --format='{{.HostConfig.NanoCpus}}' mycontainer

# 容器健康检查
docker inspect --format='{{.State.Health.Status}}' mycontainer

# 容器事件监控
docker events --filter 'container=mycontainer'

📦 第三章:Docker仓库(Registry)完全指南

3.1 什么是Docker仓库?

仓库定义:Docker仓库用于存储和分发Docker镜像。仓库分为公共仓库和私有仓库。

仓库层次结构:

仓库生态系统:
┌─────────────────────────────────────────────┐
│          Docker Registry (仓库服务)          │
├─────────────────────────────────────────────┤
│          Repository (镜像仓库)               │
│  ├── library/ubuntu (官方仓库)               │
│  ├── bitnami/nginx (组织仓库)               │
│  └── username/myapp (个人仓库)               │
├─────────────────────────────────────────────┤
│              Image (镜像)                    │
│  ├── ubuntu:20.04 (标签)                    │
│  ├── ubuntu:18.04                          │
│  └── ubuntu:latest                         │
├─────────────────────────────────────────────┤
│               Tag (标签)                     │
│  ├── 描述镜像版本                           │
│  ├── 支持多标签指向同一镜像                  │
│  └── latest为默认标签                       │
└─────────────────────────────────────────────┘

3.2 公共仓库 vs 私有仓库

特性Docker Hub(公共)私有仓库(Harbor)
访问权限公开(部分私有)完全控制访问权限
存储限制免费用户有限制根据硬件自定义
传输速度依赖网络状况内网高速传输
安全性基础安全扫描企业级安全策略
成本免费/付费订阅自建硬件成本
适用场景个人/开源项目企业生产环境

3.3 Docker Hub使用详解

镜像命名规范
完整镜像名格式:
[registry_host]/[namespace]/[repository]:[tag]

示例解析:
docker.io/library/nginx:latest
├── docker.io: 注册中心(可省略,默认Docker Hub)
├── library:   命名空间(官方镜像省略,个人/组织必填)
├── nginx:     仓库名
└── latest:    标签

常用简写:
nginx:latest           → docker.io/library/nginx:latest
ubuntu:20.04           → docker.io/library/ubuntu:20.04
bitnami/redis:latest   → docker.io/bitnami/redis:latest
mycompany/myapp:v1.0   → docker.io/mycompany/myapp:v1.0
Docker Hub操作命令
# 登录Docker Hub
docker login
docker login -u username -p password

# 推送镜像到Docker Hub
docker tag myapp:latest username/myapp:latest
docker push username/myapp:latest

# 拉取镜像
docker pull ubuntu:20.04
docker pull username/myapp:v1.0

# 搜索镜像
docker search nginx --filter stars=1000
docker search --filter is-official=true python

# 查看镜像信息
docker inspect ubuntu:20.04

# 登出
docker logout

3.4 私有仓库搭建与使用

搭建Harbor私有仓库
# 1. 下载Harbor安装包
wget https://github.com/goharbor/harbor/releases/download/v2.4.0/harbor-offline-installer-v2.4.0.tgz

# 2. 解压并配置
tar xzf harbor-offline-installer-v2.4.0.tgz
cd harbor
cp harbor.yml.tmpl harbor.yml

# 编辑配置文件
vim harbor.yml
# 修改hostname、端口、数据目录等

# 3. 安装并启动
./install.sh

# 4. 访问Web界面
# https://your-harbor-host
私有仓库操作
# 登录私有仓库
docker login harbor.example.com

# 标记镜像
docker tag myapp:latest harbor.example.com/myproject/myapp:latest

# 推送镜像
docker push harbor.example.com/myproject/myapp:latest

# 拉取镜像
docker pull harbor.example.com/myproject/myapp:latest

# 查看仓库中的镜像
curl -u admin:password https://harbor.example.com/api/v2.0/projects/myproject/repositories/myapp/artifacts

3.5 镜像仓库架构图

安全层

Docker Registry V2

客户端 Client

镜像仓库

核心服务

存储后端

Docker CLI

Docker Desktop

CI/CD工具

文件系统

S3对象存储

Azure Blob

Google Cloud Storage

认证服务 Auth

存储服务 Storage

通知服务 Notification

缓存服务 Cache

Project1/App1

Project1/App2

Project2/Service1

TLS/SSL加密

基于角色访问控制

漏洞扫描

镜像签名

🔄 第四章:镜像、容器、仓库的协同工作

4.1 完整的Docker工作流

生产环境镜像仓库CI服务器开发者生产环境镜像仓库CI服务器开发者开发阶段集成阶段部署阶段版本管理编写代码 + Dockerfiledocker build -t myapp:v1 .docker run myapp:v1 (本地测试)推送代码到Git仓库拉取代码docker build -t registry/myapp:$BUILD_ID .运行测试docker push registry/myapp:$BUILD_IDdocker pull registry/myapp:$BUILD_IDdocker run -d registry/myapp:$BUILD_ID监控与维护docker pull registry/myapp:v1.1 (更新)推送新版本滚动更新

4.2 实际工作场景示例

场景1:开发到部署全流程
# 1. 开发者在本地构建镜像
docker build -t myapp:dev .

# 2. 本地测试运行
docker run -p 3000:3000 myapp:dev

# 3. 推送到测试仓库
docker tag myapp:dev test-registry.com/myapp:build-123
docker push test-registry.com/myapp:build-123

# 4. 测试环境部署
docker pull test-registry.com/myapp:build-123
docker run -d --name myapp-test test-registry.com/myapp:build-123

# 5. 推送到生产仓库
docker tag test-registry.com/myapp:build-123 prod-registry.com/myapp:v1.0
docker push prod-registry.com/myapp:v1.0

# 6. 生产环境部署
docker pull prod-registry.com/myapp:v1.0
docker run -d --restart=always prod-registry.com/myapp:v1.0
场景2:多环境配置管理
# docker-compose.yml
version: '3.8'
services:
  app:
    image: myregistry.com/myapp:${TAG:-latest}
    environment:
      - NODE_ENV=${NODE_ENV:-development}
      - DB_HOST=${DB_HOST:-db}
    ports:
      - "${PORT:-3000}:3000"
    volumes:
      - ./logs:/app/logs

# 开发环境
export TAG=dev
export NODE_ENV=development
docker-compose up

# 生产环境  
export TAG=v1.0
export NODE_ENV=production
export DB_HOST=prod-db.example.com
docker-compose up -d

🎯 第五章:最佳实践与常见问题

5.1 镜像管理最佳实践

1. 使用官方基础镜像

# 推荐:使用官方镜像
FROM node:14-alpine

# 不推荐:从头开始构建
FROM scratch
ADD binary /

2. 合理分层,利用缓存

# 好的实践:依赖单独分层
COPY package*.json ./
RUN npm install
COPY . .

# 不好的实践:频繁变动的代码与依赖混合
COPY . .
RUN npm install  # 每次代码改动都会重新安装依赖

3. 使用多阶段构建

# 构建阶段
FROM golang:1.16 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp .

# 运行阶段
FROM alpine:latest
COPY --from=builder /app/myapp /usr/local/bin/
CMD ["myapp"]

5.2 容器运行最佳实践

1. 一个容器一个进程

# 推荐:每个容器一个主要进程
docker run -d --name web nginx
docker run -d --name app node:14

# 不推荐:一个容器运行多个服务
docker run -d --name all-in-one
# 里面运行:nginx + node + mysql + redis

2. 使用非root用户

# Dockerfile中创建非root用户
RUN groupadd -r appuser && useradd -r -g appuser appuser
USER appuser
CMD ["npm", "start"]

3. 设置资源限制

docker run -d \
  --memory="512m" \
  --cpus="1.5" \
  --restart=unless-stopped \
  myapp:latest

5.3 常见问题与解决方案

问题1:镜像太大
# 解决方案:多阶段构建 + Alpine基础镜像
# 之前:ubuntu + node = 1GB+
# 现在:alpine + 多阶段构建 = 100MB-

# 清理无用镜像
docker image prune -a --filter "until=24h"
问题2:容器数据丢失
# 解决方案:使用数据卷
docker run -d \
  -v /host/data:/container/data \
  -v myvolume:/app/storage \
  myapp:latest

# 备份卷数据
docker run --rm -v myvolume:/data -v $(pwd):/backup \
  alpine tar czf /backup/backup.tar.gz /data
问题3:容器间通信问题
# 解决方案:使用自定义网络
docker network create mynetwork
docker run -d --net=mynetwork --name db redis
docker run -d --net=mynetwork --name app myapp:latest
# 在app容器中可以通过"db"主机名访问redis

📊 第六章:监控与维护

6.1 镜像仓库监控

# 查看仓库使用情况
docker system df

# 查看镜像详细占用
docker system df -v

# 清理未使用的镜像
docker image prune -a

# 查看镜像依赖关系
docker image inspect --format='{{.RepoTags}} {{.Parent}}' myapp

6.2 容器状态监控

# 实时监控
docker stats --all --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}"

# 容器日志管理
docker logs --tail 100 -f mycontainer
docker logs --since $(date -d '1 hour ago' +%s) mycontainer

# 容器健康检查
docker inspect --format='{{json .State.Health}}' mycontainer

6.3 自动化清理脚本

#!/bin/bash
# cleanup-docker.sh

echo "=== Docker清理脚本 ==="

# 1. 停止所有运行中的容器
docker stop $(docker ps -q) 2>/dev/null

# 2. 删除所有容器
docker rm $(docker ps -aq) 2>/dev/null

# 3. 删除所有未使用的镜像
docker image prune -af

# 4. 删除所有未使用的卷
docker volume prune -f

# 5. 删除未使用的网络
docker network prune -f

# 6. 清理构建缓存
docker builder prune -af

echo "清理完成!"
docker system df

🚀 总结与下一步

核心要点回顾

  1. 镜像是只读模板:分层存储,可复用,构建一次到处运行
  2. 容器是运行实例:轻量级,隔离,生命周期管理
  3. 仓库是分发中心:存储、分享、版本管理镜像

进阶学习路径

本篇: 核心概念

Dockerfile深度优化

Docker Compose编排

Docker网络与存储

容器安全实践

Kubernetes编排

实战挑战

  1. 挑战1:将一个现有的Web应用Docker化
  2. 挑战2:搭建私有镜像仓库并配置自动构建
  3. 挑战3:设计一个多容器应用(Web+DB+Cache)

💡 互动练习:
尝试执行以下命令序列,观察每一步的输出:

# 1. 拉取镜像
docker pull nginx:alpine

# 2. 查看镜像信息
docker images
docker history nginx:alpine

# 3. 运行容器
docker run -d --name myweb -p 8080:80 nginx:alpine

# 4. 查看容器状态
docker ps
docker logs myweb

# 5. 进入容器
docker exec -it myweb /bin/sh

# 6. 停止并清理
docker stop myweb
docker rm myweb
docker rmi nginx:alpine

📢 下篇预告:
下一篇我们将深入讲解《Dockerfile编写最佳实践》,内容包括:

  • Dockerfile指令详解
  • 多阶段构建高级技巧
  • 镜像优化与安全加固
  • 实战:从零构建生产级镜像

📌 思考题:

  1. 如果多个容器共享同一个基础镜像层,当该基础镜像更新时会发生什么?
  2. 容器停止后,对可写层的修改会保留吗?
  3. 如何在不同环境(开发/测试/生产)中使用不同的镜像仓库?

欢迎在评论区分享你的实践经验和遇到的问题!

更多推荐