一句话总结
Docker 三大核心:镜像(Image)— 只读模板,分层存储(UnionFS),每层是一个文件系统变更;容器(Container)— 镜像的运行实例,在镜像层之上加一个可写层(写时复制);仓库(Registry)— 存储和分发镜像(Docker Hub/私有仓库)。Docker vs 虚拟机:Docker 共享宿主机内核,秒级启动、MB 级大小;虚拟机需要完整 Guest OS,分钟级启动、GB 级大小。Docker 不是虚拟机,是进程级别的隔离(Namespace + Cgroups)。
初级理解
Docker 架构
# Docker 架构(C/S 模式):
# Docker Client(docker CLI)
# ↓ REST API
# Docker Daemon(dockerd)
# ↓
# containerd → runc → 容器进程
# 核心组件:
# 1. Docker Client:命令行工具(docker build/run/pull)
# 2. Docker Daemon:后台服务,管理镜像/容器/网络/卷
# 3. Docker Registry:镜像仓库(Docker Hub / 私有仓库)
# 4. Docker Image:只读模板
# 5. Docker Container:镜像的运行实例
# 常用命令:
docker pull nginx:latest # 拉取镜像
docker images # 查看本地镜像
docker run -d -p 8080:80 nginx # 运行容器
docker ps # 查看运行中的容器
docker ps -a # 查看所有容器
docker stop container_id # 停止容器
docker rm container_id # 删除容器
docker rmi image_id # 删除镜像
docker exec -it container_id bash # 进入容器
Docker vs 虚拟机
| 对比维度 | Docker | 虚拟机 |
|---|---|---|
| 启动速度 | 秒级 | 分钟级 |
| 镜像大小 | MB 级 | GB 级 |
| 资源占用 | 共享宿主机内核 | 每个 VM 有完整 OS |
| 隔离级别 | 进程级(Namespace) | 硬件级(Hypervisor) |
| 性能 | 接近原生 | 有虚拟化损耗 |
| 可移植性 | 跨平台(需相同内核) | 跨平台(完整 OS) |
中级深入
镜像分层存储(UnionFS)
# Docker 镜像由多个只读层组成:
# 示例:一个 Java 应用镜像
# Layer 6: 应用 JAR 包(COPY app.jar)
# Layer 5: 启动脚本(COPY entrypoint.sh)
# Layer 4: 安装字体(RUN apt install fonts)
# Layer 3: 安装 JDK(RUN apt install openjdk-11)
# Layer 2: 更新源(RUN apt update)
# Layer 1: 基础镜像(FROM ubuntu:20.04)
# 分层的好处:
# 1. 共享层:多个镜像共享相同的基础层
# 如 10 个 Java 应用都基于 openjdk:11
# 基础层只存一份,节省磁盘空间
# 2. 增量更新:修改只重建变更的层
# 改 JAR 包只需重建 Layer 6
# 3. 快速分发:拉取镜像时已有层跳过
# 查看镜像分层:
docker image history nginx:latest
# 显示每层的创建命令和大小
# 写时复制(Copy-on-Write):
# 容器运行时不复制镜像层
# 修改文件时才复制到可写层
# 读取:从最上层往下找,找到即返回
# 写入:先复制到可写层,再修改
容器底层技术
# Docker 依赖 Linux 内核两大技术:
# 1. Namespace(命名空间)— 资源隔离
# PID Namespace:进程隔离(容器内 PID=1)
# NET Namespace:网络隔离(独立网卡/IP/端口)
# IPC Namespace:进程间通信隔离
# MNT Namespace:文件系统挂载点隔离
# UTS Namespace:主机名和域名隔离
# USER Namespace:用户隔离
# 2. Cgroups(控制组)— 资源限制
# CPU:--cpus=2(限制使用 2 核)
# 内存:--memory=512m(限制 512MB)
# 磁盘 IO:--blkio-weight
# 示例:
docker run -d --cpus=2 --memory=512m nginx
# 3. UnionFS(联合文件系统)— 分层镜像
# overlay2(推荐)、aufs、devicemapper
# 实现镜像分层和写时复制
高级进阶
Docker 网络模式
# Docker 四种网络模式:
# 1. bridge(桥接,默认)
docker run -d --network bridge nginx
# 容器通过 docker0 虚拟网桥通信
# 每个容器有独立 IP(172.17.0.x)
# 端口映射:-p 8080:80
# 2. host(主机模式)
docker run -d --network host nginx
# 容器共享宿主机网络栈
# 性能最好,但端口冲突风险
# 不需要 -p 端口映射
# 3. none(无网络)
docker run -d --network none nginx
# 容器只有 lo 回环网卡
# 完全隔离,需要手动配置
# 4. container(共享容器网络)
docker run -d --network container:nginx nginx
# 新容器共享已有容器的网络栈
# 两个容器通过 localhost 通信
# 自定义网络(推荐):
docker network create mynet
docker run -d --network mynet --name app1 app1
docker run -d --network mynet --name app2 app2
# app1 和 app2 可以通过容器名互相访问
数据卷(Volume)
# 为什么需要数据卷?
# 容器删除后,容器内的数据也丢失
# 数据卷将数据持久化到宿主机
# 三种挂载方式:
# 1. Volume(卷,推荐)
docker volume create mydata
docker run -v mydata:/data nginx
# Docker 管理,存储在 /var/lib/docker/volumes/
# 优点:可移植、可备份、驱动支持远程存储
# 2. Bind Mount(绑定挂载)
docker run -v /host/path:/container/path nginx
# 挂载宿主机指定路径
# 优点:直接访问宿主机文件
# 缺点:依赖宿主机目录结构
# 3. tmpfs(临时文件系统)
docker run --tmpfs /tmp nginx
# 存储在内存中,容器停止即消失
# 适用:敏感数据、临时缓存
# 数据卷容器(共享卷):
docker create --name data -v /data busybox
docker run --volumes-from data app1
docker run --volumes-from data app2
实战场景
# 场景1:运行 MySQL 容器
docker run -d \
--name mysql \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123456 \
-v mysql_data:/var/lib/mysql \
mysql:8.0
# 场景2:查看容器日志
docker logs -f --tail 100 container_name
# 场景3:进入容器排查
docker exec -it container_name /bin/bash
# 或 /bin/sh(Alpine 镜像)
# 场景4:资源限制
docker run -d \
--cpus=2 \
--memory=512m \
--memory-swap=1g \
nginx
# 场景5:清理资源
docker system prune -a # 清理所有未使用资源
docker container prune # 清理停止的容器
docker image prune # 清理未使用的镜像
docker volume prune # 清理未使用的卷
面试模拟
面试官:Docker 和虚拟机有什么区别?
你:Docker 共享宿主机内核,进程级隔离(Namespace + Cgroups),秒级启动、MB 级大小、接近原生性能。虚拟机需要完整 Guest OS,硬件级隔离(Hypervisor),分钟级启动、GB 级大小、有虚拟化损耗。Docker 适合微服务快速部署,虚拟机适合强隔离场景。
面试官:Docker 镜像分层是什么?有什么好处?
你:镜像由多个只读层叠加组成(UnionFS),每层是 Dockerfile 一条指令的结果。好处:1)共享层节省磁盘(多个镜像共享基础层);2)增量构建(只重建变更层);3)快速分发(已有层跳过下载)。容器运行时在镜像层上加一个可写层(写时复制)。