当前位置: 首页 > news >正文

Docker技术全景解析

一、Docker是什么

1.1 定义

Docker是一种容器化技术平台,它通过操作系统级别的虚拟化,将应用程序及其依赖打包成标准化的可移植单元(容器)。这种技术实现了:

  • 环境一致性:消除“在我机器上能跑”的问题
  • 进程级隔离:每个容器拥有独立的文件系统、网络和进程空间
  • 资源高效利用:无需模拟完整操作系统

1.2 架构图

+----------------------+
|     App A   App B    |  ← 用户应用程序
+----------------------+
|  Docker容器  Docker容器 | ← 独立的运行环境
+----------------------+
|      Docker引擎        | ← 容器运行时管理
+----------------------+
|      操作系统内核       | ← 直接使用宿主机内核
+----------------------+
|      物理服务器         |
+----------------------+

二、Docker VS Hypervisor

2.1 Hypervisor介绍

这里先对Hypervisor进行简单说明。

Hypervisor虚拟化技术使用软件,在计算机硬件上创建一个抽象层,能够将单台计算机的硬件元素(处理器、内存、存储等)分成多个虚拟计算机,通常称为虚拟机。每个虚拟机都会运行自己的操作系统,其行为就像一台独立的计算机,即使它只在一部分实际底层计算机硬件上运行。

Hypervisor分为两大类:

  1. hypervisor直接运行在物理机之上,虚拟机运行在hypervisor之上。
  2. 物理机上安装正常的操作系统,然后在正常操作系统上安装hypervisor,生成和管理虚拟机。

2.2 差异点

对比维度Docker容器传统虚拟机
虚拟化级别操作系统级虚拟化硬件级虚拟化
资源占用共享宿主机内核,MB级内存占用需完整OS,GB级内存占用
启动速度秒级启动(毫秒级创建)分钟级启动
性能损耗接近原生(<5%)显著损耗(15%-20%)
隔离性进程级别隔离完全硬件隔离
移植性镜像跨平台部署镜像依赖Hypervisor
典型镜像大小Alpine镜像仅5MB,Ubuntu约70MBWindows镜像约4GB,CentOS约800MB
安全性依赖内核隔离,存在潜在风险完全硬件隔离,安全性更高
适用场景微服务、CI/CD、弹性伸缩完整OS环境、混合部署

三、Docker安装

使用国外的源,不稳定容易断连。此处给出基于国内源的安装方法。

sudo apt-get update
sudo apt-get install ca-certificates curl gnupg lsb-release
curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
docker --version

四、Dockerfile制作Docker镜像

4.1 镜像

什么是Docker镜像?简单的理解,Docker镜像就是一个Linux的文件系统(FS),这个文件系统包含可以运行在Linux内核上的程序以及相应的数据。通过镜像启动一个容器,一个镜像就是一个可执行的包,其中包括运行应用程序所需要的所有内容:包含代码、运行时间、库、环境变量和配置文件等。

Docker把APP文件打包成一个镜像,并且采用类似多次快照的存储技术,可以实现:

  • 多个App可以共用相同的底层镜像
  • App运行时的IO操作和镜像文件隔离
  • 通过挂载包含不同配置/数据文件的目录或者卷,单个APP镜像可以用来运行不同业务的容器(如果是用来做交叉编译,可以在镜像中集成不同交叉编译工具链,通过shell脚本控制编译不同平台的代码)

4.2 容器

镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

4.3 镜像分层

Docker支持通过扩展先有镜像,创建新的镜像。事实上,可能99%的镜像都是通过在base镜像上安装和配置需要的软件构建出来的。

从上图中可以看出,新镜像是从base镜像一层层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。在使用Dockerfile创建Docker镜像时,每个RUN、COPY动作都会生成一层新镜像。

镜像分层最大的一个好处就是共享资源。比如说有多个镜像都从相同的base镜像构建而来,那么 Docker Host只需在磁盘上保存一份base镜像;同时内存中也只需加载一份base镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。

如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如 /etc 下的文件,这时其他容器的 /etc 是不会被修改的,修改只会被限制在单个容器内。这就是容器 Copy-on-Write 特性(快照的特性,此处不做详细解释)。

当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的。镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统。如果不同层中有一个相同路径的文件,比如 /a,上层的 /a 会覆盖下层的 /a,也就是说用户只能访问到上层中的文件 /a。在容器层中,用户看到的是一个叠加之后的文件系统。

示例:文件修改流程

  1. 读取文件:直接访问底层镜像层中的文件

  2. 首次修改文件

    • 检查文件是否在可写层

    • 若不存在,从镜像层复制文件到可写层

    • 在可写层完成修改(原镜像层文件保持不变)

  3. 后续修改:直接操作可写层中的副本

4.4 Dockerfile

4.4.1 和镜像的关系

Dockerfile 是构建 Docker 镜像的 蓝图 和 指令集,而 镜像 是 Dockerfile 经过编译后生成的 只读分层文件包。二者的关系可以类比为:

类比项DockerfileDocker镜像
编程领域源代码(.java)编译后的字节码(.class)
建筑施工建筑设计图纸建成的大楼
烹饪领域菜谱制作完成的菜品

4.4.2 Dockerfile指令与镜像层关系

Dockerfile指令生成的镜像层内容是否创建新层典型大小影响
FROM基础镜像的所有层是(多层)决定基础大小
RUN命令执行后的文件变更可能增加较大空间
COPY/ADD添加的文件取决于文件大小
ENV/ARG环境变量元数据是(微层)可忽略
EXPOSE端口配置元数据是(微层)可忽略
CMD/ENTRYPOINT启动命令元数据是(微层)可忽略
VOLUME挂载点声明元数据无影响
WORKDIR工作目录设置元数据无影响

4.4.3 构建流程解析

# 用户执行构建命令
docker build -t myapp:v1 .

# Docker引擎处理流程
1. 解析Dockerfile → 生成抽象语法树(AST)
2. 按顺序执行每个指令
3. 每个指令生成一个镜像层(Layer)
4. 最终打包所有层为完整镜像

4.4.4 示例

ARG BUILDER=ubuntu

FROM ubuntu:20.04

ARG BUILDER

# dpkg-reconfigure tzdata
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt install -y tzdata \
    && rm -rf /var/lib/apt/lists/*

# Install all native packages that we need; everything else
# is installed into a user venv with pip.
RUN apt-get update && apt-get install -y \
        build-essential \
        locales \
        python3\
        python3-pip \
        libxml2-dev \
        libxml2-utils \
        libxslt1-dev \
        zlib1g-dev \
        net-tools \
        wget \
    && rm -rf /var/lib/apt/lists/*


RUN apt-get update && apt-get install -y gcc g++ cmake make autoconf automake libtool vim git sudo tree unzip \
    python3-lxml python3-jinja2 \
    libmount-dev pkg-config libsqlite3-dev libcgroup-dev libbz2-dev pkg-config libpcre3-dev libsqlite3-dev libcgroup-dev \
    && rm -rf /var/lib/apt/lists/*


RUN apt-get update && apt-get install -y python-dev python-lxml python-jinja2 \
    && rm -rf /var/lib/apt/lists/*

ARG PYCHARM_VERSION=2023.1.3
RUN wget -q https://download.jetbrains.com/python/pycharm-community-${PYCHARM_VERSION}.tar.gz -O /tmp/pycharm.tar.gz \
    && tar -xzf /tmp/pycharm.tar.gz -C /opt/ \
    && mv /opt/pycharm-* /opt/pycharm \
    && rm /tmp/pycharm.tar.gz \
    && chmod +x /opt/pycharm/bin/pycharm.sh

# create ${BUILDER} sudo users
RUN useradd --create-home --no-log-init --shell /bin/bash ${BUILDER} && \
	sudo echo ${BUILDER}:${BUILDER} | chpasswd && \
	sudo usermod -aG sudo ${BUILDER}

WORKDIR /home/${BUILDER}
USER ${BUILDER}

COPY ../ /home/${BUILDER}

如下是通过该文件生成的镜像及分层信息:

五、使用示例

可以用于CI&CD流程中统一编译环境,可参考我的另一篇文章:基于GitLab Runner的轻量级CI/CD实战指南

相关文章:

  • 串行通信 与 并行通信 对比
  • 3、实际常用命令【待补充】
  • rocketmq零拷贝技术底层实现
  • PgDog:一个PostgreSQL分布式集群中间件
  • 【前端常用函数】
  • 达梦改密码时不想看到明文
  • 下载vmware17
  • SQL-木马植入、报错注入及其他
  • 【算法day22】两数相除——给你两个整数,被除数 dividend 和除数 divisor。将两数相除,要求 不使用 乘法、除法和取余运算。
  • C++ 与 C 语言中的链表初始化方式对比(数据结构)
  • 【Linux】环境搭建 - 使用Mac电脑连接树莓派
  • [Leetcode]单链表回顾
  • Linux系统中-cp命令/mv命令/rename命令/rm命令
  • JavaScript基础-BOM 概述
  • Rust vs. Go: 性能测试(2025)
  • 多态的原理
  • 个人学习编程(3-26) leetcode刷题
  • 三个串口同时打开并指定数据包控制指令思想
  • 高效内存管理:x86-64架构中的分页机制
  • RK3568 驱动和设备匹配的几种方法
  • 我的科学观|梅彦昌:科技创新关键在于能否跑得快,而不是有没有钱
  • 京东一季度净利增长五成,营收增速创近三年新高,称外卖业务取得显著进展
  • 学者的“好运气”:读本尼迪克特·安德森《椰壳碗外的人生》
  • 寒武纪陈天石:公司的产品力获得了行业客户广泛认可,市场有望迎来新增量需求
  • 老镇老宅楼:破旧,没产证,要不要更新?
  • 在地球另一端的交流,架起2万公里间更多共赢的桥梁