主题
第一阶段: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) |
工作流程:
- 用户通过
dockerCLI 输入命令 - CLI 通过 REST API 将请求发送给 Docker Daemon
- Daemon 执行操作(拉取镜像、创建容器等)
- 需要时从 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 $USER1.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:94431.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/import | save/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.234GB1.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-webDemo 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 web3Demo 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:latestDemo 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-test1.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.serviceQ3: 端口被占用 — 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/nginxQ6: exec 和 attach 有什么区别?该用哪个?
| 对比 | docker exec | docker 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 run 和 docker 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-nginxdocker 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 --volumesQ10: docker stop 和 docker kill 有什么区别?
| 对比 | docker stop | docker 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连接"。