《UNIX/Linux系统管理技术手册-读书笔记-第二十五章

容器

1. 容器概述

1.1 什么是容器

概念 说明 能做什么
容器 一组独立的进程,被限制在私有根文件系统和进程名称空间中 将应用及其依赖打包成标准可移植单元,在任何兼容环境中运行
容器镜像 容器的模板,包含应用代码、库、运行时、配置文件 一次构建,到处运行(Build Once, Run Anywhere)
容器运行时引擎 管理容器生命周期的软件(如Docker) 创建、启动、停止、删除容器,管理镜像和卷

1.2 容器 vs 虚拟机

对比维度 容器 虚拟机
启动时间 <1秒 1~2分钟
资源开销 轻量(MB级镜像) 重量(GB级镜像)
隔离级别 进程级(共享宿主机内核) 系统级(独立内核)
密度 每主机数百个 每主机数十个
OS兼容性 必须与宿主机内核一致 可运行不同OS

1.3 容器背后的内核技术

技术 功能
名称空间(Namespace) 隔离进程视图(PID、挂载点、网络、用户、UTS、IPC)
控制组(Cgroup) 限制资源使用(CPU、内存、磁盘I/O)
能力(Capability) 细粒度root权限划分(约40种)
Seccomp 限制系统调用访问

💡 容器本质上就是利用这些内核特性隔离进程,没有任何魔法——这也是Docker之前LXC等工具已存在多年的原因。

2. Docker核心架构

2.1 组件

组件 说明
dockerd 持续运行的守护进程,负责所有容器和镜像操作
docker客户端 命令行工具,通过UNIX套接字或TCP与dockerd通信
镜像(Image) 只读模板,包含文件系统+应用+配置
容器(Container) 镜像的运行实例,拥有独立的可写层
Registry 镜像仓库(默认Docker Hub)
联合文件系统(UnionFS) 多层叠加,写时复制(CoW)机制

架构图:docker客户端 ↔ docker守护进程 ↔ 镜像/容器存储 ↔ Registry

2.2 镜像分层(写时复制)

容器运行层(可写)
─────────────
Layer 3(只读)
Layer 2(只读)
Layer 1(只读)  ← 基础镜像(如debian:jessie)
  • 多个容器共享相同的基础层 → 节省存储、快速启动
  • 容器修改写入可写层,不影响基础镜像

2.3 安装与配置

系统 安装方式
Linux Docker官网提供针对各发行版的仓库
FreeBSD 实验性支持
macOS/Windows Docker Desktop

守护进程配置覆盖(systemd):

1
2
3
4
5
6
systemctl edit docker
# 写入覆盖配置
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd --storage-driver overlay --dns 8.8.8.8 --bip 172.18.0.0/19
systemctl restart docker

安全警告docker组用户相当于拥有root权限!建议通过sudo控制访问,而非将用户加入docker组。

3. Docker核心命令速查

命令 功能 示例
docker pull image 从registry下载镜像 docker pull debian:jessie
docker images 列出本地镜像
docker run 创建并启动容器 docker run -it --rm debian bash
docker ps 列出运行中容器 docker ps -a(含停止的)
docker stop/start 停止/启动容器
docker rm 删除容器 docker rm container_name
docker rmi 删除镜像 docker rmi image_name
docker exec 在运行容器中执行命令 docker exec -it nginx bash
docker logs 查看容器日志 docker logs -f nginx
docker inspect 查看容器/镜像详细配置(JSON)
docker build -t tag . 从Dockerfile构建镜像
docker push/pull 上传/下载镜像到registry
docker volume ls 列出卷
docker system prune 清理未使用的资源

快速体验

1
2
3
4
5
6
7
8
# 运行交互式Debian容器
docker run --hostname debian -it debian /bin/bash

# 后台运行Nginx,映射端口80
docker run -p 80:80 --name nginx -d nginx

# 查看Nginx访问日志
docker logs nginx

4. Dockerfile(镜像构建)

4.1 常用指令

指令 功能
FROM 第一条,指定基础镜像
RUN 构建时执行命令(如安装软件包)
COPY / ADD 将文件复制到镜像中(ADD支持URL和自动解压)
ENV 设置环境变量
EXPOSE 声明容器监听端口(文档性)
CMD 容器启动时执行的默认命令(可被覆盖
ENTRYPOINT 容器启动时执行的固定命令(不易被覆盖)
WORKDIR 设置后续指令的工作目录
USER 切换运行用户(安全实践
VOLUME 声明持久化存储卷
ARG 构建时变量(非敏感)

4.2 Dockerfile示例(Nginx官方镜像简化版)

1
2
3
4
5
6
7
8
FROM debian:jessie
ENV NGINX_VERSION 1.10.3-1-jessie
RUN apt-get update && apt-get install -y nginx=${NGINX_VERSION} \
    && rm -rf /var/lib/apt/lists/*
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
    && ln -sf /dev/stderr /var/log/nginx/error.log
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]

关键实践

  • 日志重定向到/dev/stdout/dev/stderr → 由Docker日志驱动收集
  • 前台运行(daemon off;)→ 容器不会因进程退出而终止
  • 一条RUN安装+清理 → 减少层数,减小镜像大小

4.3 构建自定义镜像

1
2
3
4
5
6
7
8
9
# Dockerfile
FROM nginx
ADD index.html /usr/share/nginx/html/

# 构建
docker build -t nginx:ulshar .

# 运行
docker run -p 80:80 --name nginx-ulshar -d nginx:ulshar

5. 卷(数据持久化)

5.1 卷类型

类型 创建方式 特点 适用场景
匿名卷 docker run -v /data 自动命名,保存在/var/lib/docker/volumes/ 临时数据
命名卷 docker volume create mydata 可管理,持久化 生产数据
绑定挂载 docker run -v /host/path:/container/path 主机目录直接挂载 开发、配置共享
数据卷容器 docker create -v /data --name data-container ... 专用于持有卷配置 容器间共享卷

5.2 绑定挂载示例

1
2
3
# 主机目录挂载到容器
docker run -v /mnt/data:/data --name web -d nginx
# 容器写入/data → 主机/mnt/data可见

5.3 数据卷容器模式

1
2
3
4
5
# 创建纯数据容器
docker create -v /data --name nginx-data nginx

# 其他容器使用该卷
docker run --volumes-from nginx-data -p 80:80 --name web -d nginx

注意:数据卷容器使容器与特定主机绑定,违背容器“短暂性”理念。需要持久状态的应用,认真评估此模式是否适合。

6. Docker网络

6.1 网络模式

模式 说明 适用场景
bridge(默认) 容器在私有网段,主机通过NAT暴露端口 大多数场景
host 容器共享主机网络栈(无隔离) 需要高性能网络的应用
none 无网络配置 高级自定义
1
2
3
docker run -p 80:80 --net host nginx   # host模式
docker network ls                       # 查看网络
docker inspect -f '{{json .NetworkSettings.Networks.bridge}}' container

6.2 端口映射

1
2
3
docker run -p 80:80 nginx           # 主机80→容器80
docker run -p 8080:80 nginx         # 主机8080→容器80
docker run -P nginx                 # 随机映射EXPOSE的端口

6.3 自定义网络

1
2
3
4
docker network create --driver bridge mynet
docker run --net mynet --name web1 -d nginx
docker run --net mynet --name web2 -d nginx
# web1可通过容器名直接访问web2(内置DNS)

7. 存储驱动程序(Storage Driver)

驱动 特点 默认平台
overlay OverlayFS,稳定的现代UnionFS CentOS 7+
overlay2 overlay改进版,更高效 推荐生产使用
aufs 原始Docker驱动,非内核主线 Debian/Ubuntu(历史)
devicemapper 需直接LVM模式配置,否则性能差 RHEL/CentOS 6
zfs / btrfs 原生CoW文件系统驱动 对应系统
vfs 无联合文件系统(完整复制),稳定但慢 测试环境

💡 推荐:Linux优先选择overlay2,性能与稳定性最佳。

8. 日志管理

8.1 容器日志惯例

  • 应用将日志写入STDOUT(正常输出)和STDERR(错误)
  • Docker收集并转发到可配置的日志驱动

8.2 日志驱动

驱动 说明
json-file 默认,JSON格式保存到/var/lib/docker/containers/
syslog 转发到系统syslog
journald 转发到systemd日志
awslogs 直接写入AWS CloudWatch
gelf Graylog扩展日志格式
none 禁用日志收集
1
2
3
4
5
# 运行时指定日志驱动
docker run --log-driver syslog --log-opt syslog-address=udp://logs.example.com:514 nginx

# 配置json-file轮替
docker run --log-driver json-file --log-opt max-size=10m --log-opt max-file=3 nginx

9. 安全最佳实践

实践 说明
限制守护进程访问 使用sudo而非加入docker组(docker组=root)
使用TLS远程通信 dockerd -H tcp://0.0.0.0:2376 --tlsverify
非root用户运行 Dockerfile中使用USER nobody
只读根文件系统 docker run --read-only
最小能力集 docker run --cap-drop ALL --cap-add NET_RAW
内容信任 export DOCKER_CONTENT_TRUST=1(验证镜像签名)
镜像漏洞扫描 使用docker scan或Clair等工具扫描基础镜像
1
2
3
# 安全运行示例
docker run --read-only --cap-drop ALL --cap-add NET_BIND_SERVICE \
  -v /tmp:/tmp -p 80:80 -d nginx

10. Registry(镜像仓库)

10.1 Docker Hub

  • 公共镜像仓库,大量官方镜像(debian、ubuntu、nginx、mysql等)
  • 付费账户支持私有仓库
  • 内容信任验证部分官方镜像

10.2 私有Registry

1
2
3
4
5
6
# 运行简单registry容器
docker run -d -p 5000:5000 --name registry registry:2

# 推送镜像到私有registry
docker tag nginx localhost:5000/nginx
docker push localhost:5000/nginx

生产registry注意事项

  • 必须启用TLS加密通信
  • 配置认证(token或htpasswd)
  • 考虑存储后端(S3/GCS)和清理策略
  • 云托管registry(AWS ECR、GCR)是更省心的选择

11. 容器集群管理(编排)

11.1 为什么需要编排

问题 编排的解决方案
容器部署在哪台服务器? 调度算法自动选择合适节点
节点故障怎么办? 自动重新调度容器到健康节点
如何发现服务? 内置服务发现 + DNS
如何负载均衡? 集成负载均衡器
如何滚动更新? 零停机部署策略

11.2 主流编排系统对比

系统 来源 特点 学习曲线 适用场景
Kubernetes(k8s) Google 功能最全,社区最大,生产级 陡峭 复杂微服务架构
Docker Swarm Docker, Inc. 最简单,与Docker原生集成 中小规模,已有Docker环境
Mesos + Marathon Apache 通用集群管理,支持多种framework 大数据+容器混合环境
AWS ECS Amazon 托管服务,与AWS深度集成 AWS云环境,不想自建管理面

11.3 Kubernetes核心概念

概念 说明
Pod 一个或多个容器的组合,共享网络和存储(最小调度单元
Service 一组Pod的稳定网络入口(地址不变
Deployment 声明式管理Pod副本数、滚动更新、回滚
Node 集群中的一个工作节点
Kubelet 每个节点上的代理,管理Pod生命周期
kubectl Kubernetes命令行工具
1
2
3
4
5
6
7
8
# 部署应用
kubectl create deployment nginx --image=nginx
# 暴露服务
kubectl expose deployment nginx --port=80 --type=LoadBalancer
# 滚动更新
kubectl set image deployment/nginx nginx=nginx:1.17
# 回滚
kubectl rollout undo deployment/nginx

11.4 Docker Swarm

1
2
3
4
5
docker swarm init                          # 初始化集群
docker node ls                             # 查看节点
docker service create --replicas 3 -p 80:80 --name web nginx   # 部署服务
docker service scale web=5                 # 扩展副本数
docker service update --image nginx:1.17 web   # 更新

Swarm优势:学习成本最低,命令与单机Docker几乎一致,TLS加密开箱即用。

12. 容器实践建议(运维视角)

场景 建议
调度任务(cron) 主机上运行cron,调度一次性容器
远程登录调试 不要sshd进容器!登录主机后用docker exec -it
配置管理 用环境变量传入配置
容器升级 替换容器,而非原地更新
日志收集 容器日志通过Docker日志驱动收集
容器维护 避免手动访问容器“修复”问题
数据持久化 状态化应用使用卷(Volume)
资源限制 使用--memory--cpus限制容器资源
清理 定期清理停止的容器、悬空镜像和卷

13. 本章核心命令速查表

命令 功能
docker pull ubuntu:22.04 下载镜像
docker run -it --rm ubuntu bash 运行临时交互式容器
docker run -d -p 80:80 --name web nginx 后台运行Nginx
docker exec -it web bash 进入运行中容器
docker logs -f web 查看实时日志
docker stop web && docker rm web 停止并删除
docker build -t myapp:v1 . 从Dockerfile构建镜像
docker tag myapp:v1 myregistry/myapp:v1 标记镜像
docker push myregistry/myapp:v1 推送到私有registry
docker volume create mydata 创建命名卷
docker run -v mydata:/data -d nginx 使用命名卷
docker system prune -f 清理未使用资源
kubectl get pods 查看Kubernetes Pod
docker service ls 查看Swarm服务

DBA视角补充

  • 数据库容器化需谨慎:数据库是状态化应用,容器化意味着管理数据卷、备份、恢复、网络等复杂性。生产环境建议将数据库部署在虚拟机/裸机上,将无状态应用层容器化。开发/测试环境可容器化数据库以快速拉起环境。
  • 如果必须容器化数据库
    • 使用命名卷绑定挂载持久化数据(绝不能用容器可写层存数据)
    • 配置资源限制--memory--cpus)防止数据库容器耗尽宿主机资源
    • 使用--restart=always确保崩溃后自动重启
    • 数据库配置通过环境变量或配置文件挂载传入
    • 备份通过主机侧卷数据备份,而非docker exec执行备份(避免额外负载)
  • 官方数据库镜像:Docker Hub有官方MySQL/PostgreSQL镜像,适合快速测试,使用前仔细阅读镜像文档,理解初始化机制(如/docker-entrypoint-initdb.d/)。
  • 网络性能:容器网络(bridge模式)有NAT开销,数据库高吞吐场景可考虑--net=host模式,但需权衡安全与端口冲突。
  • 编排与数据库:Kubernetes StatefulSet + PersistentVolume可实现有状态数据库容器编排,但复杂度高。建议优先使用云托管数据库服务(AWS RDS、GCP Cloud SQL)替代自建容器化数据库。