Docker学习笔记(一)

介绍

背景

        Docker 最初是 dotClound 公司创始人 Solomon Hykes 在法国时发起的一个公司内部项目,它是基于 dotClound公司多年云服务技术的一次革新,并于 2013 年 3 月以 Apache 2.0 授权协议开源,主要项目代码在 GitHub 进行维护。Docker 项目后来还加入了 Linux 基金会,并成立推动 开放容器联盟(" OCI ")。

        Docker 使用 Google 公司推出的 Go 语言进行开发实现,基于 Linux 内核的 cgroup 、namespace 及 OverlayFS 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。

        由于 Docker 隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。

概念        

        Docker 是一个开源的应用容器引擎,基于 Go 语言并遵从 Apache2.0 协议开源。

        Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

        Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。它是目前最流行的 Linux 容器解决方案。

        容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

        Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker,就不用担心环境问题。

        总体来说,Docker 的接口相当简单,用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。

用途

        提供一次性的环境

        比如,本地测试他人的软件、持续集成的时候提供单元测试和构建的环境。

        提供弹性的云服务

        因为 Docker 容器可以随开随关,很适合动态扩容和缩容。

        组建微服务架构

        通过多个容器,一台机器可以跑多个服务,因此在本机就可以模拟出微服务架构。

工作模式

        Docker 技术使用 Linux 内核和内核功能(例如 Cgroups 和 namespaces)来分隔进程,以便各进程相互独立运行。这种独立性正是采用容器的目的所在;它可以独立运行多种进程、多个应用程序,更加充分地发挥基础设施的作用,同时保持各个独立系统的安全性。

        容器工具(包括 Docker)可提供基于镜像的部署模式。这使得它能够轻松跨多种环境,与其依赖程序共享应用或服务组。Docker 还可在这一容器环境中自动部署应用程序(或者合并多种流程,以构建单个应用程序)。

        此外,由于这些工具基于 Linux 容器构建,使得 Docker 既易于使用,又别具一格 —— 它可为用户提供前所未有的高度应用程访问权限、快速部署以及版本控制和分发能力。

架构

核心部分

Docker Image(镜像)
概念

        Docker Image 是一个只读的模板,包含了应用程序运行所需的所有文件、依赖项和配置。

        镜像是构建容器的基础,可以看作是容器的快照。通过使用 Docker file 定义镜像的构建过程,开发者可以自定义镜像,使其满足特定应用的需求。镜像的分层结构和 Union FS (联合文件系统)使得镜像的创建和传播变得高效而节省空间。

        通过镜像启动一个容器,一个镜像就是一个可执行的包,其中包括运行应用程序所需要的所有内容:包含代码,运行时间,库,环境变量和配置文件等。

        Docker Image 是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。

        我们都知道,操作系统分为内核和用户空间。对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而 Docker Image,就相当于是一个 root  文件系统。

特点

        轻量级和可移植性

        Docker Image 是轻量级的,它只包含了应用程序运行所需的文件和依赖项,相对于传统虚拟机镜像来说更小巧。由于镜像是独立的、可移植的文件,因此可以轻松地在不同的环境中进行部署和运行,保证了应用程序在不同平台上的一致性。

        分层结构

        Docker Image 采用分层结构的设计。一个 Docker 镜像由多个只读层组成,每个层都包含了文件系统的一部分。这种分层的结构使得镜像可以复用共同的部分,减少了镜像之间的冗余。当多个镜像共享同一层时,它们只需要存储该层的一个副本,而不需要多份拷贝。

        联合文件系统(Union FS)

        Docker Image 镜像使用联合文件系统(Union FS)来实现镜像的分层结构。联合文件系统允许多个文件系统挂载为单一文件系统,使得不同层的文件系统在容器启动时可以合并在一起。这样,镜像的修改操作可以通过添加一个新的可写层来实现,而不是在原有的镜像层上直接修改,保持了镜像的不可变性。

        因为镜像包含操作系统完整的 root 文件系统,其体积往往是庞大的,因此在 Docker 设计时,就充分利用 Union FS 的技术,将其设计为分层存储的架构。所以严格来说,镜像并非是像一个 ISO 那样的打包文件,镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成。

        镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。

        分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。

        镜像版本控制

        Docker Image 支持版本控制,每个镜像都有一个唯一的标签或 ID,用于标识镜像的不同版本。这使得开发者可以轻松地管理和追踪镜像的更新和变化。通过指定特定的标签或 ID,可以确保使用特定版本的镜像来构建容器。

Docker Container(容器)
概念

        Docker Container 是 Docker Image 的运行实例。

        容器是隔离的、轻量级的运行环境,每个容器都运行在自己的进程空间中,互不干扰。容器在创建时,会使用镜像的文件系统作为基础层,并在其上添加一个可写层,用于保存运行时状态和数据。容器的隔离性和轻量性使得应用程序可以在不同的环境中以相同的方式运行。

        容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。因此容器可以拥有自己的 root 文件系统、网络配置、进程空间,甚至自己的用户 ID 空间。

        容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。也因为这种隔离的特性,很多人初学 Docker 时常常会混淆容器和虚拟机。

        前面讲过镜像使用的是分层存储,容器也是如此。每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为容器存储层。

        容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。

        按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。

        数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行之后,数据却不会丢失。

Image 和 Container 的关系

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

Docker面向对象
镜像
容器对象

Docker Engine(引擎)

        Docker 引擎是 Docker 的核心组件,负责管理和运行容器。

核心组件

        它主要包括 Docker 守护进程(dockerd)、REST API、命令行接口(CLI)。

        Docker 守护进程(dockerd)

        作为后台服务运行,负责管理容器的创建、运行和停止等任务。

        Docker 守护进程是 Docker 引擎的后台服务,负责持续运行并处理与容器相关的请求。它监听来自 Docker 客户端或其他组件的命令,并根据这些请求执行相应的操作。Docker 守护进程管理着整个容器的生命周期,包括创建、启动、停止和销毁容器。

        REST API

        提供了与 Docker 引擎进行交互的接口,允许用户通过 API 请求来管理容器和镜像。

        Docker 引擎提供了一个 REST API,它允许用户和其他应用程序通过 HTTP 请求来与 Docker 引擎进行交互。这个 API 提供了对容器和镜像的管理功能,可以通过编程方式与 Docker 引擎进行通信。

        Docker 客户端通过调用这些 API 来实现用户的命令行操作,比如创建容器、上传镜像等。

        命令行接口(CLI)

        通过命令行工具(docker)与 Docker 引擎进行交互,方便用户操作容器和镜像。

        Docker 引擎的命令行接口(CLI)是用户与 Docker 守护进程交互的主要方式。通过在终端中输入各种 Docker 命令,用户可以创建、启动、停止、删除容器,以及构建、上传、下载镜像等。CLI 工具将用户的命令请求转发给 Docker 守护进程,并返回相应的结果。

任务

        Docker 引擎负责容器和镜像的管理,主要任务如下。

任务详细内容
创建镜像根据 Dockerfile 和构建上下文创建 Docker 镜像
存储镜像将创建的镜像保存在本地或上传至 Docker Hub 等远程仓库
创建容器基于指定的镜像创建容器,并分配唯一的容器 ID
容器生命周期管理启动、停止、重启、销毁容器,并监控容器的状态变化
网络管理配置容器网络,实现容器间的通信和与外部网络的连接

特性

        Docker 引擎主要的特性就是其安全性与隔离性。

        Docker 引擎实现了一系列安全措施,确保容器之间和主机之间的隔离性。它使用 Linux 命名空间(namespace)和控制组(cgroup)等特性,以及基于用户的权限管理,确保容器运行在隔离的环境中,不会对其他容器或主机造成影响。

Docker Client(客户端)

        Docker Client 是用户与 Docker Engine 交互的主要方式。用户可以通过命令行工具(docker)或者 Docker 的图形用户界面(GUI)来与 Docker Engine 进行通信,执行创建、启动、停止、删除容器等操作。Docker 客户端会将用户的命令请求发送给 Docker 引擎的 REST API,由引擎来处理具体的操作。

        Docker 是一个客户端-服务器(C/S)架构程序。Docker C只需要向 Docker 服务器或者守护进程发出请求,服务器或者守护进程将完成所有工作并返回结果。

        Docker 提供了一个命令行工具 Docker 以及一整套 REST ful API。你可以在同一台宿主机上运行 Docker 守护进程和客户端,也可以从本地的 Docker 客户端连接到运行在另一台宿主机上的远程 Docker 守护进程。

Container Runtime(容器进行时)

        Container Runtime 是一个负责运行容器的软件组件,它实际上是 Docker Engine 的一部分。容器运行时负责创建容器的运行环境,包括启动容器的进程、设置网络和文件系统等。常见的容器运行时实现包括 runc、containerd 等。

        Docker 架构的这些组件共同协作,实现了容器化应用的生命周期管理。开发者可以通过定义镜像和容器来构建、交付和运行应用程序,而 Docker Engine 则负责管理这些容器和镜像的生命周期。了解 Docker 架构的工作原理,有助于更好地理解 Docker 技术的运作方式和优势。接下来,我们将深入理解 Docker Engine 及其关键角色。

Docker Registry(注册服务器)

        镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Register 就是这样的服务。

        Registry 是仓库注册服务器,实际上参考注册服务器中存放着多个仓库,每个仓库中又包含了多个镜像,而每个镜像有不同的标签(tag)。

        也就是说,一个 Docker Register 中可以包含多个 Repository(仓库),每个仓库可以包含多个 Tag(标签),每个 Tag 对应一个 Image(镜像)。

        Repository(仓库)分为两种,公有仓库和私有仓库,最大的公开仓库是docker Hub,存放了数量庞大的镜像供用户下载,国内的有docker pool。这里仓库的概念与 Git 类似,Registry 可以理解为 github 这样的托管服务。

        通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过" <仓库名>:<标签名> "的格式来指定具体是这个软件是哪个版本的镜像。如果不给出相应标签,将以 latest 作为默认标签。

Docker和传统虚拟机的区别

        Docker 是一种容器化技术,而传统虚拟化技术通常指的是基于虚拟机(Virtual Machine,即VM)的虚拟化。虽然 Docker 和传统虚拟化技术都可以实现应用程序的隔离和部署,但它们在架构和性能方面存在显著的差异。

        下面是两者在不同方面的比较。

架构

传统虚拟机Docker
在传统虚拟化中,Hypervisor 负责创建和管理虚拟机,每个虚拟机运行一个完整的操作系统,包括内核和用户空间Docker 使用容器来实现应用程序的隔离,容器共享主机操作系统的内核,避免了虚拟机的重复内核和操作系统资源
每个虚拟机都需要独立的操作系统和内核,因此虚拟机之间存在较大的资源开销容器内只包含应用程序和其依赖项,因此容器更加轻量级且资源开销较小

性能

传统虚拟机Docker
由于每个虚拟机都运行一个完整的操作系统,虚拟化的性能开销较大,资源利用率较低Docker 容器共享主机操作系统的内核,因此性能开销较小,资源利用率较高
虚拟机启动时间较长,通常需要几秒钟或更多时间来启动容器的启动时间通常在毫秒级别,几乎可以瞬间启动

 综合

特性容器(如 Docker)虚拟机
启动秒级分钟级
硬盘使用一般为MB一般为GB
性能接近原生弱于
系统支持量单机支持上千个容器一般几十个

优缺点

优点

        更高效地利用资源

        由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销, Docker 对系统资源的利用率更高。无论是应用执行速度、内存损耗或者文件存储速度,都要比传统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的主机,往往可以运行更多数量的应用。

        更快速地启动时间

        传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间,这一点大大节约了开发、测试、部署的时间。

        快速地提供一致的测试开发所需环境

        Docker 允许开发人员使用您提供的应用程序或服务的本地容器在标准化环境中工作,从而简化了开发的生命周期。

        开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环境不一致,导致有些 bug 并未在开发过程中被发现。而 Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性。

        使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过 Docker File 来进行镜像构建,并结合持续集成系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合持续部署系统进行自动部署。

        而且使用 Docker File 使镜像构建透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像。

        响应式部署和扩展

        Docker 是基于容器的平台,允许高度可移植的工作负载。Docker 容器可以在开发人员的本机上,数据中心的物理或虚拟机上,云服务上或混合环境中运行。

        Docker 的可移植性和轻量级的特性,还可以使操作人员轻松地完成动态管理的工作负担,并根据业务需求指示,实时扩展或拆除应用程序和服务。

        在同一硬件上运行更多工作负载

        Docker 轻巧快速。它为基于虚拟机管理程序的虚拟机提供了可行、经济、高效的替代方案,因此操作人员可以利用更多的计算能力来实现业务目标。Docker 非常适合于高密度环境以及中小型部署,而操作人员可以用更少的资源做更多的事情。

        更轻松地迁移

        由于 Docker 确保了执行环境的一致性,使得应用的迁移更加容易。Docker 可以在很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运行结果是一致的。因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。

        更轻松地维护和扩展

        Docker 使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。此外,Docker 团队同各个开源项目团队一起维护了一大批高质量的官方镜像,既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。

缺点

        资源消耗较大

        Docker Image 是一个完整的文件系统,包含了运行应用所需的所有依赖,因此镜像的体积较大,可能会占用较多的磁盘空间。

        每个镜像的运行都需要一个额外的 Docker 运行时环境,这会占用一定的内存和CPU资源。如果服务器资源有限,可能会导致性能压力。

        难以维护和管理

        当应用的规模逐渐增大,涉及到多个镜像的组合和协作时,Docker 容器的维护和管理可能变得复杂。需要考虑容器之间的依赖关系、服务发现和负载均衡等问题,以及镜像和容器的积累也会增加维护和管理的工作量。

        容器编排和管理的复杂性

        在大规模部署时,容器编排的复杂性可能成为瓶颈。简单的 Docker Compose 文件可能不足以管理服务依赖、负载均衡和自动扩缩容等需求。

        这需要引入更复杂的容器编排工具(如Kubernetes)来管理服务,这增加了系统的复杂性和学习成本。

        数据持久化挑战

        Docker 容器的无状态特性使得数据持久化成为一个挑战。特别是对于需要持久存储的应用(如数据库),需要妥善处理数据卷的备份和恢复策略。

两大重要技术

        Docker 本质就是宿主机的一个进程,Docker 是通过 namespace 实现资源隔离,通过cgroup实现资源限制,通过写时复制技术(copy-on-write)实现了高效的文件操作(类似虚拟机的磁盘比如分配500g并不是实际占用物理磁盘500g)

Namespace(命名空间)

        Namespace 是对全局系统资源的一种封装隔离机制,使得不同 Namespace 中的进程拥有独立的全局系统资源。这样,改变一个 Namespace 的系统资源只会影响当前 Namespace 中的进程,对其它 Namespace 中的资源没有影响。这种机制是实现容器技术(如Docker)的基础之一,为容器提供了轻量级的虚拟化环境。

Namespace参数隔离内容
UTSCLONE_NEWUTS主机名与域名
IPCCLONE_NEWWIPC信号量、消息队列及共享内存
PIDCLONE_NEWPID进程编号
NETWORKCLONE_NEWNET网络设备、网络栈、端口等
MOUNTCLONE_NEWNS挂载点(文件系统)
USERCLONE_NEWUSER用户和用户组

Control Group(控制组)

        Cgroup(Control Groups)是Linux内核提供的一种用于限制、记录和隔离进程组所使用的物理资源的机制。

        Cgroup 通过将进程分组并设置资源限制,来控制这些进程组可以使用的CPU、内存、磁盘IO等资源。Docker 等容器技术利用 Cgroup 来实现对容器资源的配额和限制。

子系统

        Cgroup 包含多个子系统,每个子系统负责控制不同类型的资源。

子系统作用子系统作用
blkio设置限制每个块设备的输入输出控制cpu使用调度程序为cgroup任务提供CPU的访问
cpuacct产生cgroup任务的CPU资源报告cpuset为多核心的CPU分配单独的CPU和内存给cgroup任务
devices允许或拒绝cgroup任务对设备的访问freezer暂停和恢复cgroup任务
memory设置每个cgroup的内存限制以及产生内存资源报告net_cls标记每个网络包以供cgroup方便使用
组织结构与基本规则

        Cgroup的组织结构和基本规则如下。

层级与子系统

        同一个层级可以附加一个或多个子系统,一个子系统也可以附加到多个层级(但目标层级只能有唯一子系统时)。

任务与cgroup

        一个任务(进程)不能存在于同一层级的不同cgroup中,但可以存在于不同层级中的多个Cgroup 中。任务在fork/clone时创建的子任务默认与原任务在同一个 Cgroup 中,但允许被移动到不同的 Cgroup 中。

特点

        Cgroup 的 API 以一个伪文件系统的实现方式,用户的程序可以通过文件系统实现 Cgroup 的组件管理。而Cgroup 的组件管理操作单元可以细粒度到线程级别,另外用户可以创建销毁 Cgroup,从而实现资源载分配和再利用。

        所有资源管理的功能都以子系统的方式实现,接口统一子任务创建之初与其父任务处于同一个 Cgroup 的控制组。

功能

资源限制

        可以对任务使用的资源总额进行限制。

优先级分配

        通过分配的 cpu 时间片数量以及磁盘IO 带宽大小,实际上相当于控制了任务运行优先级。

资源统计

        可以统计系统的资源使用量,如 cpu 时长,内存用量等。

任务控制

        Cgroup 可以对任务执行挂起、恢复等操作。

安装

        这里以 CentOS 7.9 系统为例。

        首先查看 CentOS 的版本,之后配置源时要配置和系统版本相匹配的源。

cat /etc/centos-release

        然后进入官方源在的仓库,删除官方源,配置国内源(这里用阿里云的源举例)。因为现在官方已经不提供 CentOS7.9 的后续服务了,而且配置国内源很多安装会简单快捷很多。

cd  /etc/yum.repos.d/
rm -rf *
curl  -O  http://mirrors.aliyun.com/repo/Centos-7.repo

        详细效果图如下。

        先安装 yum 相关的工具,方便后面下载 docker-ce.repo 文件。

yum install  yum-utils -y

        成功效果图如下。

        如果遇到下面“未知错误”的效果,不需要担心,重试上面的安装命令即可,这种情况一般是网络超时,多试几次会好。

        下载安装与系统版本匹配的 docker 的仓库文件。

yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

        然后更新 yum 的软件仓库缓存。当第一次配置完 yum 仓库或者仓库地址发生变化时,运行这个命令可以帮助 yum 索引仓库中的软件包,以便之后可以快速搜索和安装这些软件包。

yum makecache (fast) # fast可接可不接,有时候会让过程快一点

        效果图如下。

        安装 Docker,效果图如下。

yum -y install docker-ce

        启动 docker。

systemctl start docker

        设置开机启动。

systemctl enable docker

        效果图如下。

        查看 docker 进程。

        安装" vim "和" net-tools "。

yum  install  vim   net-tools -y

        这里的" yum install "指用 yum 进行安装下载操作;" vim "则指定安装 vim,即文本编辑器,这是一个非常强大的文本编辑器,广泛用于Linux系统中;" net-tools "指要安装 net-tools 包,它包含了一系列用于检查和控制网络设置的命令行工具,如 ifconfig、netstat 、route 等;" -y "则自动给出所有的提示都为 yes,使得安装过程不需要人工干预。

        安装后输入下面命令查询 docker 相关端口,但因为docker还没有启动容器,所以并没有监听Docker 相关的端口,效果图如下。

        关闭防火墙并禁止其开机自启。

systemctl stop firewalld
systemctl disable firewalld

        效果图如下。

 

        然后禁用 selinux,修改配置文件 /etc/selinux/config。

vim /etc/selinux/config

        进入后将 SELINUX 的状态修改成禁用。

        最后输入" reboot "重启即可。

reboot

        重启后,可以开始正常使用 docker。

基本命令

        这里先简单介绍几条 docker 使用时会用到的基本命令。

        查看 docker 版本,效果图如下。

docker version # 查看docker版本

        查看 docker 内的镜像。(镜像指由 docker 容器启动的软件所在的文件)

docker images

        本来有条命令" docker pull 软件名(这里用 nginx 举例)",是可以直接从 docker 的官方(docker hub)提供的镜像仓库网站去下载。但是由于某些不可抗力,这种国外的一般无法正常访问,运行结果如下图。

        现在我知道的有两种替代方法,一种是自己先在本机上下载 " 软件名.tar " 镜像文件,还有一种是登录他人的镜像仓库,然后进行拉取。

        登录其他镜像仓库的代码如下(这里用阿里云的镜像仓库举例)。

docker login --username=仓库用户名 registry.cn-地域(比如"hangzhou").aliyuncs.com

        然后输入密码,如果正确效果图应该如下。

        接下来再以本机文件直接传输为例。

        传输之后,再将镜像文件导入 docker 中。

docker load -i 镜像文件名

        现在镜像内就可以看到 nginx 这个镜像文件了。

        删除镜像文件。

docker rmi 镜像名

        创建并运行一个某个软件对应的容器(以" nginx "和" mysql"为例)。

docker run -d -p 自定义(0-65535):80 --name 自定义容器名 nginx
docker run -d -p 自定义(0-65535):3306 --name 自定义容器名 -e MYSQL_ROOT_PASSWORD='自定义密码' mysql:5.7.41(如果查看镜像有版本名,要在后面写完整)

        效果图如下,一个容器在docker里运行,本质上在 Linux 系统里就是一个进程。

        查看正在运行的容器,上面那张图有效果展示。

docker ps

        查看所有被创建的运行的容器,不管是否运行。

docker ps -a

        创建、运行、停止、删除一个容器。

docker create -d -p 自定义:80 --name 自定义容器名 nginx(以 nginx 为例) #创建容器
docker start 容器名 #运行创建的容器
docker stop 容器名 # 停止正在运行的容器
docker rm 容器名 # 删除容器(容器此时不能再运行)

        查看容器运行的具体状态,代码和效果图如下。

docker stats

        查看指定容器内部运行的进程信息。

docker top 容器名

        进入容器内部。(" exit "退出)

docker exec -it 容器名 bash

        查看容器日志信息。

docker logs 容器名

        查看 docker 主机上的所有网络。

docker network ls

        查看特定网络的详细信息。

docker network inspect 网络名

        查看 docker 服务器的状态。

systemctl status docker

        查看容器的详细配置信息(包括网络设置、CPU、内存、环境变量等)。

docker inspect 容器名

常见问题

1、cgroup的v1版本和v2版本的差异

        cgroup(Control Groups)是Linux内核提供的一种资源管理机制,用于限制、记录和隔离进程组使用的物理资源(如CPU、内存、I/O等)。cgroup存在两个主要版本,cgroup v1 和 cgroup v2,它们在设计理念、接口和功能上存在显著差异。

cgroup v1cgroup v2
架构设计提供了一种层次化的组织结构来管理进程组的资源;通过在/proc目录下创建一系列的虚拟文件和目录来实现资源隔离和限制(这些文件和目录包含了诸如cpu、memory、io等资源的配置和统计信息)cgroup API 的新一代版本,提供了更灵活的资源控制机制和更强大的层次结构管理;通过在/sys/fs/cgroup目录下使用文件系统来组织和管理控制组;并提供了以层次结构方式组织控制组的能力,并支持更细粒度的资源控制和配置
功能特性提供了基本的资源限制和隔离功能;支持多种资源控制器,如CPU、内存、I/O等,但每个控制器可能需要单独配置和管理提供了更丰富的功能,如更细粒度的资源控制、更强大的层次管理等;所有的控制器(如内存、CPU、I/O等)都被整合到同一个层次结构中,简化了资源管理的过程;支持在运行时动态添加和删除控制器,而无需重新启动系统
兼容性和配置在许多旧的Linux发行版和系统中仍然广泛使用;配置方式相对直接,但可能需要针对每个控制器进行单独配置在较新的Linux发行版中开始得到支持,如Ubuntu 21.10及以后版本、Debian 11及以后版本;需要确保kubelet和容器运行时(如Docker、containerd、cri-o等)都配置为使用支持cgroup v2的cgroup驱动程序(如systemd cgroup驱动程序);提供了更统一的接口和更强大的功能,但可能需要更新现有的应用程序和工具以支持cgroup v2
资源管理和隔离提供了基本的资源配额和限制功能,如限制进程组使用的CPU时间和内存大小;但某些高级功能(如更细粒度的资源控制)可能需要通过额外的工具或脚本来实现提供了更细粒度的资源控制功能,如更精确的CPU时间片分配、内存使用限制等;支持跨多个资源的增强资源分配管理和隔离,可以更有效地管理和隔离不同进程组的资源使用
性能和统计提供了基本的资源使用统计信息,如CPU使用时间、内存使用量等(但统计信息的详细程度和准确性可能受到限制)提供了更详细的资源使用统计信息,包括CPU使用的统计信息、PSI(Pressure Stall Information)信息等(这些统计信息有助于更好地监控和分析资源消耗情况,识别资源瓶颈并进行优化)

        综上所述,cgroup v2 在架构设计、功能特性、兼容性和配置、资源管理和隔离以及性能和统计等方面相比 cgroup v1 都有显著的改进和提升。然而,由于 cgroup v2 相对较新,可能需要更新现有的应用程序和工具以支持其特性。同时,在选择使用 cgroup v1 还是 cgroup v2 时,还需要考虑 Linux 发行版的支持和兼容性等因素。

2、容器启动不成功,如何排查问题

(1)查看容器日志
        首先,使用docker logs命令查看容器的日志信息。这通常能提供关于容器启动失败原因的详细信息。

(2)检查Docker环境
        确保Docker环境本身是正常的,检查Docker服务器的状态。如果服务未运行,尝试启动它。

(3)检查容器状态
        查看所有容器的状态,包括正在运行和已停止的容器。确认目标容器是否确实处于停止状态,或者是否有其他相关容器也存在问题。

(4)检查镜像
        检查镜像是否存在。查看本地镜像列表,确认目标镜像是否已存在;检查镜像是否损坏。如果怀疑镜像损坏,可以尝试重新拉取镜像;检查镜像版本兼容性。检查镜像版本是否与Docker守护程序兼容。

(5)检查容器配置
        查看容器的详细配置信息,包括网络设置、资源限制(如CPU和内存)、环境变量等。

(6)检查端口冲突
        如果容器因端口冲突而无法启动,检查端口占用情况,确保容器配置的端口未被其他进程占用。

(7)检查系统资源
        检查系统CPU和内存的使用情况,确保有足够的资源供容器使用;检查磁盘空间,使用" df -  h "命令检查磁盘空间,确保有足够的空间供 docker 使用。

(8)检查网络配置
        检查 docker 网络;检查防火墙和DNS。检查防火墙设置是否允许容器之间的通信,以及DNS解析是否正常。(DNS 解析在 /etc/resolv.conf 里看)

(9)检查依赖项和环境变量
        确保容器所需的所有依赖项都已安装,且环境变量设置正确。(这包括操作系统级别的依赖项和容器内部应用程序所需的依赖项。)

(10)查看 docker 守护程序的日志
       如果以上步骤都无法解决问题,可以考虑查看 docker 守护程序的日志,以获取更多关于容器启动失败的线索。(日志可能位于 var/log/docker/log,具体位置可能因系统而异)

        总的来说,docker 容器启动不成功可能由多种原因引起,包括镜像问题、配置错误、资源限制、网络问题、依赖项缺失等。通过系统地排查这些潜在问题,可以逐步缩小问题范围并最终找到解决方案。
 

  • 20
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值