Docker 学习笔记:从生态系统到镜像构建

Docker 学习笔记:从生态系统到镜像构建

本笔记系统梳理了容器生态、Docker 架构、镜像原理与 Dockerfile 最佳实践。保留了全部关键实验代码,文末提供知识速查表,适合快速复习与查阅。


1. 容器生态系统鸟瞰

容器技术绝非只有 Docker,而是一整套分层、协作的技术栈。理解整体生态,才能分清主次、有的放矢。

1.1 核心技术

让容器在 Host OS 上跑起来的最基础组件。

  • 容器规范 :OCI (Open Container Initiative) 制定 runtime specimage format spec,保证不同容器间的可移植性。
  • 容器 runtimelxc, runc, rkt。runc 是 Docker 默认 runtime。
  • 容器管理工具 :对内与 runtime 交互,对外提供 CLI。Docker Engine (dockerd + docker CLI)、lxdrkt CLI
  • 容器定义工具:Docker image(模板)、Dockerfile(构建镜像的文本文件)。
  • Registry :存放镜像的仓库。公共的有 Docker Hub、Quay.io;企业可自建私有 Registry。
  • 容器 OS:裁剪过的操作系统,专用于运行容器,如 CoreOS、Atomic、Ubuntu Core。

1.2 平台技术

使容器作为集群在分布式环境中运行。

  • 容器编排引擎:管理集群中的容器,实现调度、服务发现、动态伸缩。主流:Docker Swarm、Kubernetes、Mesos+Marathon。
  • 容器管理平台:在编排引擎之上的通用平台,如 Rancher、ContainerShip。
  • 基于容器的 PaaS:开发者无需关心基础设施,如 Deis、Flynn、Dokku。

1.3 支持技术

为容器基础设施提供周边能力。

  • 容器网络:Docker network、Flannel、Calico、Weave 等。
  • 服务发现:动态跟踪容器服务位置。常用 etcd、Consul、Zookeeper。
  • 监控:Docker stats、cAdvisor、Weave Scope、Sysdig。
  • 数据管理:跨主机迁移持久化数据,如 Flocker。
  • 日志管理:Docker logs、Logspout。
  • 安全性:扫描镜像漏洞,如 OpenSCAP。

2. Docker 安装与加速

2.1 安装 Docker CE (CentOS Stream 8)

bash

bash 复制代码
# 卸载旧版本
yum remove docker docker-client docker-client-latest docker-common docker-latest ...

# 安装必要工具
yum install -y yum-utils device-mapper-persistent-data lvm2 vim

# 添加阿里云镜像仓库
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 生成缓存并安装
yum makecache
yum install -y docker-ce

# 启动并设置开机自启
systemctl enable docker.service --now
docker --version

2.2 配置镜像加速器(阿里云/华为云)

bash

bash 复制代码
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://spcqvmfn.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker
docker info | grep "Registry Mirrors"

3. Docker C/S 分离部署

Docker 采用 Client/Server 架构。可在独立管理机上仅安装客户端,远程连接 Docker 服务端。

3.1 服务端配置(docker_server: 192.168.108.30)

bash

bash 复制代码
# 安装 Docker 并启动
# 编辑服务文件,添加监听端口
vim /usr/lib/systemd/system/docker.service
# ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375

systemctl daemon-reload
systemctl restart docker
systemctl stop firewalld

3.2 客户端配置(docker_client: 192.168.108.31)

bash

bash 复制代码
# 仅安装 Docker CLI
yum install -y docker-ce-cli

# 远程连接服务端执行命令
docker -H 192.168.108.30 run hello-world
docker -H 192.168.108.30 images

4. 容器 What, Why, How

4.1 什么是容器?

容器是一种轻量级、可移植、自包含的软件打包技术,应用+依赖被打包成容器,可在几乎任何地方以相同方式运行。

4.2 容器 vs 虚拟机

特性 容器 虚拟机
启动速度 秒级/毫秒级 分钟级
内核 共享 Host OS 内核 各自独立 Guest OS
性能 接近原生 有额外虚拟化开销
镜像大小 MB 级 GB 级
运行密度 上千个 几十个
隔离性 进程级 系统级
迁移性 优秀 一般

4.3 为什么需要容器?------集装箱思想

Docker 借鉴了集装箱运输的理念。任何软件及其依赖被打包进标准化的"集装箱"(容器),开发、测试、运维环境无缝衔接,消除了"在我机器上能跑"的终极痛点。

Docker 特性与集装箱类比

  • 打包对象:任何货物 → 任何软件及依赖
  • 标准接口:标准集装箱接口 → 各种平台无修改运行
  • 隔离性:货物不会相互压坏 → 资源、库完全隔离
  • 自动化:易于机械装卸 → run, start, stop 标准化
  • 职责分工:货主关心装什么,承运方关心怎么运 → 开发关心代码,运维关心基础环境

5. Docker 核心概念与架构

5.1 三大核心概念

  • 镜像(Image):只读模板,例如一个包含 Apache 的 Ubuntu 系统。
  • 容器(Container):镜像的运行实例,轻量级沙盒。
  • 仓库(Registry):存放镜像的场所,分为公有(Docker Hub)和私有。

5.2 Docker 架构

Docker 采用 Client/Server 模型:

  • Docker Client :命令行工具 docker,通过 REST API 与 daemon 通信。
  • Docker Daemon:后台服务,管理镜像、容器、网络、存储等。
  • Registry:镜像仓库,默认 Docker Hub。

一次 docker run 的简单流程:

  1. Client 向 Daemon 发起请求。
  2. Daemon 检查本地有无镜像,若无则从 Registry 下载。
  3. Daemon 创建并启动容器,输出返回给 Client。

6. Docker 镜像深度解析

6.1 最小的镜像:hello-world

镜像仅 13.3 kB,Dockerfile 如下:

dockerfile

bash 复制代码
FROM scratch
COPY hello /
CMD ["hello"]

镜像内只有一个可执行文件 /hello,无 Shell、无 Lib,体现了镜像的极简理念。

6.2 base 镜像与 rootfs

  • base 镜像 :不依赖其他镜像,从 scratch 构建,提供最小化的 Linux 发行版 rootfs。

  • Linux 操作系统 = 内核空间 (kernel) + 用户空间 (rootfs)

  • 容器直接使用 Host 的 kernel,自身只提供 rootfs,因此 CentOS 镜像可以只有约 200 MB。

  • 不同 Linux 发行版的容器可以共用同一个 Host Kernel,例如在 CentOS Stream 8 的 Host 上运行 Ubuntu 容器:

    bash

    bash 复制代码
    docker run -it ubuntu uname -r   # 输出 Host 的 kernel 版本

6.3 镜像的分层结构与 Copy-on-Write

  • 镜像由多个只读层堆叠而成,每层对应 Dockerfile 的一条指令。
  • 容器启动时,在最顶层添加一个可写容器层
  • 修改文件时,先将文件从镜像层拷贝到容器层,再进行修改(Copy-on-Write)。
  • 删除文件时,在容器层创建 whiteout 文件遮挡下层文件。
  • 优势:多个镜像可共享相同的底层,节省磁盘和内存。

6.4 构建镜像:两种方式

方式1:docker commit(不推荐)

bash

bash 复制代码
docker run -it ubuntu
# 在容器内安装 vim
docker commit <容器ID> ubuntu-with-vim

缺点:手工操作,不可重复,无法审计,容易产生安全隐患。

方式2:Dockerfile(推荐)

dockerfile

dockerfile 复制代码
FROM ubuntu
RUN apt-get update && apt-get install -y vim

bash

dockerfile 复制代码
docker build -t ubuntu-with-vim-dockerfile .

构建过程:每执行一条指令,就会启动临时容器、执行命令、commit 为新层,然后删除临时容器。

6.5 镜像缓存特性

  • Docker 会缓存已有的镜像层,下次构建如层未变则直接复用。
  • 如果某层发生变化,其后的所有层缓存都失效。
  • 可用 --no-cache 强制不使用缓存。

6.6 调试 Dockerfile

如果某条指令失败,Docker 会保留前一条指令成功构建的镜像。可基于该镜像启动临时容器,手工执行失败命令来定位问题。

bash

bash 复制代码
docker run -it <最后成功镜像ID> sh

6.7 Dockerfile 常用指令详解

指令 说明
FROM 指定 base 镜像,第一条必须为 FROM
MAINTAINER 镜像作者信息(已弃用,建议用 LABEL)
COPY 从 build context 复制文件到镜像
ADD 类似 COPY,但能自动解压归档文件
ENV 设置环境变量,后续指令可用
EXPOSE 声明容器监听端口
VOLUME 声明挂载点
WORKDIR 为后续指令设置工作目录
RUN 在容器内执行命令,通常用于安装软件
CMD 容器启动时的默认命令,可被 docker run 后的命令覆盖
ENTRYPOINT 容器启动时运行,一般不会被覆盖

6.8 RUN vs CMD vs ENTRYPOINT

  • RUN:在构建镜像时执行,生成新的镜像层,常用于安装软件。
  • CMD :设置容器默认启动命令,若 docker run 指定了其他命令则被忽略。
  • ENTRYPOINT :设定容器启动时的主命令,docker run 的额外参数会作为该命令的参数。
Shell 格式 vs Exec 格式
  • Shell 格式:CMD echo "Hello" → 调用 /bin/sh -c
  • Exec 格式:CMD ["executable","param1"] → 直接调用 executable,推荐使用。

示例:

dockerfile

dockerfile 复制代码
FROM busybox
ENV name world
ENTRYPOINT ["/bin/echo", "Hello,"]
CMD ["${name}"]

如果 docker run 不加参数,输出 Hello, ${name}(因为 Exec 格式不会解析变量)。若改为 Shell 格式 ENTRYPOINT echo "Hello, $name",则会正确替换变量。

6.9 典型 Dockerfile 案例

带 SSH 的 CentOS 镜像

dockerfile

dockerfile 复制代码
FROM centos:8.4.2105
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 install -y openssh-server
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
RUN echo "root:huawei" | chpasswd
EXPOSE 22
CMD ["/usr/sbin/sshd","-D"]
自定义 httpd 镜像

dockerfile

dockerfile 复制代码
FROM centos:8.4.2105
# ... 替换 yum 源
RUN yum install -y httpd && yum clean all
COPY index.html /var/www/html/
EXPOSE 80
CMD ["/usr/sbin/httpd", "-DFOREGROUND"]
CentOS + Java 8 开发环境

dockerfile

dockerfile 复制代码
FROM centos:8.4.2105
ENV MYPATH /usr/local
WORKDIR $MYPATH
# 安装 vim、net-tools、glibc
RUN yum -y install vim net-tools glibc.i686
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
CMD /bin/bash

7. 知识点速查表

7.1 Docker 生态核心组件

层次 组件 常见实例
核心技术 容器规范 OCI
容器 runtime runc, lxc, rkt
管理工具 Docker Engine, lxd
定义工具 Dockerfile, Docker Image
Registry Docker Hub, Harbor
容器 OS CoreOS, Atomic
平台技术 编排引擎 Kubernetes, Swarm, Mesos
管理平台 Rancher, ContainerShip
容器 PaaS Deis, Flynn, Dokku
支持技术 网络 flannel, calico, weave
服务发现 etcd, consul, zookeeper
监控 cAdvisor, Weave Scope

7.2 容器与虚拟机快速对比

指标 容器 虚拟机
启动速度 秒/毫秒级 分钟级
镜像大小 MB 级 GB 级
系统内核 共享 Host 内核 各自完整 OS
性能 近原生 有虚拟化损耗
部署密度 数千个 数十个
隔离级别 进程级 系统级

7.3 Dockerfile 指令速查

指令 用途 重要备注
FROM 指定基础镜像 必须为第一条指令
RUN 执行命令并提交新层 用于安装软件,常结合 &&\ 减少层数
COPY 复制本地文件到镜像 优于 ADD(除非需要解压)
ADD 复制并自动解压归档文件 使用需谨慎
ENV 设置环境变量 后续指令及容器运行时均可用
WORKDIR 设置工作目录 不存在则自动创建
CMD 容器启动默认命令 可被 docker run 后命令覆盖
ENTRYPOINT 容器入口点命令 不会被覆盖,推荐 Exec 格式
EXPOSE 声明端口 仅声明,不实际映射
VOLUME 定义匿名卷 用于持久化或共享数据

7.4 docker run 常用参数

参数 作用 示例
-d 后台运行 docker run -d nginx
-p 端口映射 -p 8080:80
-v 挂载 volume -v /host/path:/container/path
-e 设置环境变量 -e MYSQL_ROOT_PASSWORD=123
--name 指定容器名 --name web
--restart 重启策略 --restart always
--network 指定网络模式 --network host

7.5 镜像构建与分发命令

命令 用途
docker build -t name:tag . 基于当前目录 Dockerfile 构建镜像
docker tag src dest 给镜像打新标签
docker push repository/image:tag 推送镜像到仓库
docker pull image:tag 从仓库拉取镜像
docker images 列出本地镜像
docker rmi image 删除镜像
docker history image 查看镜像构建历史(各层)
docker save -o file.tar image 导出镜像为 tar 文件
docker load -i file.tar 从 tar 文件导入镜像

本笔记覆盖 Docker 学习技术文档第1章至第3章017节,后续内容将涉及容器运行、网络、存储等,敬请期待。

相关推荐
剑神一笑1 小时前
Linux du 命令深度解析:从磁盘占用统计到目录空间分析
linux·运维·前端
知识分享小能手1 小时前
R语言入门学习教程,从入门到精通,R语言数据结构(4)
数据结构·学习·r语言
CoderMeijun1 小时前
Linux 进程间通信:共享内存详解
linux·共享内存·进程间通信·ipc·shmget
Brilliantwxx1 小时前
【算法题】递归树+哈希表+分治异或+双指针
开发语言·c++·笔记·算法
坚持就完事了1 小时前
Ubuntu和Centos中安装软件的命令
linux·ubuntu·centos
江湖有缘1 小时前
Docker部署PortNote端口自动检测工具
运维·docker·容器
程序猿编码1 小时前
Linux 高负载场景下 Web 服务访问日志极速定位工具实现解析(C/C++代码实现)
linux·服务器·c语言·前端·c++
CC城子1 小时前
嵌入式Linux宕机问题GDB调试(二)
linux·gdb
LuminousCPP1 小时前
C 语言文件操作全攻略:从基础读写到随机访问与缓冲区原理
c语言·经验分享·笔记·文件操作