Docker核心揭秘:轻量级虚拟化的革命

一、Docker 简介

1.1 Docker 简介

Docker = 隔离性(namespace) + 可配额/可度量(Cgroup) + 移动性 (images)

  1. 隔离性(namespace) - 每个用户实例之间相互隔离, 互不影响。 硬件虚拟化方法给出的方法是VM, LXC给出的方法是container,更细一点是kernel namespace

  2. 可配额/可度量(Cgroup) - 每个用户实例可以按需提供其计算资源,所使用的资源可以被计量。硬件虚拟化方法因为虚拟了CPU, memory可以方便实现, LXC则主要是利用cgroups来控制资源

  3. 移动性 (images)- 用户的实例可以很方便地复制、移动和重建。硬件虚拟化方法提供snapshot和image来实现,docker(主要)利用AUFS实现

1.1.1 什么是 Docker?
  • Docker 是一个用于管理容器的引擎,也是为应用提供打包、部署的平台,并非单纯的虚拟化技术,它是一个开放的分布式应用平台,主要包含 Docker Engine(可移植、轻量级的运行时和打包工具)和 Docker Hub(用于共享应用和自动化工作流的云服务)。
1.1.2 Docker 的核心特点与优势

轻量级虚拟化、一致性、可移植性、高效资源利用、易于部署和扩展

  • 轻量级虚拟化:相比传统虚拟机更轻量高效,启动停止快速,例如启动 Docker 容器仅需几秒,而虚拟机可能需要几分钟,能节省系统资源。

  • 一致性:保障应用在开发、测试、生产等不同环境中运行表现一致,无论本地还是云端,运行环境相同,减少环境差异引发的问题。

  • 可移植性:可轻松在不同平台间迁移 Docker 容器,无需担忧依赖和环境配置差异,如本地开发的容器可无缝部署到云服务器。

  • 高效资源利用:多个 Docker 容器可共享主机操作系统内核,更高效地利用系统资源。

  • 易于部署和扩展:能快速部署新应用实例,并可根据需求轻松实现水平扩展。

1.1.3 Docker 的对于工作者优势
  • 对开发人员:Build once、Run anywhere(一次构建,随处运行)。

  • 对运维人员:Configure once、Run anything(一次配置,运行任何应用),容器技术大幅提升 IT 人员工作幸福感。

1.1.4 Docker 缺点及劣势
  1. 多个容器共用宿主机的内核,各应用之间的隔离不如虚拟机彻底

  2. 由于和宿主机之间的进程也是隔离的,需要进入容器查看和调试容器内进程等资源,变得比较困难和繁琐

  3. 如果容器内进程需要查看和调试,需要在每个容器内都需要安装相应的工具,这也造成存储空间的重复浪费

1.1.5 Docker 在企业中的应用场景
  • Docker 在企业中作为业务最小载体被广泛应用,企业借助 Docker 能更高效地部署应用且更节省资源,可应用于 SaaS(如网站、微店、云盘等)、PaaS(如 Redis、MySQL、Nginx、MongoDB 等)层面,构建基于 Docker 的云平台。

    • IaaS(Infrastructure as a Service):基础设施即服务。

    • PaaS(Platform as a Service):平台即服务。

    • SaaS(Software as a Service):软件运营服务。

1.1.6 Docker 与虚拟化的对比
1.1.6.1 底层原理与架构
维度 Docker(容器) 传统虚拟化(虚拟机)
隔离粒度 进程级隔离(共享宿主机内核) 完全隔离(每个虚拟机有独立内核、操作系统、硬件模拟)
核心依赖 依赖 Linux 内核的namespace (命名空间,实现资源隔离)和cgroups(控制组,限制资源) 依赖 Hypervisor(虚拟化层,如 KVM、VMware ESXi)模拟硬件资源
操作系统 容器内通常是精简的操作系统(如 Alpine Linux),与宿主机共享内核 每个虚拟机运行完整的操作系统(如 Windows、Linux),内核独立于宿主机
启动依赖 无需启动完整操作系统,直接运行进程 必须先启动虚拟机的操作系统,再运行应用
1.1.6.2 关键特性对比
特性 Docker(容器) 传统虚拟化(虚拟机)
启动速度 极快(秒级甚至毫秒级),直接启动进程 较慢(分钟级),需启动完整操作系统
资源占用 轻量,共享宿主机内核和资源,仅占用应用自身所需资源 重量级,每个虚拟机需分配独立的 CPU、内存、磁盘等资源,资源利用率低
隔离性 隔离性较弱(共享内核,内核级漏洞可能影响所有容器) 隔离性强(完全独立的内核和硬件模拟,一个虚拟机故障不影响其他)
移植性 极高,基于镜像打包应用和依赖,可在任何支持 Docker 的环境中运行("一次构建,到处运行") 较差,虚拟机镜像与硬件和 Hypervisor 绑定,跨平台迁移复杂(如 VMware 到 KVM)
镜像大小 很小(通常 MB 级,如 Alpine 镜像仅几 MB),基于分层存储(复用基础镜像层) 很大(通常 GB 级),包含完整操作系统
适用场景 微服务、持续集成 / 部署(CI/CD)、应用隔离、快速扩展 运行不同操作系统(如 Windows 和 Linux 并存)、强隔离需求(如多租户场景)、旧系统迁移

3. 典型使用场景

1.2 部署 Docker

1.2.1 docker 组成
  • 其中,runc是docker最底层的核心引擎,是轻量级的通用运行时容器,遵守OCI规范,是实现OCI接口最低级别的组件,它与内核交互创建并运行容器
  1. Docker 主机(Host): 一个物理机或虚拟机,用于运行Docker服务进程和容器,也称为宿主机,node节点

  2. Docker 服务端(Server): Docker守护进程,运行docker容器

  3. Docker 客户端(Client): 客户端使用 docker 命令或其他工具调用docker API

  4. Docker 镜像(Images): 镜像可以理解为创建实例使用的模板,本质上就是一些程序文件的集合

  5. Docker 仓库(Registry): 保存镜像的仓库

1.2.2 容器工作方法
  • 涉及 Client(客户端)、DOCKER_HOST(Docker 主机,包含 Docker daemon、Containers、Images)、Registry(仓库),主要操作有 docker build(构建镜像)、docker pull(拉取镜像)、docker run(运行容器,如运行 NGINX)
1.2.3 部署第一个容器
bash 复制代码
 # 进入yum源配置目录配置docker镜像
 [root@docker01 ~] vim /etc/yum.repos.d/docker.repo
 [docker]
 name=docker-ce
 baseurl=https://mirrors.aliyun.com/docker-ce/linux/rhel/9/x86_64/stable
 gpgcheck=0
bash 复制代码
 # 添加镜像加速器
 [root@docker01 ~] cat /etc/docker/daemon.json 
 {
     "registry-mirrors":["https://docker.m.daocloud.io"]
 }
  • 安装 docker-ce 并启动服务

    bash 复制代码
     # 安装docker
     [root@docker01 ~] yum install -y docker-ce 
     # 编辑docker启动文件,设定使用iptables的网络设定方式(默认使用nftables)
     vim /usr/lib/systemd/system/docker.service
     # 修改ExecStart行如下
     ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true
     # 设置docker开机自启并立即启动
     [root@docker01 ~] systemctl enable --now docker
    bash 复制代码
     # 查看 docker 信息
     [root@docker01 ~]# docker info
     Client: Docker Engine - Community  # 客户端类型:Docker 社区版
      Version:    28.5.1                # 客户端版本号
      Context:    default               # 当前使用的上下文(默认上下文,用于管理Docker环境连接)
      Debug Mode: false                 # 未启用调试模式
      Plugins:                          # 客户端安装的插件
       buildx: Docker Buildx (Docker Inc.)  # Docker Buildx插件(官方提供,增强镜像构建功能)
         Version:  v0.29.1                 # 插件版本
         Path:     /usr/libexec/docker/cli-plugins/docker-buildx  # 插件安装路径
       compose: Docker Compose (Docker Inc.)  # Docker Compose插件(官方提供,管理多容器应用)
         Version:  v2.40.0                   # 插件版本
         Path:     /usr/libexec/docker/cli-plugins/docker-compose  # 插件安装路径
      Server:
      Containers: 0                     # 总容器数:0(包括所有状态)
       Running: 0                       # 运行中容器数:0
       Paused: 0                        # 暂停状态容器数:0
       Stopped: 0                       # 已停止容器数:0
      Images: 0                         # 本地存储的镜像数:0
      Server Version: 28.5.1            # 服务端(Docker引擎)版本号(与客户端一致)
      Storage Driver: overlay2          # 存储驱动:overlay2(Docker推荐的高效存储驱动)
       Backing Filesystem: xfs          # 底层文件系统:xfs(宿主机的文件系统类型)
       Supports d_type: true            # 支持d_type(文件类型识别,overlay2依赖此特性)
       Using metacopy: false            # 未启用metacopy模式(关闭时性能更优,依赖底层文件系统)
       Native Overlay Diff: true        # 使用原生overlay差异计算(高效存储容器与镜像的差异)
       userxattr: false                 # 未启用用户扩展属性(xattr,用于高级权限控制)
      Logging Driver: json-file         # 默认日志驱动:json-file(容器日志以JSON格式存于宿主机文件)
      Cgroup Driver: systemd            # cgroup驱动:systemd(用于管理容器的CPU/内存等资源限制)
      Cgroup Version: 2                 # cgroup版本:v2(Linux内核资源管理机制,比v1更统一)
      Plugins:                          # 服务端支持的插件
       Volume: local                    # 卷插件:local(本地卷,容器数据存储在宿主机目录)
       Network: bridge host ipvlan macvlan null overlay  # 网络插件
         # bridge:默认桥接网络(容器通过虚拟网桥通信)
         # host:容器使用宿主机网络栈
         # ipvlan/macvlan:为容器分配独立IP/MAC,模拟物理设备
         # null:无网络(容器无法联网)
         # overlay:跨主机网络(用于Swarm集群)
       Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog  # 日志驱动
         # 支持对接AWS/GCP日志服务、fluentd、journald等(默认使用json-file)
      CDI spec directories:             # CDI(容器设备接口)配置目录(用于暴露宿主机设备给容器)
       /etc/cdi
       /var/run/cdi
      Swarm: inactive                   # Docker Swarm(容器编排)状态:未激活(未启用集群模式)
      Runtimes: runc io.containerd.runc.v2  # 支持的容器运行时(负责创建和运行容器进程)
         # runc:OCI标准运行时(默认)
         # io.containerd.runc.v2:containerd集成的runc运行时
      Default Runtime: runc             # 默认运行时:runc
      Init Binary: docker-init          # 容器初始化程序:docker-init(处理容器内进程管理,如回收僵尸进程)
      containerd version: b98a3aace656320842a23f4a392a33f46af97866  # containerd(容器运行时管理器)版本
      runc version: v1.3.0-0-g4ca628d1  # runc运行时版本
      init version: de40ad0             # docker-init工具版本
      Security Options:                 # 启用的安全选项
       seccomp                          # seccomp(安全计算模式):限制容器可调用的系统调用
        Profile: builtin                # 使用Docker内置的seccomp安全策略
       cgroupns                         # cgroup命名空间:隔离容器的cgroup视图,增强安全性
      Kernel Version: 5.14.0-362.8.1.el9_3.x86_64  # 宿主机内核版本(适用于RHEL 9.3)
      Operating System: Red Hat Enterprise Linux 9.3 (Plow)  # 宿主机操作系统:RHEL 9.3(代号Plow)
      OSType: linux                     # 操作系统类型:Linux(Docker原生支持)
      Architecture: x86_64              # CPU架构:x86_64(64位Intel/AMD处理器)
      CPUs: 4                           # 宿主机CPU核心数:4
      Total Memory: 1.879GiB            # 宿主机总内存:约1.9GB
      Name: docker01                    # 宿主机/节点名称:docker01
      ID: 6f00beda-f59d-4762-86c9-2c3637b09409  # Docker服务端唯一标识符(用于节点身份)
      Docker Root Dir: /var/lib/docker  # Docker根目录(存储镜像、容器数据、配置等的默认路径)
      Debug Mode: false                 # 服务端未启用调试模式
      Experimental: false               # 未启用实验性特性(实验特性可能不稳定)
      Insecure Registries:              # 非安全镜像仓库(不验证TLS证书)
       ::1/128                          # 本地IPv6地址
       127.0.0.0/8                      # 本地IPv4地址段(通常用于测试)
      Registry Mirrors:                 # 镜像仓库加速器(加速拉取Docker Hub镜像)
       https://docker.m.daocloud.io/    # DaoCloud提供的加速器地址
      Live Restore Enabled: false       # 未启用Live Restore(Docker服务重启时,容器不会继续运行)
  • 激活内核网络选项注意:我是使用的是9.3版本Redhat,不需要激活 | 如果为7版本则需要激活内核

    bash 复制代码
     # 添加内核模块配置
     echo br_netfilter > /etc/modules-load.d/docker_mod.conf
     # 加载模块
     modprobe br_netfilter
     # 编辑内核参数配置文件
     vim /etc/sysctl.d/docker.conf
     # 添加以下内核参数
     net.bridge.bridge-nf-call-iptables = 1
     net.bridge.bridge-nf-call-ip6tables = 1
     net.ipv4.ip_forward = 1
     # 应用内核参数
     sysctl --system
     # 重启docker服务
     systemctl restart docker

二、Docker 的基本操作

2.1 Docker 镜像管理

2.1.1 搜索镜像
bash 复制代码
 [root@docker01 ~] docker search nginx
  搜索镜像会搜索很慢或拉取失败(为正常现象,可以忽略,进行直接拉去)
  输出结果包含 NAME(镜像名称)
  DESCRIPTION(镜像说明)
  STARS(点赞数量)
  OFFICIAL(是否为官方镜像)
2.1.2 拉取镜像
  • 拉取镜像若不指定版本则拉取后版本均为latest
bash 复制代码
 # 从镜像仓库拉取busybox镜像
 [root@docker01 ~] docker pull busybox
 Using default tag: latest
 latest: Pulling from library/busybox
 80bfbb8a41a2: Pull complete 
 Digest: sha256:2f590fc602ce325cbff2ccfc39499014d039546dc400ef8bbf5c6ffb860632e7
 Status: Downloaded newer image for busybox:latest
 docker.io/library/busybox:latest
 # 拉取指定版本(1.23)的nginx镜像
 [root@docker01 ~]# docker pull nginx:1.23
 1.23: Pulling from library/nginx
 f03b40093957: Pull complete 
 0972072e0e8a: Pull complete 
 a85095acb896: Pull complete 
 d24b987aa74e: Pull complete 
 6c1a86118ade: Pull complete 
 9989f7b33228: Pull complete 
 Digest: sha256:f5747a42e3adcb3168049d63278d7251d91185bb5111d2563d58729a5c9179b0
 Status: Downloaded newer image for nginx:1.23
 docker.io/library/nginx:1.23
 # 查看本地镜像
 [root@docker01 ~] docker images
 REPOSITORY(仓库名)   TAG(标签 / 版本)       IMAGE ID(镜像 ID)       CREATED(创建时间)         SIZE(镜像大小)
 busybox                  latest                0ed463b26dae            12 months ago           4.43MB
 nginx                     1.23                 a7be6198544f             2 years ago             142MB
2.1.3 查看镜像信息
复制代码
 
bash 复制代码
# 可查看镜像的详细配置信息
 [root@docker01 ~] docker image inspect nginx:1.23
 [
     {
         "Id": "sha256:a7be6198544f09a75b26e6376459b47c5b9972e7aa742af9f356b540fe852cd4",
         "RepoTags": [
             "nginx:1.23"
         ],
         "RepoDigests": [
             "nginx@sha256:f5747a42e3adcb3168049d63278d7251d91185bb5111d2563d58729a5c9179b0"
         ],
         "Parent": "",
         "Comment": "",
         "Created": "2023-05-23T08:51:38.011802405Z",
         "DockerVersion": "20.10.23",
         "Author": "",
         "Architecture": "amd64",
         "Os": "linux",
         "Size": 142145851,
         "GraphDriver": {
             "Data": {
                 "LowerDir": "/var/lib/docker/overlay2/d10331966ed5f307a7164aed6d131bf6a6015663b9a5a5a81acad3b550692557/diff:/var/lib/docker/overlay2/3b33f62f9d962dee76ae3beed2b3a1026b3638992222ed4043296eed5cd13bc4/diff:/var/lib/docker/overlay2/a463d970450193c66b9b639581276b69960dbd60a01abd58e3e4703fdada2e87/diff:/var/lib/docker/overlay2/076312549c7578157eb2491d51953f3f9cf4b844d43b1b336771a3e3046922f7/diff:/var/lib/docker/overlay2/2b347d40ba6a2ea28fad68574ff38a7a18014ea6ade6972a0e393d9f8337e775/diff",
                 "MergedDir": "/var/lib/docker/overlay2/856acfd6d4c9ca8cd2fa945b085c317cd031dca76100a52292f7a994ebbadea5/merged",
                 "UpperDir": "/var/lib/docker/overlay2/856acfd6d4c9ca8cd2fa945b085c317cd031dca76100a52292f7a994ebbadea5/diff",
                 "WorkDir": "/var/lib/docker/overlay2/856acfd6d4c9ca8cd2fa945b085c317cd031dca76100a52292f7a994ebbadea5/work"
             },
             "Name": "overlay2"
         },
         "RootFS": {
             "Type": "layers",
             "Layers": [
                 "sha256:8cbe4b54fa88d8fc0198ea0cc3a5432aea41573e6a0ee26eca8c79f9fbfa40e3",
                 "sha256:5dd6bfd241b4f4d0bb0a784cd7cefe00829edce2fccb2fcad71244df6344abff",
                 "sha256:043198f57be0cb6dd81abe9dd01531faa8dd2879239dc3b798870c0604e1bb3c",
                 "sha256:2731b5cfb6163ee5f1fe6126edb946ef11660de5a949404cc76207bf8a9c0e6e",
                 "sha256:6791458b394218a2c05b055f952309afa42ec238b74d5165cf1e2ebe9ffe6a33",
                 "sha256:4d33db9fdf22934a1c6007dcfbf84184739d590324c998520553d7559a172cfb"
             ]
         },
         "Metadata": {
             "LastTagTime": "0001-01-01T00:00:00Z"
         },
         "Config": {
             "Cmd": [
                 "nginx",
                 "-g",
                 "daemon off;"
             ],
             "Entrypoint": [
                 "/docker-entrypoint.sh"
             ],
             "Env": [
                 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",           # 环境变量
                 "NGINX_VERSION=1.23.4",
                 "NJS_VERSION=0.7.11",
                 "PKG_RELEASE=1~bullseye"
             ],
             "ExposedPorts": {
                 "80/tcp": {}
             },
             "Labels": {
                 "maintainer": "NGINX Docker Maintainers \u003cdocker-maint@nginx.com\u003e"
             },
             "OnBuild": null,
             "StopSignal": "SIGQUIT",
             "User": "",
             "Volumes": null,
             "WorkingDir": ""
         }
     }
 ]
2.1.4 导出镜像

-o 用于指定导出镜像的位置,可同时导出多个镜像到一个文件,指定.tar.gz 格式可导出并压缩

bash 复制代码
# 保存nginx:latest镜像到指定文件
 [root@docker01 ~] docker image save nginx:latest -o nginx-latest.tar.gz
 # 同时保存多个镜像到一个文件
 [root@docker01 ~] docker image save nginx:latest nginx:1.26-alpine -o nginx.tag.gz
 # 保存所有镜像到一个压缩文件
 [root@docker01 ~] docker save `docker images | awk 'NR>1{print $1":"$2}'` -o images.tar.gz
2.1.5 删除镜像
bash 复制代码
 # 删除指定镜像
 [root@docker01 ~] docker rmi busybox:latest
 # 删除所有镜像
 [root@docker01 ~] docker rmi `docker images | awk 'NR>1{print $1":"$2}'`

2.2 容器的常用操作

2.2.1 启动容器
bash 复制代码
# 后台运行nginx容器,端口映射(主机80端口映射到容器80端口)
 [root@docker01 ~] docker run -d --name nginx -p 80:80 nginx:latest
 7ecb34aa2e5812adbccb1b01fad77e7185536eba402ea2d133d9fbf16f4599ef
 [root@docker01 ~] docker ps 
 CONTAINER ID   IMAGE          COMMAND                   CREATED          STATUS          PORTS                                 NAMES
 7ecb34aa2e58   nginx:latest   "/docker-entrypoint...."   36 seconds ago   Up 36 seconds   0.0.0.0:80->80/tcp, [::]:80->80/tcp   nginx
 # 删除该运行容器
 [root@docker01 ~] docker rm -f nginx
 nginx
 # 交互式运行busybox容器,打开终端
 [root@docker01 ~] docker run -it --name busybox busybox:latest
 - 若是执行 `<ctrl>+<pq>`,即可 docker attach busybox:latest 可重新进入
 # 删除该运行容器
 [root@docker01 ~] docker rm -f busybox
 =======================交互式容器操作===================
 `<ctrl>+<d>`退出并停止容器
 `<ctrl>+<pq>`退出但不停止容器。
 =======================参数说明========================
  -d:后台运行
  -i:交互式运行
  -t:打开一个终端
  -it: 当打开一个交互式的终端
  --name:指定容器名称
  -p:端口映射,格式为 "主机端口:容器端口"
  --rm:容器停止后自动删除容器
  --network:指定容器使用的网络
  • 在容器中执行命令:docker exec -it test ifconfig
2.2.2 查看容器运行信息
  • **docker ps:**查看当前运行的容器

  • **docker ps -a:**查看所有容器(包括已停止的)

  • **docker inspect busybox:**查看容器运行的详细信息

2.2.3 停止和启动容器
  • **docker stop busybox:**停止容器

  • **docker kill busybox:**杀死容器(可使用信号)

  • **docker start busybox:**启动已停止的容器

  • 说明 :容器内的第一个进程必须持续运行,否则容器会处于退出状态。

2.2.4 删除容器
  • **docker rm centos7:**删除已停止的容器

  • **docker rm -f busybox:**强制删除运行中的容器

  • **docker container prune -f:**删除所有已停止的容器

2.2.5 容器内容提交
  • 默认情况:容器删除后,内部所有操作(包括文件)会被清理,若需永久保存,需提交容器生成新镜像。

    bash 复制代码
     # 运行test容器并在其中创建文件
     [root@docker01 ~] docker run -it --name test busybox
     touch testfile
     # 退出容器后删除,再运行新容器,文件不存在
     [root@docker01 ~] docker rm test
     [root@docker01 ~] docker run -it --name test busybox
     # 提交容器生成新镜像
     [root@docker01 ~] docker commit -m "add testfile" test busybox:v1
     # 查看新生成的镜像
     [root@docker01 ~] docker images
     # 查看镜像历史记录
     [root@docker01 ~] docker image history busybox:v1
2.2.6 系统与容器间文件传输
  • **docker cp test2:/leefile /mnt:**将容器 test 中的 testfile 文件复制到主机 /mnt 目录

  • **docker cp /etc/fstab test2:/fstab:**将主机 /etc/fstab 文件复制到容器 test 中

2.2.7 查询容器内部日志
  • docker logs web,可查看 web 容器的日志输出,如 nginx 容器的启动配置、请求记录等信息。
相关推荐
ZLRRLZ3 小时前
【Docker】Docker Image(镜像)
运维·docker·容器
小熊h3 小时前
Kubernetes(K8s) —— 部署(保姆级教程)
云原生·容器·kubernetes
焱焱枫4 小时前
Linux疑难杂症诊断利器:深入解析 fuser 命令
linux·运维·服务器
深思慎考4 小时前
RabbitMQ 入门:基于 AMQP-CPP 的 C++ 实践指南与二次封装
开发语言·c++·分布式·rabbitmq·api
Andya_net4 小时前
Java | 基于redis实现分布式批量设置各个数据中心的服务器配置方案设计和代码实践
java·服务器·分布式
catchadmin4 小时前
PHP8.5 的新 URI 扩展
开发语言·后端·php
博语小屋4 小时前
Linux进程信号(壹)_产生信号
linux·运维·服务器
元亓亓亓4 小时前
考研408--计算机网络--day1-概念&组成功能&三种交换技术&分类
服务器·计算机网络·考研
似水流年 光阴已逝4 小时前
从Excel姓名匹配案例学Python:由点及面的系统化学习指南
开发语言·python·excel