Skip to content

第一阶段:Docker 基础入门


1.1 Docker 核心概念

1.1.1 什么是容器?

容器是一种轻量级的操作系统级虚拟化技术,它将应用及其所有依赖项打包在一起,使应用可以在任何环境中一致地运行。

核心思想:"Build once, run anywhere" — 一次构建,到处运行。

容器本质上是一个被隔离的进程,它运行在宿主机的内核之上,共享宿主机内核,但拥有自己独立的文件系统、网络栈、进程空间等。

1.1.2 容器 vs 虚拟机

┌─────────────────────────────────────────────────────┐
│                    虚拟机架构                         │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐            │
│  │   App A  │ │   App B  │ │   App C  │            │
│  │  Bins/Libs│ │ Bins/Libs│ │ Bins/Libs│            │
│  │ Guest OS │ │ Guest OS │ │ Guest OS │  ← 每个VM  │
│  └──────────┘ └──────────┘ └──────────┘   有完整OS  │
│  ┌─────────────────────────────────────┐            │
│  │           Hypervisor                │            │
│  └─────────────────────────────────────┘            │
│  ┌─────────────────────────────────────┐            │
│  │            Host OS                  │            │
│  └─────────────────────────────────────┘            │
│  ┌─────────────────────────────────────┐            │
│  │           Infrastructure            │            │
│  └─────────────────────────────────────┘            │
└─────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────┐
│                    容器架构                           │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐            │
│  │   App A  │ │   App B  │ │   App C  │            │
│  │  Bins/Libs│ │ Bins/Libs│ │ Bins/Libs│ ← 共享内核 │
│  └──────────┘ └──────────┘ └──────────┘   无Guest OS│
│  ┌─────────────────────────────────────┐            │
│  │          Docker Engine              │            │
│  └─────────────────────────────────────┘            │
│  ┌─────────────────────────────────────┐            │
│  │            Host OS                  │            │
│  └─────────────────────────────────────┘            │
│  ┌─────────────────────────────────────┐            │
│  │           Infrastructure            │            │
│  └─────────────────────────────────────┘            │
└─────────────────────────────────────────────────────┘
对比维度容器虚拟机
启动速度秒级分钟级
体积MB 级GB 级
性能接近原生有损耗(Hypervisor 开销)
隔离性进程级隔离(较弱)完整 OS 隔离(强)
内核共享宿主机内核独立内核
资源利用率高,可运行大量容器较低,每个 VM 占用大量资源
适用场景微服务、CI/CD、快速部署需要完全隔离、不同内核的场景

💡 一句话总结:虚拟机虚拟的是硬件,容器虚拟的是操作系统。

1.1.3 Docker 架构

Docker 采用 C/S(客户端-服务端)架构

┌──────────────────────────────────────────────────────────┐
│                                                          │
│   Docker Client (CLI)          Docker Host               │
│   ┌─────────────┐      ┌─────────────────────────┐      │
│   │ docker build │─────▶│     Docker Daemon        │      │
│   │ docker pull  │      │     (dockerd)            │      │
│   │ docker run   │      │                         │      │
│   └─────────────┘      │  ┌─────────┐ ┌────────┐│      │
│                         │  │Containers│ │ Images ││      │
│          REST API       │  └─────────┘ └────────┘│      │
│                         └──────────┬──────────────┘      │
│                                    │                     │
│                         ┌──────────▼──────────────┐      │
│                         │     Registry             │      │
│                         │   (Docker Hub / 私有)    │      │
│                         └─────────────────────────┘      │
└──────────────────────────────────────────────────────────┘

三大核心组件:

组件说明
Docker Client(CLI)用户与 Docker 交互的命令行工具,发送命令给 Docker Daemon
Docker Daemon(dockerd)后台守护进程,负责管理镜像、容器、网络、存储等
Docker Registry镜像仓库,存储和分发 Docker 镜像(如 Docker Hub)

工作流程:

  1. 用户通过 docker CLI 输入命令
  2. CLI 通过 REST API 将请求发送给 Docker Daemon
  3. Daemon 执行操作(拉取镜像、创建容器等)
  4. 需要时从 Registry 拉取/推送镜像

1.1.4 核心概念:镜像、容器、仓库

📦 镜像(Image)

  • 定义:只读的模板,包含运行应用所需的一切(代码、运行时、库、环境变量、配置文件)
  • 特点:分层存储(Layer),每一层都是只读的
  • 类比:可以理解为一个"类(Class)",是创建容器的蓝图
镜像分层结构示意:

┌──────────────────────┐
│    应用代码层         │  ← 最上层(你的应用)
├──────────────────────┤
│    依赖安装层         │  ← pip install / npm install
├──────────────────────┤
│    系统工具层         │  ← apt-get install
├──────────────────────┤
│    基础镜像层         │  ← ubuntu:22.04 / python:3.12
└──────────────────────┘

🚀 容器(Container)

  • 定义:镜像的运行实例,是一个独立的、可运行的进程
  • 特点:在镜像层之上添加一个可写层(读写层),容器的所有修改都发生在这一层
  • 类比:可以理解为"对象(Instance)",由镜像创建而来
  • 生命周期:创建 → 启动 → 运行 → 暂停 → 停止 → 删除
容器 = 镜像 + 可写层

┌──────────────────────┐
│    可写层(容器层)    │  ← 容器运行时的修改保存在这里
├══════════════════════┤
│    镜像层(只读)      │
│    ...               │
│    基础镜像层         │
└──────────────────────┘

🏪 仓库(Registry)

  • 定义:集中存储和分发 Docker 镜像的服务
  • Docker Hub:官方公共仓库,类似 GitHub 之于代码
  • 私有仓库:企业自建,如 Harbor、腾讯云 TCR
  • 仓库命名规则[registry_host/]namespace/repository:tag
    • 例:docker.io/library/nginx:1.25 → 可简写为 nginx:1.25

1.1.5 Docker 底层技术

Docker 依赖 Linux 内核的三大核心技术实现容器化:

🔒 Namespace — 资源隔离

Namespace 提供了进程级别的隔离,让容器认为自己独占了一台完整的机器。

Namespace隔离内容说明
PID进程 ID容器内进程 PID 从 1 开始
NET网络独立的网络栈、IP、端口
MNT文件系统挂载点容器有自己的根文件系统
UTS主机名和域名容器可以有自己的 hostname
IPC进程间通信隔离信号量、消息队列
USER用户和用户组容器内 root ≠ 宿主机 root
bash
# 查看一个容器的 namespace
ls -la /proc/<容器内PID>/ns/

# 输出示例:
# lrwxrwxrwx 1 root root 0 cgroup -> 'cgroup:[4026531835]'
# lrwxrwxrwx 1 root root 0 ipc -> 'ipc:[4026532xxx]'
# lrwxrwxrwx 1 root root 0 mnt -> 'mnt:[4026532xxx]'
# lrwxrwxrwx 1 root root 0 net -> 'net:[4026532xxx]'
# lrwxrwxrwx 1 root root 0 pid -> 'pid:[4026532xxx]'
# lrwxrwxrwx 1 root root 0 user -> 'user:[4026531837]'
# lrwxrwxrwx 1 root root 0 uts -> 'uts:[4026532xxx]'

⚙️ Cgroups — 资源限制

Control Groups(Cgroups)用于限制、记录和隔离进程组所使用的物理资源

资源控制能力
CPU限制 CPU 使用时间或核心数
Memory限制内存使用上限,超出可 OOM Kill
I/O限制磁盘读写速率
Network限制网络带宽(通过 tc 配合)
bash
# Docker 中限制容器资源的示例
docker run -d \
  --name my-app \
  --memory="512m" \        # 限制内存 512MB
  --cpus="1.5" \           # 限制使用 1.5 个 CPU 核心
  --memory-swap="1g" \     # 限制 swap 1GB
  nginx

# 查看容器资源使用情况
docker stats my-app

📂 UnionFS — 联合文件系统

UnionFS 是一种分层、轻量级、高性能的文件系统,支持将多个目录联合挂载到同一目录下。

  • Docker 镜像的分层结构就是基于 UnionFS 实现的
  • 常见实现:OverlayFS(overlay2)、AUFS
  • 目前 Docker 默认使用 overlay2 驱动
OverlayFS 工作原理:

┌─────────────┐
│  merged     │  ← 用户看到的统一视图
├─────────────┤
│  upperdir   │  ← 可写层(容器层)
├─────────────┤
│  lowerdir   │  ← 只读层(镜像层,可多层)
└─────────────┘

- 读取文件:从上到下查找,找到即返回
- 写入文件:Copy-on-Write(写时复制),先从只读层复制到可写层再修改
- 删除文件:在可写层创建 whiteout 文件标记删除
bash
# 查看 Docker 使用的存储驱动
docker info | grep "Storage Driver"
# 输出:Storage Driver: overlay2

# 查看镜像的分层信息
docker inspect nginx | jq '.[0].RootFS'

1.2 环境安装与配置

1.2.1 Linux 下安装 Docker Engine(Ubuntu/Debian)

bash
# ============================================
# 方法一:使用官方安装脚本(推荐,最简单)
# ============================================
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# ============================================
# 方法二:手动安装(适合生产环境、需要控制版本)
# ============================================

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

# 2. 安装依赖
sudo apt-get update
sudo apt-get install -y \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

# 3. 添加 Docker 官方 GPG 密钥
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# 4. 添加 Docker 仓库
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

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

# 6. 将当前用户加入 docker 组(免 sudo)
sudo usermod -aG docker $USER
newgrp docker   # 立即生效,或重新登录

1.2.2 CentOS / RHEL 安装

bash
# 1. 卸载旧版本
sudo yum remove docker docker-common docker-selinux docker-engine

# 2. 安装依赖
sudo yum install -y yum-utils

# 3. 添加 Docker 仓库
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

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

# 5. 启动 Docker
sudo systemctl start docker
sudo systemctl enable docker

# 6. 添加用户到 docker 组
sudo usermod -aG docker $USER

1.2.3 配置镜像加速

国内访问 Docker Hub 较慢,配置镜像加速器可以显著提升拉取速度。

bash
# 创建或编辑 Docker 配置文件
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": [
    "https://mirror.ccs.tencentyun.com",
    "https://hub-mirror.c.163.com",
    "https://docker.mirrors.ustc.edu.cn"
  ],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  }
}
EOF

# 重启 Docker 使配置生效
sudo systemctl daemon-reload
sudo systemctl restart docker

# 验证镜像加速是否生效
docker info | grep -A 5 "Registry Mirrors"

⚠️ 注意:腾讯云镜像加速地址仅对腾讯云服务器有效。非腾讯云环境请使用其他镜像源。

1.2.4 验证安装

bash
# 查看 Docker 版本信息
docker version
# 输出示例:
# Client: Docker Engine - Community
#  Version:           24.0.7
#  API version:       1.43
#  Go version:        go1.21.3
# Server: Docker Engine - Community
#  Engine:
#   Version:          24.0.7

# 查看 Docker 系统信息
docker info
# 关注以下信息:
# - Server Version
# - Storage Driver(存储驱动,通常为 overlay2)
# - Cgroup Driver(cgroup 驱动)
# - Registry Mirrors(镜像加速地址)

# 运行测试容器
docker run --rm hello-world
# 看到 "Hello from Docker!" 说明安装成功

1.2.5 Docker Desktop 简介(可选)

Docker Desktop 是 Docker 官方提供的桌面端应用,主要面向 macOS 和 Windows 用户。

功能特点:

  • 图形化管理界面:查看容器、镜像、Volume
  • 集成 Docker Compose 和 Kubernetes
  • 内置 Docker Scout(镜像安全扫描)
  • 资源管理(CPU/内存分配设置)

Linux 上的替代方案:

  • Lazydocker:终端 UI 管理工具
  • Portainer:Web 端 Docker 管理平台
bash
# 安装 Lazydocker(推荐的终端管理工具)
curl https://raw.githubusercontent.com/jesseduffield/lazydocker/master/scripts/install_update_linux.sh | bash

# 安装 Portainer(Web 管理界面)
docker volume create portainer_data
docker run -d -p 9443:9443 --name portainer \
  --restart=always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v portainer_data:/data \
  portainer/portainer-ce:latest
# 访问 https://localhost:9443

1.3 基础命令实操

1.3.1 镜像操作

bash
# ==================== 搜索镜像 ====================
docker search nginx
docker search --filter=stars=100 nginx  # 只显示 star > 100 的镜像

# ==================== 拉取镜像 ====================
docker pull nginx              # 拉取最新版(默认 :latest)
docker pull nginx:1.25-alpine  # 拉取指定版本(推荐指定版本)
docker pull ubuntu:22.04

# ==================== 查看本地镜像 ====================
docker images                  # 列出所有镜像
docker images nginx            # 只列出 nginx 相关的镜像
docker images -q               # 只显示镜像 ID
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"  # 自定义格式

# 输出示例:
# REPOSITORY   TAG           IMAGE ID       CREATED        SIZE
# nginx        latest        a6bd71f48f68   2 weeks ago    187MB
# nginx        1.25-alpine   1e7e2bbc3c5b   2 weeks ago    43.2MB

# ==================== 查看镜像详情 ====================
docker inspect nginx:latest              # 查看镜像完整信息(JSON)
docker inspect nginx --format '{{.Config.ExposedPorts}}'  # 查看暴露端口
docker history nginx                     # 查看镜像构建历史(每一层)

# ==================== 标记镜像 ====================
docker tag nginx:latest my-nginx:v1.0    # 给镜像打标签
docker tag nginx:latest myregistry.com/nginx:v1.0  # 为推送私有仓库打标签

# ==================== 删除镜像 ====================
docker rmi nginx:1.25-alpine             # 删除指定镜像
docker rmi $(docker images -q -f "dangling=true")  # 删除所有悬空镜像
docker image prune                       # 清理未使用的悬空镜像
docker image prune -a                    # 清理所有未被容器使用的镜像(慎用)

1.3.2 容器操作

bash
# ==================== 创建并启动容器 ====================

# 基础运行
docker run nginx                        # 前台运行(会阻塞终端)

# 后台运行(最常用)
docker run -d --name my-nginx nginx     # -d: 后台运行, --name: 指定名称

# 端口映射
docker run -d -p 8080:80 --name web nginx
# -p 8080:80 → 宿主机 8080 端口映射到容器 80 端口
# 访问 http://localhost:8080 即可看到 nginx 默认页面

# 多端口映射
docker run -d -p 8080:80 -p 8443:443 --name web nginx

# 随机端口映射
docker run -d -P --name web nginx       # -P: 随机分配宿主机端口

# 环境变量
docker run -d \
  --name my-mysql \
  -e MYSQL_ROOT_PASSWORD=123456 \       # 设置环境变量
  -e MYSQL_DATABASE=testdb \
  -p 3306:3306 \
  mysql:8.0

# 资源限制
docker run -d \
  --name my-app \
  --memory="256m" \                     # 限制内存
  --cpus="0.5" \                        # 限制 CPU
  --restart=unless-stopped \            # 重启策略
  nginx

# 一次性运行(退出后自动删除)
docker run --rm ubuntu echo "Hello Docker"
docker run --rm -it ubuntu bash         # 交互式运行后自动清理

# ==================== 查看容器 ====================
docker ps                              # 查看运行中的容器
docker ps -a                           # 查看所有容器(含已停止的)
docker ps -a -q                        # 只显示容器 ID
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"  # 自定义格式
docker ps -f "status=exited"           # 过滤已停止的容器

# ==================== 容器生命周期管理 ====================
docker stop my-nginx                   # 优雅停止(发送 SIGTERM,10s后 SIGKILL)
docker stop -t 30 my-nginx             # 等待 30 秒后强制停止
docker kill my-nginx                   # 立即强制停止(发送 SIGKILL)
docker start my-nginx                  # 启动已停止的容器
docker restart my-nginx                # 重启容器
docker pause my-nginx                  # 暂停容器
docker unpause my-nginx                # 取消暂停

# ==================== 删除容器 ====================
docker rm my-nginx                     # 删除已停止的容器
docker rm -f my-nginx                  # 强制删除(即使运行中)
docker rm $(docker ps -a -q)           # 删除所有已停止的容器
docker container prune                 # 清理所有已停止的容器(推荐)

# ==================== 重启策略 ====================
# --restart=no              不自动重启(默认)
# --restart=always          总是自动重启
# --restart=unless-stopped  除非手动 stop,否则自动重启
# --restart=on-failure:5    失败时重启,最多 5 次

1.3.3 容器交互

bash
# ==================== 进入容器 ====================

# exec 方式(推荐)— 在运行中的容器内执行命令
docker exec -it my-nginx bash          # 进入容器的 bash shell
docker exec -it my-nginx sh            # 如果没有 bash,用 sh
docker exec -it my-nginx /bin/sh       # 完整路径

# exec 执行单条命令(不进入交互模式)
docker exec my-nginx cat /etc/nginx/nginx.conf   # 查看配置文件
docker exec my-nginx ls /usr/share/nginx/html    # 查看文件列表
docker exec my-nginx whoami                      # 查看当前用户

# -it 参数说明:
# -i (--interactive) : 保持标准输入打开
# -t (--tty)         : 分配一个伪终端
# 两者通常一起使用,提供交互式终端体验

# attach 方式(不推荐日常使用)
docker attach my-nginx
# ⚠️ 注意:attach 连接的是容器的主进程(PID 1)
# 按 Ctrl+C 会停止容器!用 Ctrl+P Ctrl+Q 可安全退出

# ==================== 查看日志 ====================
docker logs my-nginx                   # 查看全部日志
docker logs -f my-nginx                # 实时跟踪日志(类似 tail -f)
docker logs --tail 100 my-nginx        # 查看最后 100 行
docker logs --since "2024-01-01" my-nginx  # 查看指定时间之后的日志
docker logs --since 30m my-nginx       # 查看最近 30 分钟的日志
docker logs -t my-nginx                # 显示时间戳

# ==================== 查看容器信息 ====================
docker inspect my-nginx                # 查看容器完整信息
docker inspect --format '{{.NetworkSettings.IPAddress}}' my-nginx  # 查看 IP
docker inspect --format '{{.State.Status}}' my-nginx               # 查看状态
docker top my-nginx                    # 查看容器内进程
docker stats                           # 实时查看所有容器资源使用
docker stats my-nginx                  # 查看指定容器资源使用
docker port my-nginx                   # 查看端口映射
docker diff my-nginx                   # 查看容器文件系统变化

1.3.4 文件拷贝与导入导出

bash
# ==================== 容器与宿主机之间复制文件 ====================

# 从宿主机复制到容器
docker cp ./index.html my-nginx:/usr/share/nginx/html/index.html

# 从容器复制到宿主机
docker cp my-nginx:/etc/nginx/nginx.conf ./nginx.conf

# 复制目录
docker cp my-nginx:/var/log/nginx/ ./nginx-logs/

# ==================== 容器导入导出(不含元数据) ====================
# export/import: 导出容器的文件系统快照,不包含镜像历史和元数据

# 导出容器为 tar 文件
docker export my-nginx > nginx-container.tar
docker export -o nginx-container.tar my-nginx   # 等效写法

# 从 tar 导入为镜像
docker import nginx-container.tar my-nginx-image:v1
cat nginx-container.tar | docker import - my-nginx-image:v1  # 等效写法

# ==================== 镜像保存加载(保留完整信息) ====================
# save/load: 完整保存镜像,包含所有分层、标签、元数据

# 保存镜像为 tar 文件
docker save nginx:latest > nginx-image.tar
docker save -o nginx-image.tar nginx:latest     # 等效写法
docker save -o all-images.tar nginx:latest ubuntu:22.04  # 保存多个镜像

# 加载镜像
docker load < nginx-image.tar
docker load -i nginx-image.tar                  # 等效写法

export/import vs save/load 对比:

对比export/importsave/load
操作对象容器镜像
保留分层❌ 合并为单层✅ 保留所有层
保留元数据❌ 丢失 CMD、ENV 等✅ 完整保留
文件体积较小较大
适用场景快速迁移容器离线传输镜像

1.3.5 系统清理命令

bash
# ==================== 一键清理 ====================

# 清理所有停止的容器、未使用的网络、悬空镜像、构建缓存
docker system prune

# 更彻底的清理(包括未使用的镜像和 volume)
docker system prune -a --volumes

# ⚠️ 以上命令会删除大量数据,生产环境慎用!

# 查看 Docker 磁盘使用情况
docker system df

# 输出示例:
# TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
# Images          10        3         2.453GB   1.825GB (74%)
# Containers      5         2         123.4MB   89.2MB (72%)
# Local Volumes   3         2         456.7MB   12.3MB (2%)
# Build Cache     15        0         1.234GB   1.234GB

1.4 实践 Demo

Demo 1:Nginx 入门实战 — 启动、访问、修改页面

bash
# ===== Step 1: 拉取 Nginx 镜像 =====
docker pull nginx:latest

# ===== Step 2: 启动 Nginx 容器 =====
docker run -d \
  --name my-web \
  -p 8080:80 \
  nginx:latest

# 查看容器状态
docker ps

# ===== Step 3: 访问默认页面 =====
# 浏览器打开 http://localhost:8080
# 或者用 curl 测试
curl http://localhost:8080

# ===== Step 4: 进入容器修改默认页面 =====
docker exec -it my-web bash

# 在容器内执行:
echo '<h1>Hello Docker!</h1><p>My first Docker container.</p>' \
  > /usr/share/nginx/html/index.html
exit

# 刷新浏览器,页面已更新!
curl http://localhost:8080

# ===== Step 5: 也可以不进入容器,直接用 cp 修改 =====
# 在宿主机创建一个自定义页面
cat > /tmp/index.html <<'EOF'
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Docker 学习</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
        }
        .container { text-align: center; }
        h1 { font-size: 3em; margin-bottom: 0.5em; }
        p { font-size: 1.2em; opacity: 0.9; }
    </style>
</head>
<body>
    <div class="container">
        <h1>🐳 Hello Docker!</h1>
        <p>这是我的第一个 Docker 容器</p>
        <p>Running on Nginx inside a container</p>
    </div>
</body>
</html>
EOF

# 将文件复制到容器中
docker cp /tmp/index.html my-web:/usr/share/nginx/html/index.html

# 验证
curl http://localhost:8080

# ===== Step 6: 清理 =====
docker stop my-web
docker rm my-web

Demo 2:运行多个容器 — 理解容器隔离

bash
# 启动 3 个独立的 Nginx 容器,映射不同端口
docker run -d --name web1 -p 8081:80 nginx
docker run -d --name web2 -p 8082:80 nginx
docker run -d --name web3 -p 8083:80 nginx

# 分别修改每个容器的页面
docker exec web1 bash -c 'echo "<h1>Server 1</h1>" > /usr/share/nginx/html/index.html'
docker exec web2 bash -c 'echo "<h1>Server 2</h1>" > /usr/share/nginx/html/index.html'
docker exec web3 bash -c 'echo "<h1>Server 3</h1>" > /usr/share/nginx/html/index.html'

# 验证 —— 三个容器完全独立
curl http://localhost:8081   # → Server 1
curl http://localhost:8082   # → Server 2
curl http://localhost:8083   # → Server 3

# 查看容器各自的 IP
docker inspect --format '{{.Name}} → {{.NetworkSettings.IPAddress}}' web1 web2 web3

# 查看容器进程 —— 每个容器内 PID 都从 1 开始
docker exec web1 ps aux
docker exec web2 ps aux

# 清理
docker stop web1 web2 web3
docker rm web1 web2 web3

Demo 3:容器生命周期完整演示

bash
# ===== 创建容器(不启动) =====
docker create --name lifecycle-demo -p 9090:80 nginx
docker ps -a    # STATUS: Created

# ===== 启动 =====
docker start lifecycle-demo
docker ps       # STATUS: Up X seconds

# ===== 暂停 =====
docker pause lifecycle-demo
docker ps       # STATUS: Up X seconds (Paused)
curl http://localhost:9090   # 请求会挂起,无响应

# ===== 恢复 =====
docker unpause lifecycle-demo
curl http://localhost:9090   # 恢复正常

# ===== 停止 =====
docker stop lifecycle-demo
docker ps -a    # STATUS: Exited (0)

# ===== 重新启动 =====
docker start lifecycle-demo
docker ps       # 又活了

# ===== 强制终止 =====
docker kill lifecycle-demo
docker ps -a    # STATUS: Exited (137)  ← 137 = 128 + 9(SIGKILL)

# ===== 删除 =====
docker rm lifecycle-demo
docker ps -a    # 已经消失

Demo 4:镜像导入导出实战 — 离线迁移

bash
# 场景:将镜像从一台机器迁移到另一台(无网络的机器)

# ===== 在源机器上 =====
# 保存镜像为 tar 文件
docker save -o nginx-offline.tar nginx:latest

# 查看文件大小
ls -lh nginx-offline.tar
# -rw------- 1 user user 187M Jan 1 00:00 nginx-offline.tar

# 将 tar 文件传输到目标机器(scp、U盘等)
# scp nginx-offline.tar user@target-host:/tmp/

# ===== 在目标机器上 =====
# 加载镜像
docker load -i /tmp/nginx-offline.tar
# Loaded image: nginx:latest

# 验证
docker images nginx
docker run -d -p 80:80 nginx:latest

Demo 5:资源限制实验

bash
# 启动一个内存受限的容器
docker run -d \
  --name mem-test \
  --memory="100m" \
  --memory-swap="100m" \
  ubuntu:22.04 \
  sleep infinity

# 查看资源使用
docker stats mem-test --no-stream

# 在容器内尝试分配超过限制的内存(会被 OOM Kill)
docker exec -it mem-test bash
# 在容器内运行:
# apt-get update && apt-get install -y stress
# stress --vm 1 --vm-bytes 150M --vm-hang 0
# 容器会被杀掉!

# 查看容器退出原因
docker inspect --format '{{.State.OOMKilled}}' mem-test
# true

# 清理
docker rm -f mem-test

1.5 常见问题 QA

Q1: Got permission denied while trying to connect to the Docker daemon socket

Got permission denied while trying to connect to the Docker daemon socket at
unix:///var/run/docker.sock: ... connect: permission denied

原因:当前用户没有权限访问 Docker daemon 的 socket 文件。

解决方案

bash
# 方案一:将用户加入 docker 组(推荐)
sudo usermod -aG docker $USER
# 然后重新登录(或执行 newgrp docker)

# 方案二:临时使用 sudo
sudo docker ps

# 验证
groups  # 确认用户在 docker 组中

Q2: Cannot connect to the Docker daemon. Is the docker daemon running?

原因:Docker Daemon 未启动。

解决方案

bash
# 启动 Docker
sudo systemctl start docker

# 设置开机自启
sudo systemctl enable docker

# 检查 Docker 状态
sudo systemctl status docker

# 如果启动失败,查看日志排错
sudo journalctl -xeu docker.service

Q3: 端口被占用 — Bind for 0.0.0.0:8080 failed: port is already allocated

原因:宿主机 8080 端口已被其他进程或容器占用。

解决方案

bash
# 查看谁占用了端口
sudo lsof -i :8080
# 或
sudo netstat -tlnp | grep 8080

# 方案一:换一个端口
docker run -d -p 8888:80 --name my-web nginx

# 方案二:停止占用端口的进程/容器
docker stop <占用端口的容>
# 或 kill 占用进程

Q4: 容器启动后立即退出(状态为 Exited)

原因:容器的主进程执行完毕后退出了。Docker 容器在主进程退出后就会停止。

解决方案

bash
# 查看容器退出日志
docker logs <container_name>

# 查看退出状态码
docker inspect --format '{{.State.ExitCode}}' <container_name>
# 退出码含义:
# 0   → 正常退出
# 1   → 应用程序错误
# 137 → 被 SIGKILL 杀掉(OOM 或 docker kill)
# 139 → 段错误
# 143 → 被 SIGTERM 正常终止

# 如果需要容器持续运行,确保主进程不会退出
# 错误:
docker run -d ubuntu            # ubuntu 镜像默认 CMD 是 bash,没有终端会立即退出

# 正确:
docker run -d ubuntu sleep infinity          # 保持进程运行
docker run -d -it ubuntu bash                # 分配终端
docker run -d ubuntu tail -f /dev/null       # 另一种保持方式

Q5: docker pull 拉取镜像很慢或超时

原因:默认从 Docker Hub 拉取,国内网络访问较慢。

解决方案

bash
# 配置镜像加速器(见 1.2.3 节)
# 确认配置已生效:
docker info | grep -A 5 "Registry Mirrors"

# 临时指定源拉取
# 使用腾讯云 CCR
docker pull ccr.ccs.tencentyun.com/library/nginx

Q6: execattach 有什么区别?该用哪个?

对比docker execdocker attach
作用在容器内启动新进程连接到容器的主进程
Ctrl+C只退出 exec 进程会停止整个容器!
使用场景调试、执行命令查看主进程输出
推荐✅ 日常使用推荐⚠️ 谨慎使用
bash
# 推荐使用 exec
docker exec -it my-nginx bash

# 如果必须用 attach,记得用 Ctrl+P Ctrl+Q 安全退出(不会停止容器)
docker attach my-nginx
# 按 Ctrl+P 然后 Ctrl+Q 退出

Q7: 如何查看容器的 IP 地址?

bash
# 方法一:docker inspect
docker inspect --format '{{.NetworkSettings.IPAddress}}' my-nginx

# 方法二:进入容器查看
docker exec my-nginx cat /etc/hosts
docker exec my-nginx hostname -i

# 方法三:查看所有容器的 IP
docker inspect --format '{{.Name}} → {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -q)

Q8: docker rundocker create + docker start 有什么区别?

bash
# docker run = docker create + docker start + docker attach(前台模式)

# 等效操作:
docker run -d --name my-nginx nginx
# 等于:
docker create --name my-nginx nginx
docker start my-nginx

docker create 适用于需要先配置好容器再启动的场景。


Q9: 如何清理 Docker 占用的磁盘空间?

bash
# 1. 查看 Docker 磁盘使用
docker system df
docker system df -v   # 详细信息

# 2. 渐进式清理(从安全到激进)

# 清理已停止的容器
docker container prune

# 清理悬空镜像(<none> 标签的镜像)
docker image prune

# 清理未使用的网络
docker network prune

# 清理未使用的 volume(⚠️ 可能丢数据)
docker volume prune

# 一键清理(不含 volume)
docker system prune

# 一键清理所有(⚠️ 慎用,含未使用的镜像和 volume)
docker system prune -a --volumes

Q10: docker stopdocker kill 有什么区别?

对比docker stopdocker kill
信号先发 SIGTERM,超时后发 SIGKILL直接发 SIGKILL
行为给进程优雅退出的机会强制立即终止
超时默认等待 10 秒无等待
适用正常停止容器无响应时
bash
docker stop my-nginx              # 优雅停止,等待 10 秒
docker stop -t 30 my-nginx        # 等待 30 秒
docker kill my-nginx               # 强制停止
docker kill -s SIGTERM my-nginx    # kill 也可以发送指定信号

1.6 命令速查表

┌─────────────────────────────────────────────────────────────────┐
│                    Docker 基础命令速查表                         │
├──────────────────┬──────────────────────────────────────────────┤
│                  │                                              │
│  镜像管理         │  docker pull <image>      拉取镜像           │
│                  │  docker images            列出镜像           │
│                  │  docker rmi <image>       删除镜像           │
│                  │  docker tag <src> <dst>   打标签             │
│                  │  docker history <image>   查看构建历史        │
│                  │  docker save / load       保存/加载镜像       │
│                  │  docker image prune       清理悬空镜像        │
│                  │                                              │
├──────────────────┼──────────────────────────────────────────────┤
│                  │                                              │
│  容器管理         │  docker run -d -p H:C     后台运行+端口映射    │
│                  │  docker ps / ps -a        查看容器            │
│                  │  docker stop / start      停止/启动           │
│                  │  docker rm <container>    删除容器            │
│                  │  docker restart           重启容器            │
│                  │  docker container prune   清理已停止容器       │
│                  │                                              │
├──────────────────┼──────────────────────────────────────────────┤
│                  │                                              │
│  容器交互         │  docker exec -it ... bash  进入容器          │
│                  │  docker logs -f            实时日志           │
│                  │  docker cp                 文件复制           │
│                  │  docker inspect            查看详情           │
│                  │  docker stats              资源监控           │
│                  │  docker top                查看进程           │
│                  │                                              │
├──────────────────┼──────────────────────────────────────────────┤
│                  │                                              │
│  系统管理         │  docker system df          磁盘使用           │
│                  │  docker system prune       一键清理           │
│                  │  docker info               系统信息           │
│                  │  docker version            版本信息           │
│                  │                                              │
└──────────────────┴──────────────────────────────────────────────┘

📝 学习建议:本阶段以动手实操为主,每个命令都亲自执行一遍。建议在虚拟机或云服务器上练习,避免影响本机环境。完成所有 Demo 后,尝试自己组合命令,比如"启动一个 Redis 容器并通过 redis-cli 连接"。