Docker 容器技术实战


第1章 容器生态系统

1.1 容器技术概述

容器技术是继大数据、云计算之后的核心技术方向,核心价值是实现应用的一次构建,随处运行。传统应用部署面临环境差异、依赖复杂、迁移成本高等问题,容器通过标准化的打包机制,将应用及其依赖统一封装,实现了跨环境的一致运行。

从技术趋势来看,Docker是容器技术的事实标准,其生态体系仍在快速完善,掌握容器技术是职业能力提升的核心路径。

1.2 容器生态全景

容器是典型的平台级技术,生态体系覆盖核心技术、平台技术、支持技术三大层级,学习前先建立全局认知,可避免知识点碎片化。

1.2.1 容器核心技术

核心技术是容器运行的基础,支撑容器在主机上的完整生命周期。

技术分类说明主流实现
容器规范定义容器标准,保证不同厂商容器的可移植性与互操作性OCI(开放容器倡议)发布的运行时规范、镜像格式规范
容器运行时(Runtime)真正运行容器的组件,与操作系统内核协作提供运行环境runc(Docker默认,符合OCI规范)、lxc、rkt
容器管理工具对接运行时,向用户提供操作接口Docker Engine、lxd、rkt cli
容器定义工具定义容器的内容与属性,支持保存、共享与重建Docker镜像、Dockerfile、ACI(rkt镜像格式)
镜像仓库(Registry)统一存储、分发容器镜像的仓库Docker Hub、Quay.io、Harbor、私有Registry
容器操作系统专为容器定制的轻量化操作系统,体积小、启动快、运行效率高CoreOS、Atomic、Ubuntu Core

补充说明:OCI(Open Container Initiative)由Docker、Google、红帽等厂商联合成立,目的是制定开放的容器标准,避免生态碎片化。

1.2.2 容器平台技术

平台技术支撑容器在分布式集群环境中运行,面向微服务架构的部署与管理。

  1. 容器编排引擎

    :负责容器集群的管理、调度、服务发现、自动扩缩容等,主流实现:

    • Docker Swarm:Docker官方自研编排工具,轻量易用
    • Kubernetes(K8s):Google主导的开源编排引擎,是当前业界事实标准
    • Mesos+Marathon:通用集群资源调度平台,兼顾容器与非容器负载
  2. 容器管理平台:封装编排引擎底层细节,提供应用目录、一键部署等更易用的功能,代表:Rancher、ContainerShip。

  3. 容器化PaaS:面向应用开发的平台,屏蔽底层基础设施,代表:Deis、Flynn、Dokku。

1.2.3 容器支持技术

支撑容器基础设施的周边技术体系。

技术分类作用主流方案
容器网络管理容器间、容器与外部的连通性与隔离性Docker原生网络、Flannel、Weave、Calico
服务发现动态维护微服务的地址信息,解决容器IP动态变化的问题etcd、Consul、ZooKeeper
监控方案采集容器状态、资源使用率等监控数据docker stats、cAdvisor、Sysdig
数据管理实现容器持久化数据的迁移与管理Flocker
日志管理收集、转发、存储容器日志docker logs、Logspout
安全扫描检测容器镜像的漏洞与风险OpenSCAP、Docker Scout

第2章 容器架构与核心原理

2.1 容器的本质:What/Why/How

2.1.1 什么是容器

容器是一种轻量级、可移植、自包含的软件打包技术,应用及其依赖被打包在容器中,可在几乎任何环境以一致的方式运行。

容器与虚拟机是经常被对比的两种虚拟化技术,核心差异如下:

对比维度容器虚拟机
启动速度秒级甚至毫秒级数秒至数十秒
内核使用共享宿主机内核独立完整内核
实现原理基于Linux内核Namespace+Cgroup等技术,进程级隔离基于Hypervisor虚拟化,系统级隔离
资源消耗极小,仅额外消耗进程级开销较高,需要完整操作系统资源
运行密度单台主机可启动上千个容器单台主机通常几十个虚拟机
镜像大小MB级GB级
适用场景DevOps、微服务、持续集成硬件资源划分、强隔离需求
2.1.2 为什么需要容器

容器核心解决的是应用可移植性问题。 当前软件开发面临「多服务组件+多部署环境」的双重复杂度:应用包含MQ、缓存、数据库等多种服务,同时需要部署在虚拟机、私有云、公有云等不同环境,形成了N×M的配置矩阵,开发与运维成本极高。

Docker借鉴了物流行业「集装箱」的思想:将应用及其依赖统一打包成标准“容器”,容器在整个生命周期中密封,跨环境无需开箱,直接运行,彻底解决了环境差异带来的部署问题。

2.1.3 容器的核心特性

对应集装箱的设计思想,Docker的核心特性如下:

  • 标准化打包:任何软件及其依赖都可打包成容器镜像
  • 环境一致性:容器无需修改即可运行在虚拟机、物理机、公有云、私有云
  • 资源隔离:容器间资源、网络、依赖完全隔离,互不影响
  • 自动化操作:提供标准化的启动、停止、删除接口,适配自动化运维
  • 轻量高效:秒级启动,迁移快速,资源开销极低
  • 职责解耦:开发聚焦业务代码,运维聚焦基础环境

2.2 Docker架构详解

Docker采用客户端-服务器(C/S)架构,核心组件包括客户端、守护进程、镜像、仓库、容器五部分。

2.2.1 核心组件
  1. Docker客户端(Client) 用户与Docker交互的入口,以命令行(CLI)为主要形式。客户端将用户命令通过REST API发送给守护进程执行。 常用命令包括docker rundocker builddocker pull等,也支持通过-H参数连接远程守护进程。
  2. Docker守护进程(Daemon) 后台运行的dockerd服务,负责监听API请求、管理Docker对象(镜像、容器、网络、卷等),也可与其他守护进程通信实现集群管理。
  3. Docker镜像(Image) 只读的容器模板,包含创建容器的指令与文件系统。镜像基于分层结构构建,可基于基础镜像扩展新镜像。
  4. 镜像仓库(Registry) 集中存储和分发镜像的服务。分为公共仓库(如Docker Hub)和私有仓库(如Harbor、自建Registry)。
  5. Docker容器(Container) 镜像的运行实例,是可读写的运行环境。可通过API或CLI创建、启动、停止、删除容器。
2.2.2 内部实现机制

Docker守护进程内部通过不同驱动实现核心能力:

  • Graph driver:管理镜像分层文件系统
  • Network driver:创建与管理容器网络
  • Exec driver:执行容器内命令,限制资源使用
  • Libcontainer:独立的容器管理库,底层对接内核Namespace与Cgroup

2.3 Docker组件协作流程

docker run httpd为例,组件协作流程如下:

  1. 客户端执行docker run命令,向守护进程发送请求
  2. 守护进程检查本地是否存在httpd镜像,不存在则从Registry下载
  3. 镜像下载完成后保存到本地存储
  4. 守护进程基于镜像创建容器,分配资源、启动进程
  5. 将执行结果返回给客户端

可通过docker images查看本地镜像,docker ps查看运行中的容器,验证上述流程。


第3章 Docker镜像

3.1 镜像原理与分层结构

镜像是容器的基础,本质是分层的只读文件系统。

3.1.1 最小镜像:hello-world

hello-world是Docker官方提供的最简镜像,仅十几KB,用于验证Docker环境。 其Dockerfile仅3条指令:

FROM scratch
COPY hello /
CMD ["/hello"]
  • FROM scratch:从空文件系统开始构建,是最基础的根镜像
  • COPY hello /:将可执行文件hello复制到镜像根目录
  • CMD ["/hello"]:容器启动时执行hello程序
3.1.2 基础镜像(Base Image)

基础镜像指提供基础操作系统环境的镜像,如CentOS、Ubuntu、Debian等。 核心原理:容器共享宿主机的Linux内核,镜像仅需要提供用户态的rootfs文件系统,因此体积远小于完整操作系统。

  • 例如CentOS 7镜像仅200MB左右,而完整安装的CentOS系统需要数GB
  • 容器内的内核版本与宿主机完全一致,无法单独升级内核

注意:如果应用对内核版本有严格要求,不适合使用容器部署,建议使用虚拟机。

3.1.3 分层结构与Copy-on-Write

Docker镜像采用分层堆叠结构,每安装一个软件就增加一层镜像层,所有镜像层都是只读的。 容器启动时,会在镜像层顶部添加一层可写的容器层

  • 新增文件:直接写入容器层
  • 修改文件:先从镜像层复制到容器层,修改后保存在容器层(写时复制Copy-on-Write)
  • 删除文件:在容器层创建whiteout文件遮挡下层文件
  • 读取文件:从上到下逐层查找,返回最先找到的文件

核心优势:镜像层可被多个容器共享,大幅节省磁盘与内存空间;同时镜像构建可复用缓存,提升构建效率。

3.2 构建镜像的两种方式

3.2.1 docker commit(不推荐)

通过提交运行中容器的修改生成新镜像,分为三步:运行容器→修改容器→提交为镜像。

示例:在ubuntu镜像中安装vim并生成新镜像

# 1. 运行交互容器
docker run -it ubuntu

# 2. 容器内安装vim
apt-get update && apt-get install -y vim

# 3. 新开终端,提交容器为新镜像
docker commit <容器ID/名称> ubuntu-with-vim

缺点:手工构建效率低、可重复性差、无法审计镜像内容,存在安全隐患,仅用于临时调试。

3.2.2 Dockerfile构建(推荐)

Dockerfile是记录镜像构建步骤的文本文件,每条指令对应一个镜像层,可重复、可审计,是构建镜像的标准方式。

基础构建命令:

docker build -t <镜像名:标签> <构建上下文路径>
  • -t:指定镜像名称与标签
  • 构建上下文:打包发送给守护进程的目录,Dockerfile中的COPY/ADD指令只能引用上下文中的文件
  • 默认查找上下文目录下名为Dockerfile的文件,可通过-f指定自定义路径

3.3 Dockerfile指令详解

3.3.1 核心指令说明
指令作用说明
FROM指定基础镜像必须是第一条指令
MAINTAINER声明镜像作者可选,现已推荐使用LABEL
COPY复制构建上下文中的文件到镜像仅复制,不解压归档文件
ADD复制文件到镜像源为归档文件时自动解压,支持远程URL
ENV设置环境变量后续指令可引用
EXPOSE声明容器监听端口仅做声明,不自动映射端口
VOLUME声明数据卷挂载点容器启动时自动创建managed volume
WORKDIR设置工作目录为后续指令指定默认路径,不存在则自动创建
RUN构建时执行命令创建新的镜像层,用于安装软件
CMD容器启动默认命令可被docker run后的参数覆盖,仅最后一条生效
ENTRYPOINT容器启动入口命令一定会执行,docker run参数会作为参数传入
3.3.2 RUN/CMD/ENTRYPOINT对比

三个指令都可执行命令,核心区别如下:

  • RUN:构建镜像时执行,用于安装软件、配置环境,生成镜像层
  • CMD:容器启动时默认执行,可被命令行参数覆盖
  • ENTRYPOINT:容器启动时必定执行,命令行参数会作为追加参数传入

最佳实践:服务类镜像优先使用Exec格式的ENTRYPOINT,搭配CMD提供默认参数;工具类镜像可使用CMD设置默认命令。

3.3.3 Shell格式与Exec格式
  • Shell格式RUN apt-get install vim,底层调用/bin/sh -c执行命令,支持环境变量解析
  • Exec格式RUN ["apt-get", "install", "-y", "vim"],直接执行程序,不启动shell,环境变量不会被解析
3.3.4 构建缓存特性

Docker构建时会缓存已有的镜像层,指令未变化时直接复用缓存,大幅提升构建速度。

  • 某一层指令修改后,其上方所有层缓存有效,下方所有层缓存失效
  • 可通过--no-cache参数强制禁用缓存

3.4 镜像命名与分发

3.4.1 镜像命名规范

完整镜像名称格式:

[仓库地址/命名空间/]仓库名:标签
  • 标签(Tag):用于标识版本,默认值为latest,不代表“最新稳定版”,仅表示未指定标签时的默认值
  • Docker Hub官方镜像可省略仓库地址,例如httpd:latest
3.4.2 标签最佳实践

采用语义化版本方案,例如镜像myimage发布v1.9.1时,同时打标签:1.9.11.91latest。 版本更新时,移动对应大版本、次版本的标签,用户可灵活选择精度。

3.4.3 公共镜像仓库使用
  1. Docker Hub:全球最大公共镜像仓库,注册账号后可上传自有镜像

    # 登录
    docker login
    # 重命名镜像,匹配账号格式
    docker tag httpd:latest <用户名>/httpd:v1
    # 上传镜像
    docker push <用户名>/httpd:v1
    
  2. 国内镜像加速器:解决Docker Hub访问慢的问题,阿里云、华为云均提供免费加速服务 配置方式(以阿里云为例):

    mkdir -p /etc/docker
    tee /etc/docker/daemon.json <<-'EOF'
    {
      "registry-mirrors": ["https://<加速器地址>.mirror.aliyuncs.com"]
    }
    EOF
    systemctl daemon-reload
    systemctl restart docker
    

    可通过docker info查看Registry Mirrors字段验证配置。

3.5 私有镜像仓库搭建

3.5.1 官方Registry(轻量版)

Docker官方提供的开源镜像仓库,单容器即可启动。

# 启动Registry容器,挂载数据目录到宿主机
docker run -d -p 5000:5000 -v /myregistry:/var/lib/registry registry:2

# 重命名镜像
docker tag httpd:latest localhost:5000/httpd:v1

# 上传镜像
docker push localhost:5000/httpd:v1

# 验证仓库
curl http://localhost:5000/v2/_catalog

官方Registry功能简单,适合小型场景;企业级场景推荐使用Harbor。

3.5.2 Harbor企业级仓库

Harbor是VMware开源的企业级镜像仓库,提供Web UI、权限管理、审计日志、安全扫描等功能。

安装步骤

  1. 下载离线安装包(推荐v2.9.1稳定版)并解压

  2. 复制文件到安装目录,修改

    harbor.yml
    

    配置:

    • hostname:设置为服务器IP或域名
    • 注释掉https配置(内网可暂用HTTP)
    • 设置管理员密码
  3. 执行./prepare生成配置,再执行./install.sh安装启动

  4. 配置Docker信任该仓库:

    {
      "insecure-registries": ["192.168.108.30"]
    }
    
  5. 登录并上传/下载镜像

    docker login 192.168.108.30
    docker tag nginx:latest 192.168.108.30/cloud/nginx:latest
    docker push 192.168.108.30/cloud/nginx:latest
    

3.6 镜像本地导入导出

命令作用特点
docker save将镜像保存为tar包保留完整镜像历史与元数据,可跨主机迁移镜像
docker load从tar包导入镜像对应save命令导出的文件
docker export将容器文件系统导出为tar包仅保存容器当前状态,丢失历史与元数据,体积更小
docker import导入容器tar包为镜像对应export命令导出的文件

示例:

# 保存镜像
docker save httpd hello-world -o images.tar

# 导入镜像
docker load -i images.tar

本章小结

  • 镜像是分层只读文件系统,基于Copy-on-Write机制实现高效共享
  • Dockerfile是构建镜像的标准方式,核心指令需区分RUN/CMD/ENTRYPOINT的差异
  • 镜像可通过公共仓库、私有仓库分发,也可通过save/load做本地迁移
  • 企业级场景推荐使用Harbor搭建私有镜像仓库

第4章 Docker容器

4.1 容器生命周期操作

4.1.1 启动容器

docker run = docker create + docker start,是创建并启动容器的核心命令。

常用参数:

  • -d:后台守护模式运行
  • -it:交互模式,分配终端并打开标准输入
  • --name:指定容器名称
  • -p:端口映射
  • -v:数据卷挂载
  • -e:设置环境变量
  • --restart:重启策略,可选no/always/on-failure:N

重启策略说明--restart=always表示容器退出时自动重启(手动stop除外);on-failure:3表示异常退出时最多重启3次。

4.1.2 进入容器

两种常用方式:

  1. docker attach

    :附加到容器启动命令的终端,不启动新进程

    • 退出快捷键:Ctrl+P然后Ctrl+Q,直接Ctrl+C会终止容器
  2. docker exec

    :在运行容器中启动新进程,是最常用方式

    docker exec -it <容器ID/名称> bash
    
4.1.3 状态管理命令
命令作用
docker ps / docker ps -a查看运行中/所有容器
docker start/stop/restart启动/停止/重启容器
docker pause/unpause暂停/恢复容器,暂停时不占用CPU
docker kill强制停止容器(发送SIGKILL)
docker rm删除容器,-f强制删除运行中容器
docker rename重命名容器

批量操作示例:

# 删除所有已退出的容器
docker rm -f $(docker ps -aq -f status=exited)

# 强制删除所有容器(谨慎使用)
docker rm -f $(docker ps -aq)
4.1.4 容器状态机

容器完整生命周期状态流转: CreatedRunningPausedRunning/ExitedRunning/Deleted

  • docker create创建的容器处于Created状态
  • 正常执行完启动命令或stop/kill后进入Exited状态
  • pause命令暂停后进入Paused状态

4.2 容器资源限制

Docker通过Linux内核的Cgroup机制限制容器资源,核心包括CPU、内存、磁盘IO三大类。

4.2.1 内存限制
  • -m / --memory:设置物理内存使用限额,如200M2G
  • --memory-swap:设置内存+swap总限额

常用配置说明:

  • -m 200M --memory-swap=300M:物理内存200M,可用swap 100M
  • 仅设置-m时,swap默认等于内存大小,即总限额为内存的2倍
  • --memory-swap=-1:swap不受限制,可用宿主机全部swap空间
4.2.2 CPU限制

通过--cpu-shares设置CPU时间片权重,默认值1024。

  • 权重是相对值,仅在CPU资源紧张时生效
  • 例如两个容器权重分别为1024和512,CPU满载时获得的时间片比例为2:1
  • 单个容器运行时,即使权重很低也可占用全部CPU资源

4.3 容器底层实现原理

容器的两大核心技术:Namespace实现资源隔离,Cgroup实现资源限制

4.3.1 Namespace(命名空间)

让容器认为自己拥有独立的全局资源,共6种:

  • Mount Namespace:隔离文件系统挂载点,容器有独立的根目录
  • UTS Namespace:隔离主机名,容器可设置独立hostname
  • IPC Namespace:隔离进程间通信,容器内共享内存、信号量独立
  • PID Namespace:隔离进程ID,容器内有独立的PID 1进程
  • Network Namespace:隔离网络栈,容器有独立的网卡、IP、路由表
  • User Namespace:隔离用户,容器内用户不映射到宿主机
4.3.2 Cgroup(控制组)

Linux内核提供的进程资源管控机制,Docker使用的核心子系统:

  • cpu:CPU调度权重
  • memory:内存使用限额
  • blkio:块设备IO限制
  • cpuset:绑定CPU核心
  • devices:设备访问权限控制

可在/sys/fs/cgroup/目录下查看每个容器对应的Cgroup配置。

本章小结

  • 容器生命周期操作是日常运维的基础,需熟练掌握run、exec、ps、rm等核心命令
  • 资源限制通过Cgroup实现,生产环境必须配置内存与CPU限额,避免容器抢占宿主机资源
  • Namespace实现了容器的六大隔离维度,是容器轻量隔离的核心原理

第5章 Docker网络

5.1 四大原生网络模式

Docker安装后默认创建bridge、host、none三种网络,加上container模式共四类。

网络模式驱动说明适用场景
bridgebridge默认模式,容器挂在docker0网桥上,通过NAT访问外网大多数单主机场景
hosthost共享宿主机网络命名空间,网络配置与宿主机完全一致高网络性能需求场景
nonenull无网络,仅回环接口高安全、无需联网的容器
container-共享另一个容器的网络栈容器间通过loopback高效通信、网络监控
5.1.1 none网络

容器只有lo回环接口,完全无法联网,用于对安全性要求极高的离线场景,如密码生成容器。

5.1.2 host网络

容器共享宿主机的网络栈,性能接近原生,但端口会与宿主机冲突,适合网络传输密集型应用。

5.1.3 bridge网络(默认)

Docker创建名为docker0的Linux网桥,容器通过veth pair连接到网桥上,是最常用的模式。

  • 网桥默认网段:172.17.0.0/16,网关为docker0的IP172.17.0.1
  • 容器自动从网段分配IP,通过宿主机的NAT规则访问外网
  • 不同网桥之间默认被iptables隔离,无法直接通信

5.2 自定义bridge网络

5.2.1 创建自定义网络
# 创建默认网段的bridge网络
docker network create --driver bridge my_net

# 指定网段与网关
docker network create --driver bridge --subnet 172.22.16.0/24 --gateway 172.22.16.1 my_net2
5.2.2 指定容器IP

只有用户指定子网的网络支持静态IP:

docker run -it --network=my_net2 --ip 172.22.16.8 busybox
5.2.3 网络连接管理
# 将已有容器加入指定网络
docker network connect my_net2 <容器名>

# 断开容器网络
docker network disconnect my_net2 <容器名>

一个容器可同时加入多个网络,实现不同网络域的连通。

5.3 容器间通信

5.3.1 IP通信

同一网络中的容器可直接通过IP通信,是最基础的方式。

5.3.2 Docker DNS服务

自定义bridge网络支持内置DNS,容器可直接通过容器名通信。

# 启动两个容器,指定名称
docker run -itd --network=my_net2 --name bbox1 busybox
docker run -itd --network=my_net2 --name bbox2 busybox

# bbox2中ping bbox1
docker exec -it bbox2 ping bbox1

注意:默认bridge网络不支持DNS解析,必须使用自定义网络。

5.3.3 Joined容器

多个容器共享同一个网络栈,通过127.0.0.1互相访问,适合紧密耦合的服务。

# 启动web容器
docker run -d --name web1 httpd

# busybox共享web1的网络
docker run -it --network=container:web1 busybox

两个容器网卡、IP、端口完全一致,可直接通过回环地址访问对方服务。

5.4 外部访问与端口映射

容器访问外网默认通过宿主机NAT实现;外部访问容器需要端口映射。

5.4.1 端口映射语法
# 指定宿主机端口:容器端口
docker run -d -p 8080:80 httpd

# 宿主机随机分配端口
docker run -d -p 80 httpd

可通过docker psdocker port <容器名>查看映射关系。

5.4.2 实现原理

宿主机上的docker-proxy进程监听映射端口,将流量转发到对应容器的端口;同时iptables配置MASQUERADE规则实现容器出站NAT。

本章小结

  • bridge是默认网络模式,生产环境推荐创建自定义bridge网络,启用DNS服务
  • 容器间通信三种方式:IP、DNS、Joined容器,各有适用场景
  • 端口映射是外部访问容器服务的核心方式,底层通过docker-proxy与iptables实现

第6章 Docker存储

6.1 存储驱动与分层文件系统

Docker通过存储驱动(Storage Driver)实现镜像分层结构,CentOS Stream 8默认使用overlay2驱动,底层文件系统为xfs。 镜像与容器层数据默认存储在/var/lib/docker/目录下。

最佳实践:优先使用发行版默认的存储驱动,经过最充分的兼容性测试。

分层文件系统适合无状态应用:应用本身作为镜像的一部分,容器销毁时数据随之清除,无需持久化。

6.2 数据卷(Data Volume)

数据卷是宿主机文件系统中的目录/文件,直接挂载到容器中,用于持久化数据,生命周期独立于容器。

分为两类:

6.2.1 Bind Mount(绑定挂载)

将宿主机上指定的目录/文件挂载到容器中。

# 挂载目录
docker run -d -p 80:80 -v /root/htdocs:/usr/local/apache2/htdocs httpd

# 只读挂载
docker run -d -p 80:80 -v /root/htdocs:/usr/local/apache2/htdocs:ro httpd
  • 优点:直观灵活,可直接在宿主机操作数据
  • 缺点:依赖宿主机特定路径,移植性差
6.2.2 Docker Managed Volume(托管卷)

Docker在/var/lib/docker/volumes/下自动创建管理的卷,只需指定容器内挂载点。

docker run -d -p 80:80 -v /usr/local/apache2/htdocs httpd
  • 优点:移植性强,无需关心宿主机路径
  • 缺点:访问数据需要通过容器或进入卷目录
6.2.3 两类卷对比
对比项Bind MountDocker Managed Volume
卷位置宿主机任意路径/var/lib/docker/volumes/下
对已有目录影响隐藏原有内容,替换为宿主机数据将容器内原有数据复制到卷中
单文件支持支持不支持,仅支持目录
权限控制支持只读/读写仅读写
移植性弱,绑定宿主机路径强,与宿主机解耦

6.3 数据共享方案

6.3.1 宿主机与容器共享
  • Bind Mount直接挂载共享目录

  • Managed Volume可通过

    docker cp
    

    在宿主机与容器间拷贝文件

    # 宿主机文件拷贝到容器
    docker cp /root/index.html <容器名>:/usr/local/apache2/htdocs
    
6.3.2 多容器共享数据
  1. 共享Bind Mount:多个容器挂载同一个宿主机目录

  2. 数据卷容器(Volume Container)

    :专门提供数据卷的容器,其他容器通过

    --volumes-from
    

    挂载

    # 创建数据卷容器
    docker create --name vc_data -v /root/htdocs:/usr/local/apache2/htdocs busybox
    
    # 业务容器挂载数据卷容器
    docker run -d --name web1 --volumes-from vc_data httpd
    
  3. Data-packed Volume Container:将数据打包到镜像中,自包含数据,移植性极强,适合静态配置、静态文件场景。

6.4 数据卷生命周期管理

  • 备份:直接备份宿主机上的卷目录即可

  • 恢复:将备份数据拷贝回卷目录

  • 迁移:停止旧容器,启动新容器挂载同一卷

  • 删除

    • Bind Mount不会随容器删除,需手动清理
    • Managed Volume:docker rm -v删除容器时同时删除卷;孤儿卷可通过docker volume prune清理

注意:生产环境数据库等有状态服务必须使用数据卷持久化数据,避免容器删除导致数据丢失。

本章小结

  • 容器存储分为分层文件系统和数据卷,无状态应用用前者,持久化数据用后者
  • 数据卷分Bind Mount和Managed Volume,按需选择;生产环境推荐Managed Volume配合数据卷容器
  • 数据卷生命周期独立于容器,删除容器时注意重要数据备份

第7章 容器监控

7.1 Docker原生监控命令

命令作用
docker ps查看容器运行状态、端口、名称等基础信息
docker top <容器>查看容器内运行的进程,支持ps命令参数
docker stats实时查看容器CPU、内存、网络IO、磁盘IO使用率

docker stats默认实时刷新,支持--no-stream只输出一次结果,支持自定义输出格式。

7.2 cAdvisor监控工具

Google开源的容器监控数据采集工具,可采集容器资源使用数据,并提供Web界面查看。

部署命令:

docker run \
  --volume=/:/rootfs:ro \
  --volume=/var/run:/var/run:rw \
  --volume=/sys:/sys:ro \
  --volume=/var/lib/docker/:/var/lib/docker:ro \
  --publish=8080:8080 \
  --detach=true \
  --name=cadvisor \
  google/cadvisor:latest

访问http://<宿主机IP>:8080即可查看监控界面。

  • 优点:数据全面,可导出对接第三方监控系统
  • 缺点:仅支持单主机,可视化能力弱,通常作为数据采集器配合Grafana等使用

本章小结

  • 日常排查优先使用docker原生命令,轻量高效
  • cAdvisor适合作为监控数据采集组件,生产环境通常配合Prometheus+Grafana构建完整监控体系

第8章 容器日志

8.1 docker logs命令

Docker将容器标准输出(STDOUT)与标准错误(STDERR)作为日志收集,通过docker logs查看。

常用参数:

  • -f:持续跟踪日志,类似tail -f
  • --tail N:查看最后N行
  • -t:显示时间戳

示例:

# 查看最近10行日志并持续跟踪
docker logs -f --tail 10 <容器名>

8.2 日志管理最佳实践

  • 应用日志输出到标准输出/标准错误,不要写入文件,由Docker统一管理
  • 生产环境部署集中式日志方案,通过日志驱动将日志转发到ELK等日志平台
  • 单个容器日志文件过大时,可配置日志轮转策略

本章小结

  • docker logs是排查容器问题的核心工具,需熟练掌握常用参数
  • 生产环境遵循日志标准化原则,输出到控制台,配合集中式日志系统管理

第9章 Docker Compose多容器编排

9.1 Compose概述

Docker Compose是定义和运行多容器应用的工具,通过YAML文件定义一组关联的容器服务,实现一键启停、批量管理。

两个核心概念:

  • 服务(Service):一个应用组件对应的容器集群
  • 项目(Project):一组关联服务组成的完整业务单元

Compose V2已用Go语言重写,集成在Docker CLI中,通过docker compose命令调用。

9.2 Compose模板文件

默认文件名为docker-compose.yml,核心结构:

services:
  服务名:
    image: 镜像名
    restart: 重启策略
    ports:
      - "宿主机端口:容器端口"
    volumes:
      - 卷映射
    environment:
      - 环境变量=值
    links:
      - 关联服务名

常用命令:

# 后台启动所有服务
docker compose up -d

# 停止并删除所有容器、网络
docker compose down

# 查看服务状态
docker compose ps

# 查看服务日志
docker compose logs -f

9.3 实战:WordPress多容器部署

实现WordPress+MySQL的博客系统,一键启动。

  1. 创建项目目录,编写docker-compose.yml
services:
  blog:
    image: wordpress:latest
    restart: always
    links:
      - db
    ports:
      - "80:80"
    environment:
      - WORDPRESS_DB_HOST=db
      - WORDPRESS_DB_USER=root
      - WORDPRESS_DB_PASSWORD=huawei
      - WORDPRESS_DB_NAME=wordpress
    volumes:
      - ./web:/var/www/html

  db:
    image: mysql:5.7
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=huawei
      - MYSQL_DATABASE=wordpress
    volumes:
      - ./mysql:/var/lib/mysql
  1. 启动服务
docker compose up -d
  1. 访问http://<宿主机IP>,完成WordPress初始化配置即可使用。

本章小结

  • Compose是单主机多容器编排的首选工具,通过声明式配置简化多容器管理
  • 模板文件遵循YAML语法,注意缩进与格式规范
  • 适合开发测试环境、小型应用部署,大规模集群推荐使用Kubernetes

第10章 图形化管理工具

10.1 DockerUI

轻量级国产Docker管理工具,Web界面友好,适合Docker初学者。

部署命令:

docker run -d --name docker.ui --restart always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -p 8999:8999 joinsunsoft/docker.ui
  • 访问地址:http://<宿主机IP>:8999
  • 默认账号密码:ginghan/123456
  • 功能:容器、镜像、卷、网络管理,Swarm集群管理等

10.2 Portainer

主流的开源容器管理平台,分为社区版和商业版,社区版免费,功能全面。

部署步骤:

# 创建数据卷
docker volume create portainer_data

# 启动Portainer
docker run -d -p 8000:8000 -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://<宿主机IP>:9443
  • 首次访问创建管理员账号,连接本地Docker环境即可管理

本章小结

  • 图形化工具降低了Docker操作门槛,适合管理多主机或非专业人员使用
  • Portainer是当前主流选择,功能完善,社区活跃

综合实验

实验1:部署Ghost开源内容管理系统

Ghost是基于Node.js的开源CMS系统,适合博客、内容网站。

  1. 创建数据目录
mkdir -p /data/ghost
chmod -R 777 /data/ghost
  1. 启动Ghost容器
docker run -d \
  --restart always \
  --name ghost \
  -p 2368:2368 \
  -v /data/ghost:/var/lib/ghost/content \
  -e NODE_ENV=development \
  -e url=http://<宿主机IP>:2368 \
  ghost
  1. 验证访问:浏览器打开http://<宿主机IP>:2368/ghost,完成管理员注册即可使用。

实验2:构建自定义Java环境镜像

基于CentOS 8构建包含JDK 8、vim、网络工具的自定义镜像。

  1. 准备JDK安装包(从Oracle官网下载对应版本)与Dockerfile放在同一目录
  2. 编写Dockerfile
FROM centos:8.4.2105
MAINTAINER author <email@example.com>

ENV MYPATH /usr/local
WORKDIR $MYPATH

# 配置阿里云CentOS Vault源
RUN minorver=8.4.2105 \
  && sed -e "s|^mirrorlist=|#mirrorlist=|g" \
  -e "s|^#baseurl=http://mirror.centos.org/\$contentdir/\$releasever|baseurl=https://mirrors.aliyun.com/centos-vault/$minorver|g" \
  -i.bak /etc/yum.repos.d/CentOS-*.repo

# 安装基础工具
RUN yum -y install vim net-tools glibc.i686

# 安装JDK
RUN mkdir /usr/local/java
ADD jdk-8u461-linux-x64.tar.gz /usr/local/java/

# 配置环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_461
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH

EXPOSE 80
CMD ["/bin/bash"]
  1. 构建镜像并验证
docker build -t centos-java8:461 .
docker run -it centos-java8:461 java -version
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐