详细解读Docker

发布于:2025-09-06 ⋅ 阅读:(15) ⋅ 点赞:(0)

1.概述

Docker是一种优秀的开源的容器化平台。用于部署、运行应用程序,它通过将应用及其依赖打包成轻量级、可移植的容器,实现高效一致的运行效果,简单来说,Docker就是一种轻量级的虚拟技术。

2.核心概念

2.1.容器(Container)

容器是独立运行的进程单元,包含应用程序代码、运行时环境、系统工具和依赖库。

1.每个容器相互隔离,共享主机操作系统内核

2.启动速度快,资源占用低

2.2.镜像(Image)

镜像是容器启动的静态模板,包含创建容器所需的分层文件系统

1.通过Dockerfile定义构建步骤(例如指定基础镜像,安装依赖)

2.支持版本管理和共享(如Docker hub共享仓库)

2.3.仓库(Registry)

用于仓储和分发镜像的平台(如Docker Hub、私有仓库)

3.核心功能

3.1.容器化技术

  • 应用隔离:将应用及其依赖打包到独立的容器中
  • 环境一致性:保证开发、测试、生产环境的一致性
  • 快速部署:秒级启动和停止容器

3.2.镜像管理

  • 分层存储:镜像采用分层结构,共享基础层,节省存储空间
  • 版本控制:支持镜像的版本管理和回滚
  • 镜像仓库:Docker Hub等平台提供镜像共享和分发

3.3.资源管理

  • 资源限制:可以限制容器的CPU、内存、磁盘IO等资源
  • 网络管理:提供多种网络模式(bridge、host等)
  • 存储管理:支持数据卷,绑定挂载等持久化存储方案

4.容器化&虚拟化

  • Infrastructure:基础设施,可以是个人电脑、主机服务器
  • Host Operating system:运行的主操作系统,例如windows、mac、Linux
  • Hypervisor:虚拟机管理器,可以虚拟出多个硬件,然后再安装操作系统,再部署应用
  • Guest OS:从操作系统,有Hypervisor虚拟出来
  • BINS/LIBS:二进制文件(Binaries)/库文件(Libraries),例如应用程序相关的编译后的可以执行的二进制文件,提供给应用程序调用的同样功能的库文件
  • Docker Daemon:Docker守护进程,代替了虚拟机的Hypervisor,docker守护进程本质是运行在主操作系统上的一个进程,直接与操作系统进行交互,这也是Docker 容器比较快的原因。

虽然虚拟机比较笨重但是也不是没有优势,可以讲服务器比作一个码头,拥有各种设备和场地(服务器硬件资源),服务器虚拟化类似在码头上有好多个仓库,仓库可以完全独立,每个仓库有各自的管理人员,Docker容器类似仓库里面的集装箱,每个集装箱各自独立,灵巧,方便迁移,但是隔离性比较差,多个集装箱统一由一个管理者进行管理,所有集装箱信息就暴露给一个管理人员,而仓库则可以有各自的用户,例如云服务提供者,通过虚拟出一个独立的虚拟机,有自己的用户,即租户管理自己的虚拟机。

# Docker 架构
+-------------------------------------------------------+
|                   Application A                       |
|                   Application B                       |
|                   Application C                       |
+-------------------------------------------------------+
|                 Docker Engine                         |
+-------------------------------------------------------+
|                 Host Operating System                 |
+-------------------------------------------------------+
|                 Physical Hardware                     |
+-------------------------------------------------------+

# 虚拟机架构
+-----------+ +-----------+ +-----------+
|   App A   | |   App B   | |   App C   |
+-----------+ +-----------+ +-----------+
| Guest OS  | | Guest OS  | | Guest OS  |
+-----------+ +-----------+ +-----------+
|                Hypervisor                            |
+-------------------------------------------------------+
|                Host Operating System                 |
+-------------------------------------------------------+
|                Physical Hardware                     |
+-------------------------------------------------------+

4.1.详细对比

特性 Docker (容器) 虚拟机 (VM)
启动速度 秒级启动 分钟级启动
性能 接近原生性能 有性能损耗(5-15%)
资源占用 轻量(MB级别) 重量(GB级别)
隔离性 进程级别隔离 完整的系统级别隔离
安全性 相对较低(共享内核) 较高(完全隔离)
镜像大小 通常为 MB 级别 通常为 GB 级别
部署密度 高(单机可运行数百容器) 低(单机通常10-20个VM)
兼容性 依赖宿主机内核 任何支持虚拟化的系统
迁移性 跨平台有限制 跨平台性好
系统开销 低(无额外OS开销) 高(每个VM需要完整OS)

4.1.技术实现对比

技术层面 Docker 虚拟机
虚拟化类型 操作系统级虚拟化 硬件级虚拟化
虚拟化技术 Namespaces, Cgroups Hypervisor (KVM, VMware, Hyper-V)
Guest OS 不需要,共享主机内核 每个VM需要完整的Guest OS
资源分配 动态分配,按需使用 预先分配固定资源
镜像构建 Dockerfile,分层构建 模板或快照,整体构建

5.Docker使用场景

使用Docker容器开发、测试、部署服务:因为Docker本身非常轻量化,所以本地开发人员可以构建、运行并分享Docker容器。容器可以在开发环境中创建,然后再提交到测试,最终进入生产环境。
创建隔离的运行环境:在很多企业应用中,同一服务的不同版本可能服务于不同的用户,那么使用Docker非常容易创建不同的生成环境来运行不同的服务。
搭建测试环境:由于Docker的轻量化,所以开发者很容易利用Docker在本地搭建测试环境,用来测试程序在不用系统下的兼容性;甚至搭建集群的部署测试。
构建多用户的平台即服务(PaaS)基础设施。
提供软件即服务(SaaS)应用程序。
高性能、超大规模的宿主机部署。

5.1.Docker组成

5.2.Docker 客户端 / 守护进程

Docker是C/S架构的程序:Docker客户端向Docker服务器端,也就是Docker的守护进程发出请求,守护进程处理完所有的请求工作并返回结果。Docker 客户端对服务器端的访问既可以是本地也可以通过远程来访问。

5.3.Docker Image 镜像

镜像是Docker容器的基石,容器基于镜像启动和运行。镜像就好比容器的源代码,保存了用于启动容器的各种条件。

Docker的镜像是一个层叠的只读文件系统,最低端是一个引导文件系统(即bootfs),第二层是root文件系统(即rootfs),它位于bootfs之上,可以是一种或多种操作系统,比如Ubuntu或者CentOS。在Docker中,root文件系统永远只能是只读状态,并且docker运用联合加载技术又会在root文件系统之上加载更多的只读文件系统,联合加载指的是一次加载多个文件系统,但是在外面看起来只能看到一个文件系统,联合加载会将各层文件系统叠加到一起,这样最终的文件系统会包含所有的底层文件和目录,docker将这样的文件系统称为镜像。

5.4.Docker Container 容器

容器是从镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。

当一个容器启动时,Docker会在该镜像的最顶层加载一个读写文件系统,也就是一个可写的文件层,我们在Docker运行的程序,就是在这个层中进行执行的,当Docker第一次启动一个容器时,初始的读写层是空的,当文件系统发生变化时,这些变化都会应用到这一层上,比如像修改一个文件,该文件首先会从读写层下面的只读层复制到该读写层,该文件的只读版本依然存在,但是已经被读写层中的该文件副本所隐藏,这就是Docker的一个重要技术:写时复制(copy on write)。每个只读镜像层都是只读的,永远不会变化,当创建一个新容器时,Docker会构建出一个镜像栈,

5.5.Docker Registry 仓库

Registry仓库是集中存放Docker镜像文件的场所。人们有时候会把Repository仓库和Registry仓库混为一谈,并不严格区分。实际上,Registry仓库上往往存放着多个Repository仓库,每个Repository仓库中又包含了多个Docker镜像,每个Docker镜像有不同的标签(tag)。

Registry仓库分为公开仓库(Public)和私有仓库(Private)两种形式。最大的公开仓库是 Docker Hub,存放了数量庞大的镜像供用户下载。 国内的公开仓库包括 Docker Pool 等,可以提供大陆用户更稳定快速的访问。

6.Dockerfile

Dockerfile 是用于构建 Docker 镜像的文本文件,包含一系列指令。每个指令在镜像中创建一个新层,最终形成可运行的容器环境。

6.1.Dockerfile 是什么

  •     文本文件: 纯文本文件,通常命名为 Dockerfile (首字母大写,无扩展名是惯例)。
  •     指令集合: 包含一系列按顺序执行的指令 (INSTRUCTION arguments)。
  •     构建蓝图: 描述了如何从基础组件(通常是基础镜像)一步步组装成一个新的、可运行的镜像。
  •     自动化构建: 执行 docker build 命令时,Docker 引擎读取 Dockerfile 并执行其中的指令,最终生成一个镜像。
  •     可重复性 & 版本控制: Dockerfile 本身可以被版本控制(如 Git),确保镜像构建过程透明、可审计、可重复。
     

6.2.Dockerfile 的核心组成部分

指令 目的 说明 示例 最佳实践
FROM 基础镜像 必须是第一个指令,指定构建新镜像所属的现有镜像 FROM ubuntu:22.04
FROM python:3.9-slim-buster
使用官方、轻量级、具体版本的基础镜像。
RUN 执行命令 在构建期间,在新镜像的文件系统层中执行命令 RUN apt-get update && apt-get install -y nginx
RUN pip install -r requirements.txt
合并命令减少层数;清理缓存;命令失败时应返回非零。
COPY 复制文件 从构建上下文复制文件或目录到镜像指定路径 COPY ./app /usr/src/app
COPY requirements.txt .
优先使用 COPY;明确复制目标目录。
ADD 复制与解压 类似COPY,单增加了功能;自动解压本地.tar文件,支持URL源 ADD ./app.tar.gz /opt/
ADD https://example.com/file /tmp/
除非需要解压或 URL 下载,否则优先用 COPY
CMD 容器默认命令 知道容器启动运行的默认命令及参数每个Dockerfile只能有一个CMD可被docker run覆盖 CMD ["nginx", "-g", "daemon off;"]
CMD ["python", "app.py"]
使用exec形式避免shell进程;仅指定主进程
ENTRYPOINT 容器入口点 定义容器启动时可执行程序,CMD作为参数传递给ENTRYPOINT,可被 docker run --entrypoint 覆盖 ENTRYPOINT ["python"]
CMD ["app.py"]
常与CMD配合使用;优先exec形式;用于固定入口
WORKDIR 设置工作目录 设置后续指令(RUN、CMD)的工作目录 WORKDIR /app
RUN pwd # 输出 /app
为清晰路径设置,替代 RUN cd ...;用绝对路径。
EXPOSE 申明端口 文档性说明容器在运行时监听哪些网络端口,不实际发布端口 EXPOSE 80
EXPOSE 8000/tcp
说明服务监听的端口;真实端口映射在 docker run 时指定。
ENV 设置环境变量 设置环境变量,可以在构建和运行期间使用 ENV PYTHONUNBUFFERED=1
ENV APP_HOME=/app
配置服务行为;使用变量简化 Dockerfile。
ARG 构建时变量 定义仅在构建过程中有效的变量,可用docker build --build -arg 传入 ARG VERSION=latest
RUN apt-get install package=$VERSION
用于参数化构建;不同默认值于不同阶段。
VOLUME 定义匿名卷 在镜像中创建一个挂载点,用于关联外部存储 VOLUME /var/lib/mysql 声明需要持久化或共享数据的目录。
USER 切换用户 设置后续指令(RUN、CMD)运行时的用户及用户组 USER www-data
USER 1000:1000
避免 root 用户运行应用;提高安全性。
LABEL 添加元数据 为镜像添加描述性元数据,如维护者信息,许可证等 LABEL maintainer="dev@example.com"
LABEL version="1.0"
记录镜像相关信息。
ONBUILD 延迟指令 将指令标记为延迟执行,当该镜像被作为另一个构建的基础时才触发。 ONBUILD COPY . /app/src 用于构建基础镜像。

7.最佳实践

  • 精简基础镜像: 使用 alpine、slim 等小型基础镜像减少攻击面和最终镜像大小。
  • 合并 RUN 指令: 将多个 RUN 命令(特别是 apt-get update && install && clean)合并为一个,减少层数并清理包管理器缓存。
  • 合理利用缓存: 将更改频率低的指令(如安装核心依赖)放前面,更改频率高的指令(如复制应用代码)放后面。
  • 使用 .dockerignore 文件: 明确忽略构建上下文中的不必要文件。
  • 优先使用 COPY 而非 ADD: 除非明确需要解压缩或从 URL 下载,否则用更简单直接的 COPY。
  • 指定版本标签: FROM 和依赖安装时使用明确版本,避免因 latest 标签更新导致的意外行为。
  • 减少镜像层数: 虽然层本身开销不大,但过多小层不利于管理,合并相关操作有益。
  • 设置非 root 用户: 在 RUN 用户级步骤后使用 USER,避免容器以 root 权限运行应用,提高安全性。
  • 使用多阶段构建: 分离构建环境和运行环境,大幅减小最终生产镜像体积(见示例)。
  • 明确暴露端口: 使用 EXPOSE 声明容器监听的端口。
  • 优先 exec 格式: 对 CMD 和 ENTRYPOINT 使用 JSON 数组格式 ["executable", "param1", "param2"] (exec 格式),避免不必要的 shell 进程并确保信号正确处理。
  • 添加元数据: 使用 LABEL 提供镜像信息。
  • 设置工作目录: 用 WORKDIR 替代 RUN cd ... && ...,使用绝对路径。
  • 考虑安全性: 定期更新基础镜像和依赖包修复漏洞;避免在 Dockerfile 或镜像中存储硬编码的机密信息,使用 ARG 或 secrets(在运行时通过环境变量或卷传入)。
  • 包含健康检查: 对关键服务使用 HEALTHCHECK 帮助编排系统管理容器状态。
     

网站公告

今日签到

点亮在社区的每一天
去签到