一文讲解Docker入门到精通

一、引入

1、什么是虚拟化

在计算机中,虚拟化(英语:Virtualization)是一种资源管理技术,它允许在一台物理机上创建多个独立的虚拟环境,这些环境被称为虚拟机(VM)。每个虚拟机都可以运行自己的操作系统和应用程序,就像它们在单独的物理机上运行一样。虚拟化技术的关键在于它能够将物理资源(如处理器、内存、存储和网络)抽象化,使得这些资源可以被多个虚拟机共享和有效利用。

在实际的生产环境中,虚拟化技术主要用来解决高性能的物理硬件产能过剩和老的旧的硬件产能过低的重组重用,透明化底层物理硬件,从而最大化的利用物理硬件 对资源充分利用。

虚拟化主要有以下几种类型:

  1. 服务器虚拟化:这是最常见的虚拟化形式,它允许在一台物理服务器上运行多个虚拟服务器。这种技术通过使用虚拟机监视器(VMM)或称为Hypervisor的软件层来实现。Hypervisor可以直接安装在物理硬件上(类型1或裸机Hypervisor),或者作为操作系统之上的一个软件层(类型2或托管Hypervisor)。

  2. 存储虚拟化:这种虚拟化形式将多个存储设备的物理存储资源整合成一个或多个逻辑存储单元,从而简化管理和提高存储资源的利用率。

  3. 网络虚拟化:网络虚拟化涉及创建虚拟网络资源,如虚拟交换机、虚拟路由器和虚拟网络,这些资源可以在物理网络基础设施上创建多个隔离的网络环境。

  4. 桌面虚拟化:这种虚拟化允许用户通过远程访问在数据中心运行的虚拟桌面环境。用户可以在任何设备上访问他们的桌面,而桌面本身则运行在服务器上。

  5. 应用虚拟化:应用虚拟化允许应用程序在不同的操作系统和硬件平台上运行,而无需进行修改。这种技术通过将应用程序与底层操作系统分离来实现。

虚拟化的好处包括:

  • 资源利用率提高:通过共享物理资源,可以更有效地使用硬件。
  • 成本节约:减少了物理服务器的数量,从而降低了硬件、电力和冷却成本。
  • 灵活性和可扩展性:可以快速创建、复制和移动虚拟机,以适应不断变化的业务需求。
  • 灾难恢复和备份:虚拟化简化了备份和恢复过程,因为虚拟机可以很容易地被复制和迁移。
  • 隔离和安全性:每个虚拟机都是隔离的,一个虚拟机的故障不会影响其他虚拟机。

虚拟化技术已经成为现代数据中心和云计算基础设施的核心组成部分,它使得IT资源的管理和部署更加灵活和高效。

2、与虚拟化相关的东西

(1)虚拟化软件

KVM(Kernel-based Virtual Machine)和 VMware 是两种流行的虚拟化技术,它们在虚拟化领域中扮演着重要角色。下面是对这两种技术的简要介绍:

① KVM(Kernel-based Virtual Machine)

KVM 是一种基于 Linux 内核的开源虚拟化解决方案。它允许 Linux 内核本身作为一个 Hypervisor 来运行虚拟机。KVM 使用硬件虚拟化扩展(如 Intel VT 或 AMD-V)来提供虚拟化功能。KVM 虚拟化模型包括一个内核模块 kvm.ko 来实现核心虚拟化基础设施,以及一个或多个处理特定硬件设备扩展的模块。

主要特点:

  • 开源:KVM 是开源的,可以免费使用。
  • 集成于 Linux:KVM 是 Linux 内核的一部分,因此它与 Linux 操作系统紧密集成。
  • 硬件支持:KVM 利用现代处理器的硬件虚拟化扩展。
  • 灵活性:KVM 可以与 QEMU 结合使用,提供灵活的虚拟化解决方案。
  • 性能:KVM 提供了接近原生性能的虚拟化环境。
② VMware

VMware 是一家提供虚拟化和云基础设施解决方案的公司,其产品广泛应用于企业和数据中心。VMware 提供多种虚拟化产品,包括 VMware vSphere(用于服务器虚拟化)、VMware Workstation(用于桌面虚拟化)和 VMware Fusion(用于 Mac 平台)。

主要特点:

  • 商业产品:VMware 提供的产品是商业软件,通常需要购买许可证。
  • 成熟稳定:VMware 产品以其成熟稳定和丰富的功能而闻名。
  • 广泛的支持:VMware 提供了广泛的企业支持和服务。
  • 高级功能:VMware 提供了许多高级功能,如 vMotion(虚拟机迁移)、HA(高可用性)和 DRS(分布式资源调度)。
  • 生态系统:VMware 拥有庞大的生态系统,包括第三方工具和集成解决方案。
③ 比较
  • 成本:KVM 是免费的,而 VMware 是商业软件,需要购买许可证。
  • 支持:VMware 提供专业的技术支持和维护服务,而 KVM 主要依赖社区支持。
  • 功能和集成:VMware 提供了更多的高级功能和集成解决方案,而 KVM 则提供了基本的虚拟化功能,并可以与开源工具(如 QEMU)结合使用。
  • 性能:两者在性能上都非常接近原生性能,但具体的性能表现可能会因配置和使用场景而异。

选择 KVM 还是 VMware 取决于具体的需求、预算和技术偏好。对于需要高级功能和专业支持的企业环境,VMware 可能是更好的选择。而对于寻求成本效益和开源解决方案的用户,KVM 可能更合适。

(2)虚拟化软件管理web项目

OpenStack 和阿里云的飞天(Apsara)是两种不同的云计算平台,它们各自服务于不同的市场和用户需求。以下是对这两种平台的简要介绍和比较:

① OpenStack

OpenStack 是一个开源的云计算平台,旨在为企业提供构建和管理私有云和公有云的能力。它由一系列相互关联的服务组成,这些服务共同提供了一个完整的云基础设施解决方案。OpenStack 的组件包括计算(Nova)、存储(Cinder, Swift)、网络(Neutron)、身份认证(Keystone)、镜像服务(Glance)等。

主要特点:

  • 开源:OpenStack 是开源的,社区驱动,允许用户自由地修改和分发。
  • 模块化:OpenStack 由多个独立的模块(服务)组成,可以根据需要选择和部署。
  • 灵活性:用户可以根据自己的需求定制 OpenStack 的配置和部署。
  • 社区支持:OpenStack 拥有一个庞大的全球社区,提供丰富的文档和社区支持。
② 阿里云飞天(Apsara)

飞天是阿里云自主研发的云计算操作系统,它支撑了阿里云的公有云服务,并为企业和开发者提供了一系列的云服务和解决方案。飞天系统包括了计算、存储、网络、数据库、大数据处理等多个层面的服务,旨在提供稳定、可靠、高效的云计算基础设施。

主要特点:

  • 自主研发:飞天是阿里云自主研发的技术,与阿里云的其他服务紧密集成。
  • 企业级服务:飞天提供了企业级的云服务,包括高可用性、安全性、弹性伸缩等特性。
  • 生态系统:阿里云拥有庞大的生态系统,包括各种云产品和解决方案。
  • 专业支持:阿里云提供了专业的技术支持和客户服务。
③ 比较
  • 开源 vs 闭源:OpenStack 是开源的,而飞天是闭源的,属于阿里云的商业产品。
  • 灵活性 vs 集成性:OpenStack 提供了高度的灵活性和定制性,而飞天则提供了与阿里云其他服务的紧密集成。
  • 社区支持 vs 专业支持:OpenStack 依赖于社区支持,而飞天则提供了专业的技术支持和维护服务。
  • 成本:OpenStack 的部署和维护成本可能会因定制化和社区支持而有所不同,而飞天的成本则与阿里云的服务定价相关。

选择 OpenStack 还是飞天取决于用户的具体需求。如果用户需要一个灵活、可定制的云平台,并且希望利用开源社区的力量,OpenStack 可能是一个好选择。如果用户更倾向于使用一个成熟、集成度高的云服务,并且需要专业的技术支持,那么飞天可能更适合。

(3)容器化

容器化是一种轻量级的虚拟化技术,它允许开发者将应用程序及其依赖打包成一个独立的、可移植的容器。这个容器可以在任何支持容器技术的环境中运行,无需担心环境差异导致的问题。容器化技术最著名的实现是Docker。

① 主要特点
  1. 轻量级:容器共享宿主机的操作系统内核,不需要为每个应用启动一个完整的操作系统,因此启动速度快,资源消耗少。
  2. 隔离性:虽然容器共享宿主机的内核,但它们在用户空间提供了隔离,每个容器都有自己的文件系统、网络、进程空间等。
  3. 可移植性:容器将应用程序及其所有依赖打包在一起,确保了应用在不同环境中的一致性。
  4. 快速部署:容器可以快速启动和停止,非常适合微服务架构和持续集成/持续部署(CI/CD)流程。
  5. 弹性伸缩:容器可以轻松地根据需求进行扩展或缩减,提高资源利用率。
② 优势
  • 环境一致性:容器确保了开发、测试和生产环境的一致性,减少了"在我的机器上可以运行"的问题。
  • 快速部署和回滚:容器可以快速部署新版本的应用,并且在出现问题时快速回滚到之前的版本。
  • 资源高效:容器比传统虚拟机更高效地使用系统资源,因为它们不需要额外的操作系统开销。
  • 微服务架构:容器非常适合微服务架构,每个服务可以打包成一个容器,独立部署和扩展。
③ 容器化的挑战
  • 安全性:容器共享宿主机的内核,如果容器被攻破,可能会影响到宿主机或其他容器。
  • 复杂性:随着容器数量的增加,管理和编排容器变得复杂,需要使用如Kubernetes这样的容器编排工具。
  • 存储和网络:容器化带来了新的存储和网络挑战,需要专门的解决方案来管理容器的数据持久化和网络通信。
④ 应用场景
  • 微服务架构:容器化是实现微服务架构的理想选择,每个微服务可以打包成一个容器。
  • 持续集成/持续部署(CI/CD):容器化简化了构建、测试和部署流程,提高了开发效率。
  • 云原生应用:容器化是云原生应用开发和部署的核心技术之一。
  • 遗留应用现代化:容器化可以帮助将遗留应用现代化,提高其可移植性和可维护性。

(4)容器管理编排

容器管理编排是指自动化和管理容器化应用程序的过程,包括容器的部署、管理、扩展和网络配置等。随着容器技术的普及,特别是微服务架构的兴起,容器管理编排工具变得至关重要,因为它们可以帮助开发者有效地管理大量容器,确保应用程序的高可用性、可靠性和可扩展性。

① 主要功能
  1. 自动化部署和回滚:自动部署容器到集群中,并在出现问题时自动回滚到稳定版本。
  2. 服务发现和负载均衡:确保容器化服务可以被其他服务发现,并提供负载均衡以分散流量。
  3. 自动扩展:根据负载自动增加或减少容器实例,以保持应用性能和资源效率。
  4. 存储编排:自动挂载外部存储系统,如云存储、网络文件系统(NFS)等。
  5. 配置管理:管理容器应用的配置信息,确保配置的一致性和安全性。
  6. 密钥和配置管理:安全地存储和管理敏感信息,如密码、OAuth令牌和SSH密钥。
  7. 批量执行:在集群中批量执行任务,如数据备份、日志清理等。
  8. 资源监控和日志管理:监控容器和集群的资源使用情况,收集和分析日志。
② 常见的容器管理编排工具
  1. Kubernetes:由Google开发,是目前最流行的容器编排工具,提供了强大的自动化部署、扩展和管理容器化应用的能力。
  2. Docker Swarm:Docker官方提供的容器编排工具,与Docker平台紧密集成,易于使用。
  3. Apache Mesos:一个开源的集群管理器,可以运行Hadoop、Spark等多种框架,也支持容器编排。
  4. Amazon ECS/EKS:亚马逊云服务提供的容器编排服务,ECS是AWS原生的服务,EKS是托管的Kubernetes服务。
  5. Azure AKS:微软Azure提供的托管Kubernetes服务,简化了Kubernetes集群的部署和管理。
  6. Google GKE:谷歌云提供的托管Kubernetes服务,基于Google的Kubernetes引擎。
③ 容器管理编排的挑战
  • 复杂性:随着集群规模的增大,管理和维护编排系统变得更加复杂。
  • 安全性:需要确保容器和编排系统的安全性,防止未授权访问和数据泄露。
  • 性能监控:需要有效的监控工具来跟踪容器和集群的性能,及时发现和解决问题。
  • 故障恢复:需要设计有效的故障恢复策略,以确保应用的高可用性。

容器管理编排是容器化技术的关键组成部分,它使得大规模容器化应用的部署和管理变得更加高效和可靠。

二、docker介绍

1、什么是docker

Docker 是一个开源项目,诞生于 2013 年初,最初是 dotCloud 公司内部的一个业余项目。它基于 Google 公司推出的 Go 语言实现。 加了 Linux 基金会,遵从了 Apache 2.0 协议,项目代码在上进行维护。Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。容器不是一台机器,docker利用的是linux的资源分离机制,例如cgroups,以及linux核心命名空间(namespaces),来建立独立的容器(containers) 。容器看上去是一台机器,实际上是一个进程。

Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版),我们用社区版就可以了。

试想下边这样一个场景:当我们把我们的web网站做成分布式的时候,我们就要加服务器,然后在各个服务器配置web所需要的配置,比如:数据库、web服务器、运行时啥,这样的我们的网站才能跑起来,但是每当我们加服务器的时候,我们都要再重新配置一下,很繁琐,有了docker,我们就可以把我们的网站和所需要的环境配置好,打成一个包(docker镜像),然后在服务器上安装docker,用docker拉取打包好的镜像,直接run(容器)起来就行了,什么都不用管了,很方便,更加的便于管理,镜像中修改配置,重新更新,所有的容器就也能修改了,我们的网站也就修改更新了,特别的方便。

2、Docker 的优点

Docker 是一个用于开发,交付和运行应用程序的开放平台。Docker 使您能够将应用程序与基础架构分开,从而可以快速交付软件。借助 Docker,您可以与管理应用程序相同的方式来管理基础架构。通过利用 Docker 的方法来快速交付,测试和部署代码,您可以大大减少编写代码和在生产环境中运行代码之间的延迟。

(1)快速,一致地交付您的应用程序

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

容器非常适合持续集成和持续交付(CI / CD)工作流程,请考虑以下示例方案:

  • 您的开发人员在本地编写代码,并使用 Docker 容器与同事共享他们的工作。
  • 他们使用 Docker 将其应用程序推送到测试环境中,并执行自动或手动测试。
  • 当开发人员发现错误时,他们可以在开发环境中对其进行修复,然后将其重新部署到测试环境中,以进行测试和验证。
  • 测试完成后,将修补程序推送给生产环境,就像将更新的镜像推送到生产环境一样简单。

(2)响应式部署和扩展

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

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

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

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

(4)Docker典型场景

  • 使应用的打包与部署自动化
  • 创建轻量、私密的PAAS环境
  • 实现自动化测试和持续的集成/部署
  • 部署与扩展webapp、数据库和后台服务

3、 docker和虚拟机比较

一说到docker,相信大家之前也了解过,那就必须要和虚拟机做一下比较,其实docker是和虚拟机是类似的东西,我们应该知道虚拟机就是在我们的操作系统上虚拟出来一个电脑,然后里边可以安装、运行各种各样的软件,和我们真的电脑是差不多的,我们可以拿着这个虚拟好的电脑(其实是一个文件)在按了虚拟机的其他电脑上可以直接运行,里边的东西就不用我们来回安装和配置了,也是很方便的。

docker其实提供的也是这么一种的技术,只不过它比虚拟机效率更加的高,启动快,占用资源小等一系列的优点,而且虚拟机比较笨重,这是因为虚拟机和docker来实现思想上有本质的区别,我们可以通过下边的两张图可以对比一下:

当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。当新建一个虚拟机时,虚拟机软件需要加载GuestOS,整个新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,省略了这个复杂的过程,因此新建一个docker容器只需要几秒钟。因此docker更轻量级,所占的空间会更小,并且还能实现隔离。

这里要注意一下:但是docker本身并不是容器,而是创建容器的工具;而虚拟机它就是虚拟机了。

特性 Docker容器 VMware
虚拟化类型 OS虚拟化 硬件虚拟化
性能 =物理机性能 5%~20%损耗
隔离级别 进程级 操作系统级
隔离策略 Cgroups Hypervisor
启动时间 秒级 分钟级
镜像存储 KB~MB GB~TB
集群规模 上万 上百

补充:

Kubernetes(k8s)是Google开源的容器集群管理系统(谷歌内部:Borg),目前已经成为容器编排一个标准。为容器化的应用提供部署运行、资源调度、服务发现和动态伸缩、高可用等一系列完整功能,提高了大规模容器集群管理的便捷性。

总结:

虚拟机技术的缺点:

  • 资源占用太多
  • 冗余步骤多
  • 启动很慢

容器化技术的优点:

  • 服务器资源利用率高
  • 比较轻量化
  • 打包镜像测试,一键运行

比较Docker和虚拟机技术不同:

  1. 传统虚拟机,虚出一套硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
  2. 容器内的应用之间运行在 宿主机的内容,容器是没有自己的内核的,也没有虚拟我们的硬件,所以久轻便了
  3. 每个容器间是互相隔离的,每个容器内都有属于自己的文件系统,互不影响
  4. 安全性,docker的安全性更弱,
  5. 与虚拟机相比,docker隔离性更弱,docker属于进程之间的隔离,虚拟机可实现系统级别隔离
  6. docker创建时秒级的,docker的快速迭代性,无论是开发、测试、部署都可以节约大量时间

4、docker架构

Docker是一个客户端-服务器(C/S)架构程序。Docker客户端只需要向Docker服务器或者守护进程发出请求,服务器或者守护进程将完成所有工作并返回结果。Docker提供了一个命令行工具Docker以及一整套RESTful API。你可以在同一台宿主机上运行Docker守护进程和客户端,也可以从本地的Docker客户端连接到运行在另一台宿主机上的远程Docker守护进程。

  • Docker daemon( Docker守护进程)

    Docker daemon是一个运行在宿主机1( DOCKER-HOST)的后台进程。可通过 Docker客户端与之通信。

  • Client( Docker客户端)

    Docker客户端是 Docker的用户界面,它可以接受用户命令和配置标识,并与 Docker daemon通信。图中, docker build等都是 Docker的相关命令。

  • Images( Docker镜像)

    Docker镜像是一个只读模板,它包含创建 Docker容器的说明。它和系统安装光盘有点像,使用系统安装光盘可以安装系统,同理,使用Docker镜像可以运行 Docker镜像中的程序。

    镜像到底是个什么东西呢,很多人在学习docker的时候都是一头雾水的,可是是歪果仁对镜像情有独钟吧,好多东西都有镜像的概念。比如我们安装系统的.iso文件,其实就是镜像,这里你就可以把镜像认为是一种模板。我们可以使用docker根据这个模板创建容器来运行,其实更可以理解为镜像是好比github上的仓库一样,我们可以克隆下来源代码然后运行,运行起来的代码可以是一个网站、一个应用程序啥的,这就可以叫做容器。说白了,镜像就是一堆静态的模板,运行起来的镜像就是容器。镜像一般需要我们拉取下来,是只读的,这个我们克隆github上的仓库是一样一样的。

    docker镜像中有分层的概念,就是一个镜像可能基于好几个镜像,比如一个web运行环境可能需要操作系统ubuntu、数据库mysql、.net core runtime运行时,那我们拉取的这个镜像就会包好这好几个镜像,这就好像我们前边说的打包好的运行环境一样,直接就拉下来一个小电脑一样。

  • Container(容器)

    当我们拉取了一个镜像,然后run一下,就会根据这个镜像运行出来一个容器,运行的容器就好像我们的应用程序一样,可以访问可以停止,我们运用多次run命令,就运行了很多很多容器,也可以说是镜像的实例。从这个角度来看,镜像和容器的关系有点类似于面向对象中,类和对象的关系。可通过 Docker API或者 CLI命令来启停、移动、删除容器。

  • Repository(仓库)

    存放镜像的地方就是仓库,就好比存放代码的地方是github一样,我们就把github称为代码的仓库,github算是最大的仓库。那么存放docker镜像的地方我们叫做dockerhub,是docker的中央仓库。其实已经有dockerhub这个网站了(https://hub.docker.com/),这就是 存放docker镜像的官方仓库,好多官方的也保存在这里,保证了镜像的安全性和可靠性,我们可以从上边拉取一下镜像来运行我们的软件。当然我们也可以制作好我们自己镜像推送上去,不过这些肯定是要官方审核的,防止有些人写入一些恶意代码。不过我们可以推到我们自己的dockerhub上去,供我们自己使用,这个就好我们的github账号一样了,属于私有镜像了。

三、docker安装和配置

python 复制代码
# 1 linux   win 安装
# 2 win:https://www.docker.com/products/docker-desktop/  下载 docker-desktop
	-一路下一步安装
    
    
# 3 centos 7.9 安装
	-视频,软件:vmware ,镜像文件
    
    
# 4 创建一个centos 7.9的虚拟机,在这个基础上讲docker

# 5 如果之前装过,卸载
# yum remove docker docker-common  docker-selinux docker-engine
# rm -rf /var/lib/docker
yum update  # 更新yum仓库

# 6 安装
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install docker-ce -y


# 7 查看安装的版本
docker --version

# 8 目前我们只装了 docker-ce,
	-只有:c  和 s端
    -没有docker-compose
    -没有图形化解码
    -跟docker-destop的区别
    
    
# 9 启动docker
systemctl status docker
systemctl start docker


# 10 镜像--》从远程下载下来的---》hub.docker.com -->仓库下的
	-有非常多镜:可以搜索,搜到以后,镜像有不同版本
    -目前:访问不到了,拉去不下来
    -配置:国内镜像站:阿里云
    -https://cr.console.aliyun.com/cn-shanghai/instances/mirrors
    sudo mkdir -p /etc/docker # 如果有,就不需要创建了
    vi /etc/docker/daemon.json 
    # 加入
    {
      "registry-mirrors": ["https://x1566319.mirror.aliyuncs.com"]
    }
    # 按 esc
    # 输入  :wq  敲回车


    # 保存退出
    systemctl daemon-reload   # 重新加载docker配置
    systemctl restart docker  # 重启docker

四、Docker镜像和容器介绍

1、镜像(images)

Docker 镜像是一个独立的、轻量级的、可执行的软件包,它包含了运行应用程序所需的所有内容:代码、运行时、系统工具、系统库等。镜像是一个只读的模板,用于创建容器。它包含了应用程序运行所需的一切,因此可以确保在任何环境中都能一致地运行。

Docker 镜像通常是通过 Dockerfile 来创建的,Dockerfile 是一个文本文件,包含了一系列的指令,用于描述如何构建 Docker 镜像。通过运行 docker build 命令,可以根据 Dockerfile 构建出一个新的镜像。

2、容器(container)

Docker 容器是 Docker 镜像的运行实例。它包含了应用程序及其所有依赖的运行环境,包括文件系统、系统工具、库等。容器是独立于宿主机的,因此可以在任何支持 Docker 的平台上运行。

通过 Docker 容器,可以轻松地部署、复制和扩展应用程序。容器还提供了隔离性,使得应用程序之间不会相互影响。每个容器都是相互隔离的,因此可以同时运行多个容器,而它们之间不会发生冲突。

3、镜像和容器的关系

可以将 Docker 镜像看作是一个类比于类的概念,而 Docker 容器则是类的实例。镜像定义了应用程序运行所需的一切,而容器则是镜像的运行实例,它们之间是一种类与实例的关系。

容器是由镜像实例化而来,这和我们学习的面向对象的概念十分相似,我们可以把镜像看作类,把容器看作类实例化后的对象。也可以说镜像是文件, 容器是进程。 容器是基于镜像创建的, 即容器中的进程依赖于镜像中的文件, 这里的文件包括进程运行所需要的可执行文件,依赖软件,库文件,配置文件等等...

总的来说,Docker 镜像是一个静态的定义,用于创建容器,而容器则是一个运行时实体,可以被启动、停止、删除等操作。docker的整个生命周期有三部分组成:镜像(image)+容器(container)+仓库(repository)。

五、镜像操作

1、搜索镜像

  • 去网站搜索
python 复制代码
https://hub.docker.com/ 
  • 使用命令行搜
bash 复制代码
docker search mysql

2、查看镜像

bash 复制代码
docker images

3、拉取镜像

  • 从register下载到本地,使用阿里云镜像站加速拉取
  • 注意拉取的对象在上面的网站一定能搜索得到的,在远程仓库,每一个镜像都有 对应的镜像名字和标签(tag),比如 ubuntu 和 latest。
python 复制代码
docker pull mysql:5.7 # 下载mysql 5.7镜像
docker pull redis:latest # 下载redis最新的镜像
docker pull nginx:latest  # 下载 nginx最新的镜像
docker pull centos:centos7  # 下载 centos7 的镜像

4、删除镜像

bash 复制代码
# 删除指定镜像
docker rmi redis:latest
或
docker image rm ed21b7a8aee9

# 删除所有镜像
docker image rm $(docker image ls -q) -f

# 清理临时的、没有被使用的镜像文件
docker image prune
# -a 删除全部未使用到的镜像
docker image prune -a
# -f 强制删除,不需要确认
docker image prune -a -f 

六、容器操作

容器是镜像的运行实体。镜像是静态的只读文件,而容器带有运行时需要的可写文件层,并且容器中的进程属于运行状态。

1、创建并运行一个容器,处于运行状态(run)

python 复制代码
docker run [OPTIONS] IMAGE
# 1.OPTIONS(可选)
-d	在后台运行容器并打印容器ID(这也是非常常见的操作)
-i  意思就是会把交互界面保留着
-t	分配一个虚拟终端,在docker中启动bash就会有提示符,通常和-it会一起出现
-p  向宿主发布(开放)容器的端口,就是把容器端口和宿主机端口进行映射。 (-p + 宿主机端口:容器端口)
	-p 的作用是把完全和外界隔离的容器,暴露出一个端口让宿主机得以访问(重要)
-v  绑定挂载卷
# 2.IMAGE
镜像名称
# 3.常见用法示例
# --name后面跟的是启动镜像后,生成的容器的名称
# nginx 是要运行的镜像的名称
docker run --name containerName -p 80:80 -d nginx

很重要的要说明的一点:**Docker容器后台运行,就必须有一个前台进程。**容器运行的命令如果不是一直挂起的命令(比如运行top,tail),就是会自动退出的。最佳的解决方案是,将你要运行的程序以前台进程的形式运行。常见就是命令行模式,表示我还有交互操作,别中断。所以这里运行一个容器示例就衍生出来两种方式:

python 复制代码
# 前台交互式启动(启动后会带一个前台运行的命令行)进入到容器内部,可以执行redis的命令,但是它是最精简的系统,很多命令可能没有,用的话需要安装
docker run -it redis:6.0.8

# 后台守护式启动
docker run -d redis:6.0.8

这个命令使用起来是很复杂的,文档内容非常长。最好就是想要运行什么容器,就直接去DockerHub上查看帮助文档。

那么如何查看帮助文档呢?

redis为例。找到官方镜像以后。有Overviewtag两栏。在Overview下往下拉,就能看到一个小标题How to use this image

2、查看所有正在运行的容器以及它们的状态(ps)

python 复制代码
docker ps [OPTIONS]
# 1.常用OPTIONS(可选)
-a	显示全部容器(默认显示正在运行的容器)
-q  显示停止运行的容器的容器id
-l  显示最近创建的容器。
-n  显示最近n个创建的容器。

# 2.常见用法示例
docker ps
docker ps -a
docker ps -q

3、查看某个容器的运行日志(logs)

python 复制代码
docker logs [OPTIONS] CONTAINER
# 1.常用OPTIONS(可选)
-f 跟踪日志输出(持续输出最新日志)
-t 显示时间戳
--tail 仅列出最新N条容器日志
# 2.CONTAINER
要查看日志的容器名称
# 3.常见用法示例
docker logs myNginx
docker logs -f myNginx					# 跟踪日志输出
docker logs -f --tail 100 myNginx		# 跟踪最新100条的日志输出

4、删除一个不在运行的容器(rm)

python 复制代码
docker rm [OPTIONS] CONTAINER [CONTAINER...]
# 1.常用OPTIONS(可选)
-f 强制移除正在运行的容器(不写-f只能移除不在运行的容器)
-v 删除与容器关联的数据卷
# 2.CONTAINER
要删除的容器名称/容器id也可以
# 3.常见用法示例
docker rm myNginx				#直接删除容器名称为myNginx的不在运行的容器
docker rm -f myNginx			#强制删除容器myNginx,即使是正在运行也会被删除
docker rm $(docker ps -a -q)	#删除所有未运行的容器

# 4.补充
# 清理掉所有处于终止状态的容器。
docker container prune

5、run参数总结

python 复制代码
-i 表示运行容器
-d 以守护式容器在后台运行,用这个参数创建出来的容器,命令行还在宿主机上,没有进入到容器内部
-t 表示容器启动后会进入容器命令行。加入这参数后,容器创建就能登录进去。即分配一个伪终端。
--name 指定容器名字,如果不指定,会随机一个名字
-p 表示端口映射,前者是宿主机端口,后者是容器内的映射端口。可以使用多个-p做多个端口映射
-v 表示目录映射关系(前者是宿主机目录,后者是容器的目录),可以使用多个-v做多个目录或文件映射。注意:最好做目录映射,在宿主机上做修改,然后共享到容器上

6、 docker exec 命令

python 复制代码
# exec 是在容器中打开新的终端,并且可以启动新的进程 用exit退出,不会导致容器的停止。
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
# 1.常用OPTIONS(可选)
-d	在后台执行命令
-i  意思就是会把交互界面保留着
-t	分配一个虚拟终端,在docker中启动bash就会有提示符,通常和-it会一起出现
-e	设置环境变量
# 2.CONTAINER
需要进入的容器名称/容器id
# 3.COMMAND
进入容器后需要执行的命令
# 4.命令示例
docker exec -it myNginx /bin/bash

docker exec -it myNginx bash这是一条很重要的命令。执行它以后就可以进入myNginx这个容器,并显示当前容器的命令行终端。在属于myNginx这个容器的命令行终端上,执行的命令都会作用于myNginx容器的内部系统.

补充:attach 命令

bash 复制代码
docker attach 容器ID/名称
  • exec是在容器中打开新的终端,并且可以启动新的进程用exit退出,不会导致容器的停止。如果是run命令进入的话,exit退出容器也会停止。
  • attach 直接进入容器启动命令的终端,不会启动新的进程 用exit退出,会导致容器的停止。

7、-v目录映射详解

python 复制代码
# 1 -v 参数表示运行容器时,跟宿主机的文件目录做映射




#2 小案例
    # 运行出一个 centos77 容器,不进入, 做目录映射
    # 把宿主机的 /root/xiao文件夹  映射到 容器内部的 /xiao文件夹  容器如果没有文件夹会自动创建
    # -v可以写多个,可以是文件或文件夹

    1 cd # 回家 前提是你是root用户
    2 mkdir xiao  # 在root目录下创建xiao文件夹
    3 运行容器,做目录映射
    docker run -id --name=centos77 -v /root/xiao:/xiao centos:centos7
    4 在宿主机的 /root/xiao 下新建 xx.txt
    vim xx.txt

    5 来到容器内部:看这个文件在不在
    docker exec -it 容器名字/id /bin/bash
    cat xx.txt

    6 他们是相互影响的:
        容器内部修改文件---》会影响外部
        外部修改文件---》影响内部



# 3 目录映射好处是,后期咱们部署django项目
	1 有个django容器,做好映射,代码放在宿主机上即可,以后更新了代码,只要重启容器,代码就是最新了
    2 运行mysql容器---》mysql配置文件,数据data目录,放在宿主机上做好映射
    	如果 mysql容器---》表数据,放到容器中---》如果删了容器---》数据库全没了
    	表数据,放在宿主机上---》把容器删除---》表数据还在----》再启动一个容器做好映射---》数据都还在

8、-p端口映射详解

python 复制代码
# 1  -p参数:端口映射  容器中启动一个mysql5.7 --》容器中的3306监听,宿主机3306没人监听,做端口映射后,宿主机的3306就被docker的这个容器监听了

# 2 小案例,运行一个mysql容器--》做端口映射
docker run -id --name=mysql5.7 -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
#  -p: 启动mysql容器  -p 宿主机端口:容器端口
# -e :启动的mysql的root密码是123456
# 以后台守护进程运行mysql容器,mysql的root用户密码是123456,宿主机和容器做了端口映射
	宿主机 3307 映射容器 3306

    
## 2.1 查看宿主机 3307端口占用情况

    #  netstat -nlp |grep 3307 查看本机80端口占用情况
    # 查看宿主机 3307端口占用情况
    yum install net-tools -y
    netstat -nlp | grep 3307 # 被docker占了

## 2.2 远程链接宿主机的3307端口
	以后访问宿主机3307端口就等于访问容器的3306端口

    # win机器可以远程链接 mysql
        -命令行链接:mysql -h 10.0.0.110 -P 3307 -uroot -p
        -Navicate: 链接,创建xiao数据库

    # 宿主机--》进入到容器内部--》进入到mysql,查看有没有创建xiao这个库
        docker exec -it mysql5.7 /bin/bash # 进入容器内部
        mysql -uroot  -p  # 进入mysql
        show databases;  # 查看所有数据库

9、其他

python 复制代码
#1 启动容器
	docker start 容器id

#2 停止容器
	docker stop 容器id

#3  mysql的容器底层的操作系统是 debian 装软件需要用 
    apt-get update
    apt-get install vim -y


#4  文件拷贝(宿主机执行)
	# 容器的文件copy到宿主机上(不是在容器内执行)
    docker cp 容器名称:容器目录 需要拷贝的文件或目录
    docker cp  0a9633190cb9:/xx.txt /root/xiao/xiao.txt
    
    # 宿主机的文件copy到容器中
    docker cp 需要拷贝的文件或目录 容器名称:容器目录
    docker cp /root/xiao/xx.txt  0a9633190cb9:/xx.txt

        
#5 查看容器IP地址    
	docker inspect 容器名称  # 查看容器的详细描述,很多
    docker inspect ea5f3c9ee99a --format='{{.NetworkSettings.IPAddress}}' 容器名称(容器ID)
    
    
#6 在多个容器之间是可以ping通的(容器和宿主机也可以)
    # python:172.17.0.3

    # mysql5.7:172.17.0.2

    # 宿主机--》ping 它俩
    # 容器--》容器
    apt-get install iputils-ping
     ping 172.17.0.2

    
#7 删除容器(删除已停止的容器)
	docker rm 容器id  
    docker rm `docker ps -a -q`


#8 无状态的服务(在容器中尽量运行无状态的服务)
    -mysql reids   有状态,运行过程中产生数据,保存,容器删除,数据就没了
    -uwsgi+django  无状态的服务


#9 补充
(1) ip地址  ip 
10.0.88.110
10.0.0.111
10.0.0.1
10.0.11.1

(2) 子网掩码 mask
255.255.0.0

(3) 网关 gatway
10.0.0.1

七、应用部署

1、mysql 部署

当我们学会在dokcer中部署mysql之后,以后就不需要在宿主机上装mysql了。另外,如果没有做目录映射,表数据都在容器中,一旦容器被删除,所有数据就都没了。

(1)拉取mysql镜像

bash 复制代码
docker pull centos/mysql-57-centos7

(2)创建容器

bash 复制代码
docker run -di --name=mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7

(3)做目录映射

  • 需要data文件,配置文件
python 复制代码
mkdir /mysql
mkdir /mysql/conf.d
mkdir /mysql/data/
vi /mysql/my.cnf

[client]
default-character-set=utf8
[mysqld]
user=mysql
character-set-server=utf8
default_authentication_plugin=mysql_native_password
secure_file_priv=/var/lib/mysql
expire_logs_days=7
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
max_connections=1000

docker run  -di -v /mysql/data/:/var/lib/mysql -v /mysql/conf.d:/etc/mysql/conf.d -v /mysql/my.cnf:/etc/mysql/my.cnf -p 3306:3306 --name mysql5.7 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7 

(4)创建库,创建表,插入数据

(5)远程登录mysql

  • 连接宿主机的IP ,指定端口为3306

(6)数据恢复

  • 如果当我们不小心关闭容器,并且删除了容器,这样myslq的容器就没了,但是数据在宿主机上放着。所以我们再运行起一个容器,做好目录映射,数据都回来了
bash 复制代码
docker run  -di -v /mysql/data/:/var/lib/mysql -v /mysql/conf.d:/etc/mysql/conf.d -v /mysql/my.cnf:/etc/mysql/my.cnf -p 3306:3306 --name mysql2 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7 


# 补充  -e参数--》环境变量
不同镜像提供不同参数
传入后放入环境变量
echo $MYSQL_ROOT_PASSWORD

2、redis部署

(1) 拉取redis镜像

bash 复制代码
docker pull redis  # 最新

(2)创建容器

python 复制代码
mkdir /root/data
vim /root/redis.conf

bind 0.0.0.0
daemonize NO
protected-mode yes
requirepass 123456


docker run -id  -p 6379:6379 --name redis -v /root/redis.conf:/etc/redis/redis.conf -v /root/data:/data redis  redis-server /etc/redis/redis.conf

(3)启动redis

bash 复制代码
redis-server /etc/redis/redis.conf
  • 在容器运行时,可以自己定制运行命名 举例:
bash 复制代码
docker run -id centos:centos7 ls

3、nginx部署

(1)拉取nginx镜像

bash 复制代码
docker pull nginx

(2)创建容器

bash 复制代码
docker run -id --name nginx -p 80:80 nginx
# 创建并进入
docker run -it --name nginx -p 80:80 nginx

(3)页面路径修改

  • html页面存放:/usr/share/nginx/html
  • 以后只需要修改宿主机的/root/html 路径,看到页面就是修改后的
python 复制代码
docker run -id --name nginx1 -p 8008:80 -v /root/html:/usr/share/nginx/html nginx 

八、补充

1、虚拟机安装ubuntu

2、ubuntu上安装docker

在Ubuntu上安装Docker,你可以按照以下步骤进行:

(1)更新包索引

首先,确保你的包索引是最新的:

bash 复制代码
sudo apt update

(2)安装必要的软件包

安装一些必要的软件包,这些软件包允许apt通过HTTPS使用软件包:

bash 复制代码
sudo apt install apt-transport-https ca-certificates curl software-properties-common

(3)安装Docker CE

安装Docker Community Edition(CE):

bash 复制代码
sudo apt install docker-ce

(4)添加阿里源

python 复制代码
# 10 镜像--》从远程下载下来的---》hub.docker.com -->仓库下的
	-有非常多镜:可以搜索,搜到以后,镜像有不同版本
    -目前:访问不到了,拉去不下来
    -配置:国内镜像站:阿里云
    -https://cr.console.aliyun.com/cn-shanghai/instances/mirrors
    sudo mkdir -p /etc/docker # 如果有,就不需要创建了
    vi /etc/docker/daemon.json 
    # 加入
    {
      "registry-mirrors": ["https://x1566319.mirror.aliyuncs.com"]
    }
    # 按 esc
    # 输入  :wq  敲回车

(5)验证Docker安装

安装完成后,验证Docker是否正确安装并运行:

bash 复制代码
sudo docker run hello-world

这个命令会下载一个测试镜像,并在容器中运行它。如果一切正常,你将看到一条消息,表明Docker安装成功。

(6)(可选)非root用户使用Docker

默认情况下,只有root用户和具有sudo权限的用户才能运行Docker命令。为了允许普通用户使用Docker,可以将用户添加到docker用户组:

bash 复制代码
sudo usermod -aG docker ${USER}

然后,重新登录或运行以下命令以应用更改:

bash 复制代码
su - ${USER}

请注意,将用户添加到docker组授予了该用户运行Docker命令的权限,这可能会带来安全风险。

(7)(可选)启用Docker服务

如果你希望Docker服务在系统启动时自动启动,可以运行:

bash 复制代码
sudo systemctl enable docker

3、小案例

要在 Docker 中运行 Django 图书管理系统,并通过宿主机的 80 端口访问该系统,您可以按照以下步骤操作:

步骤一:克隆 Django 项目

首先,您需要将项目克隆到本地:

bash 复制代码
apt install git
git clone https://gitee.com/liuqingzheng/books.git

步骤二:创建 Dockerfile

在项目根目录中创建一个 Dockerfile:

Dockerfile 复制代码
# 使用 Python 3.10 作为基础镜像
FROM python:3.10

# 设置工作目录
WORKDIR /app

# 安装依赖
COPY requirements.txt /app/
RUN pip install -r requirements.txt

# 将整个项目复制到容器中
COPY . /app

# 运行 Django 服务器
CMD python manage.py runserver 0.0.0.0:8000

步骤三:创建 requirements.txt

在项目根目录中创建一个 requirements.txt 文件,列出项目所需的依赖:

Django==3.2.8

步骤四:构建 Docker 镜像

在包含 Dockerfile 的目录中构建 Docker 镜像:

bash 复制代码
docker build -t django-book-management .

步骤五:运行 Docker 容器

运行以下命令来启动 Django 图书管理系统的 Docker 容器,并将容器的 8000 端口映射到宿主机的 80 端口:

bash 复制代码
docker run -p 80:8000 django-book-management

步骤六:访问图书管理系统

现在,您可以在浏览器中通过访问宿主机的地址即可来访问图书管理系统。

九、迁移和备份

迁移和备份主要有三个操作命令将容器保存为镜像、备份镜像(将镜像导出为一个文件)、镜像的迁移与恢复。迁移与备份在实际操作 Docker 的过程中使用的是非常多的,比如要将一台服务器的镜像迁移到另外一台服务器,就么可以先将镜像保存为一个文件,然后将文件拷贝至另一台服务器,最后进行镜像的恢复来实现。

1、镜像的来源

(1)远程仓库

  • 我们可以使用docker pull 镜像名来从远程仓库拉取镜像

(2)通过容器打包成镜像

  • 自己或者别人封装好内容并且将该容器打包成镜像,然后我们或者别人拿到就可以再运行成容器即可使用

(3)Dockerfile构建

  • 使用Dockerfile命令构建镜像

2、容器保存为镜像

(1)语法

bash 复制代码
docker commit 容器名称 镜像名称 

(2)具体使用

python 复制代码
# 1.运行一个centos容器
    docker run -id --name centos centos:centos7

# 2.在容器中装vim并创建一个文件
    docker exec -it centos /bin/bash
	yum install vim -y
    vim ss.txt
    
# 3.切到宿主机上,把容器做成镜像(centos+vim)
    docker commit centos centos_vim_image

# 4.基于新构建的镜像,运行成容器
    docker run -id --name centos_vim centos_vim_image:latest

# 5.进入到容器中,查看,软件,文件都在
    docker exec -it c3e633bd1 /bin/bash

3、本地镜像推送到远程仓库

使用 docker push 将镜像推送到 Docker Hub 镜像仓库或自行托管的镜像仓库。

在推送镜像时,会根据镜像的完整名称(镜像的tag)进行推送到对应的仓库,除非用户使用 docker tag 修改了镜像的tag,否则默认都会推送到 hub.docker.com 仓库。

(1)给镜像打个tag

python 复制代码
 docker tag 镜像id  镜像新名字(账号名/镜像名)

(2)登录到你hub.docker账号中

python 复制代码
docker login  输入账号密码

(3)推到远端仓库

python 复制代码
docker push 上面的镜像新名字

(4)下载

python 复制代码
docker pull 名字

4、备份与恢复

(1)镜像备份

使用docker save命令将镜像保存为 tar 文件。例如,要将名为my_image的镜像保存为名为my_image.tar的文件,可以执行以下命令:

python 复制代码
docker save -o my_image.tar my_image

(2)镜像恢复与迁移

使用docker load命令从 tar 文件中加载镜像。例如,要从名为my_image.tar的文件中加载镜像,可以执行以下命令:

python 复制代码
docker load -i my_image.tar

然后基于新加载的镜像创建一个新的容器。例如,要创建一个名为my_container_new的新容器,可以执行以下命令:

python 复制代码
docker run -d --name my_container_new my_image_new

十、Dockerfile

1、Dockerfile介绍及编码规则

Dockerfile 是用于构建 Docker 镜像的文本文件,其中包含了一系列的指令,用于描述镜像的构建步骤。通过 Dockerfile,用户可以定义镜像内的环境、应用程序、服务以及运行时所需的配置等信息。

Dockerfile有以下编码规则:

  • 文件名必须是 Dockerfile
  • Dockerfile中所用的所有文件一定要和Dockerfile文件在同一级父目录下
  • Dockerfile中相对路径默认都是Dockerfile所在的目录
  • Dockerfile中一能写到一行的指令,一定要写到一行,因为每条指令都被视为一层,层多了执行效率就慢
  • Dockerfile中指令大小写不敏感,但指令都用大写(约定俗成)
  • Dockerfile 非注释行第一行必须是FROM
  • Dockerfile 工作空间目录下支持隐藏文件(.dockeringore),类似于git.gitingore

2、Dockerfile常用命令

详细介绍:https://zhuanlan.zhihu.com/p/419175543?utm_id=0

Dockerfile常用指令 功能简介
FROM 指定构建新Image时使用的基础Image,通常必须是Dockerfile的第一个有效指令,但其前面也可以出现ARG指令
LABEL 附加到Image之上的元数据,键值格式
ENV 以键值格式设定环境变量,可被其后的指令所调用,且基于新生成的Image运行的Container中也会存在这些变量
RUN 以FROM中定义的Image为基础环境运行指定命令,生成结果将作为新image的一个镜像层,并可由后续指令所使用
CMD 基于该Dockerfle生成的Iimage运行Container时,CMD能够指定容器中默认运行的程序,因而其只应该定义一次
ENTRYPOINT 类似于CMD指令的功能,但不能被命令行指定要运行的应用程序覆盖,且与CMD共存时,CMD的内容将作为该指令中定义的程序的参数
WORKDIR 为RUN、CMD、ENTRPOINT、COPY和ADD等指令设定工作目录
COPY 复制主机上或者前一阶段构建结果中(需要使用--from选项)文件或目录生成新的镜像层
ADD 与COPY指令的功能相似,但ADD额外也支持使用URL指定的资源作为源文件
Dockerfile一般指令 功能简介
VOLUME 指定基于新生成的Image运行Container时期望作为Volume使用的目录
EXPOSE 指定基于新生成的Image运行Container时期望暴露的端口,但实际暴露与否取决于"docker run"命令的选项,支持TCP和UDP协议
USER 为Dockerfile中该指令后面的RUN、CMD和ENTRYPOING指令中要运行的应用程序指定运行者身份UID,以及一个可选的GID
ARG 定义专用于buid过程中的变量,但仅对该指标之后的调用生效,其值可由命令行选项"-build-arg"进行传递
ONBULID 触发器,生效于由该Dockerfile构建出的新Iage被用于另一个Dockerfle中的FROM指令作为基础镜像时
STOPSIGNAL 用于通知Container终止的系统调用信号
HEALTHCHECK 定义检测容器应用的健康状态的具体方法
SHELL 为容器定义运行时使用的默认shell程序,Linux系统默认使用["/bin/sh""-c"],Windows默认使用["cmd"","/S","/C"]
  • Dockerfile语法介绍
python 复制代码
FROM 基础镜像 	       # 基于哪个基础镜像来构建
MAINTAINER xiao 	      # 声明镜像的创建者
ENV key value 	      # 设置环境变量 (可以写多条)
ENV key value 	      # 设置环境变量 (可以写多条)
RUN command 	      # 是Dockerfile的核心部分(可以写多条)
ADD source_dir/file dest_dir/file 	#将宿主机的文件复制到镜像内,如果是一个压缩文件,将会在复制后自动解压
COPY source_dir/file dest_dir/file 	# 和ADD相似,但是如果有压缩文件并不能解压
WORKDIR xiao 	# 设置工作目录,运行起这个容器,来到的路径就是这个路径

CMD ["command1","command2"]  # 启动并运行容器执行的命令

3、小案例1

  • 实现:构建一个带vim的centos:7镜像,根路径下有/xiao/ss.py
python 复制代码
# 1.构建Dockerfile文件
vim Dockerfile

# 2.Dockerfile内容
FROM centos:centos7
MAINTAINER xiao
ENV name xiao
ARG age 19
RUN yum update&&yum install vim -y
RUN mkdir /xiao
RUN touch /xiao/ss.py
RUN echo 'print(1)' > /xiao/ss.py
RUN echo $name
RUN echo $age
WORKDIR /xiao

# 3.基于dockerfile构建镜像,不要忘了 .   基于当前路径下的Dockerfile 构建镜像
docker build -t='centos_xiao_vim' . 
docker images

# 4.基于这个镜像运行容器
 docker run -id --name xx centos_xiao_vim

# 5.进入到容器
docker exec -it xx /bin/bash

# 6.验证vim,和文件夹,文件是否存在

4、小案例2

  • 实现:验证CMD运行容器时会默认加上 /bin/sh -c,CMD的命令可以被覆盖
python 复制代码
# 1.构建Dockerfile文件
vim Dockerfile

# 2.Dockerfile内容
FROM centos:centos7
MAINTAINER xiao
ENV name xiao
RUN mkdir /xiao
RUN touch /xiao/ss.py
RUN echo 'input()' > /xiao/ss.py
WORKDIR /xiao
CMD ['python' ,'./ss.py']   # 运行容器时会默认加上 /bin/sh -c

# 3.基于dockerfile构建镜像,不要忘了 .   基于当前路径下的Dockerfile 构建镜像
docker build -t='centos_py' . 
docker images

# 4.基于这个镜像运行容器
# 1)验证CMD运行容器时会默认加上 /bin/sh -c
docker run -id --name yy centos_py
# 2)验证CMD的命令可以被覆盖==> 用python /xiao/ss.py去替换了/bin/sh -c ['python' ,'./ss.py']
docker run -id --name yy centos_py python /xiao/ss.py

# 5.进入到容器
docker exec -it xx /bin/bash

# 6.查看环境变量
# 1)python看
os.environ.get('name')
# 2)shell看
echo $name

补充:当容器没起来的时候,我们可以通过docker logs 容器名字/id号来查看错误日志排查错误

5、面试题

(1) CMDENTRYPOINT 的异同点

  • https://zhuanlan.zhihu.com/p/548188679

  • 相同点:

    • 都只能写一条,如果写了多条,那么只有最后一条生效。
    • 都是容器启动时才运行,运行时机相同。
  • 不同点:

    • ENTRYPOINT不会被运行的command覆盖,而CMD则会被覆盖。
    • 如果我们在Dockerfile中同时写了ENTRYPOINT和CMD,并且CMD指令不是一个完整的可执行命令,那么CMD指定的内容将会作为ENTRYPOINT的参数。

(2)ARG 和 ENV

  • ENV:设置执行命令时的环境变量,并且在构建完成后,仍然生效(比较常用)
  • ARG:设置只在构建过程中使用的环境变量,构建完成后,将消失

6、ARG 指令详解及使用示例

ARG 是 Dockerfile 中的一个指令,用于定义变量。在 Dockerfile 中定义的变量可以在构建过程中使用,也可以在构建命令中通过 --build-arg 选项传递给构建过程。

ARG APPLY_IN_DOCKER=/tmp/apply_in_docker 这行命令具体解释如下:

  • ARG: 指定这是一个定义变量的指令。
  • APPLY_IN_DOCKER: 这是变量的名称,你可以在 Dockerfile 或构建过程中引用它。
  • /tmp/apply_in_docker: 这是变量的默认值,如果构建时没有通过 --build-arg 指定该变量的值,就会使用这个默认值。

这个变量可以在 Dockerfile 中的任何地方被引用,例如在 COPY, ADD, ENV 等指令中。变量的值可以被替换到这些指令中,使得 Dockerfile 更加灵活和可配置。

举例说明

假设我们有一个 Dockerfile,需要根据 APPLY_IN_DOCKER 变量的值来决定复制文件到容器内的哪个目录:

python 复制代码
# 定义变量
ARG APPLY_IN_DOCKER=/tmp/apply_in_docker
# 使用变量定义环境变量
ENV MY_APP_DIR $APPLY_IN_DOCKER
# 构建基础镜像
FROM ubuntu:latest
# 使用变量作为目标路径复制文件
COPY . $MY_APP_DIR
# 其他指令...

在这个例子中,APPLY_IN_DOCKER 变量被用来设置环境变量 MY_APP_DIR,然后这个环境变量被用作 COPY 指令的目标路径。这样,无论 APPLY_IN_DOCKER 被设置为哪个路径,COPY 指令都会将当前目录(.)的文件复制到容器内的相应路径。

如果你想要覆盖默认值,可以在构建 Docker 镜像时使用 --build-arg 选项,如下所示:

docker build --build-arg APPLY_IN_DOCKER=/my/custom/path -t myimage .

在这个命令中,APPLY_IN_DOCKER 被设置为 /my/custom/path,Dockerfile 中的 COPY 指令将会把文件复制到 /my/custom/path 而不是默认的 /tmp/apply_in_docker

十一、dockerfile构建一个djagno项目(books图书管理系统)

python 复制代码
# 以图书管理系统为例---》公司使用docker流程


# 公司中,使用Docker开发的工作流程
第一步:有一个项目,pycharm开发着,开发完后
第二步:在项目路径下新建Dockerfile,写入
FROM python
MAINTAINER xiao
WORKDIR /soft
COPY ./requirements.txt /soft/requirements.txt
RUN pip install -r requirements.txt -i https://pypi.doubanio.com/simple
CMD ["python","manage.py","runserver","0.0.0.0:8080"]
第三步:把代码提交到git



------------------
第四步:上线人员:在上线机器上,把代码啦下来
git clone https://gitee.com/liuqingzheng/books.git
第五步:构建镜像
docker build -t='django_books' .
第六步:运行容器
docker run -id --name=books -v /root/project/books:/soft -p 8080:8080 django_books:latest
第七步:其它人访问宿主机的8080端口就能看到项目了

---------
第八步:开发人员继续提交代码
第九步:运维人员pull代码,重启容器,用户就可以看到最新的了

重启docker容器即可(第三方依赖变了)--》重写构建镜像,运行容器

十二、Ubuntu图构建redis(跟底层宿主机无关)

第一步:编辑Dockerfile

python 复制代码
vi Dockerfile
# 写入
FROM ubuntu:lunar-20230415
MAINTAINER xxx
WORKDIR /soft
RUN apt-get update && apt-get install wget make build-essential -y
RUN wget https://github.com/redis/redis/archive/7.0.11.tar.gz && tar -xzvf 7.0.11.tar.gz
WORKDIR /soft/redis-7.0.11
RUN make && make install
EXPOSE 6379
CMD ["redis-server","./redis.conf"]

第二步:执行命令构建镜像

python 复制代码
# 构建镜像
docker build -t='ubuntu_redis' .

第三步:查看构建完成的镜像

python 复制代码
docker images
'''
REPOSITORY     TAG              IMAGE ID       CREATED          SIZE
ubuntu_redis   latest           3ef971a3ea96   15 minutes ago   615MB
'''

第四步:镜像运行成容器

python 复制代码
docker run -id --name redis -p 6379:6379 ubuntu_redis

第五步:查看正在运行的容器

python 复制代码
docker ps
'''
CONTAINER ID   IMAGE          COMMAND                   CREATED          STATUS          PORTS                                       NAMES
bce3cd443ae7   ubuntu_redis   "redis-server ./redi..."   9 minutes ago    Up 9 minutes    0.0.0.0:6379->6379/tcp, :::6379->6379/tcp   redis
'''

第六步:进入到容器

python 复制代码
docker exec -it redis /bin/bash
redis-cli  # 连接

十三、docker 私有仓库

python 复制代码
# 有个远程仓库 ,docker官方提供的 ---》我们可以把我们的镜像传上去
# 公司做的镜像,一般不放在远程仓库,公司会自己搭建私有仓库(把公司制作的镜像传到私有仓库)

1、镜像传到官方仓库

python 复制代码
# 第0步:在远端创建仓库
# 第一步:给镜像打标签
	docker tag 086e6b3e71c0 用户名/xiao_books:v1
# 第二步:登录到远程
	docker login
    用户名:不是邮箱
    密码:挺复杂
    
# 第三步:提交
	docker push 用户名/xiao_books:v1
        
# 第四步:别人就可以下载了
	docker pull 用户名/xiao_books:v1

2、镜像分层

python 复制代码
每一个Dockerfile命令都会构建一层镜像(本质上是每一层都会启动一个容器,执行完命令后,将容器进行提交,通过查看下载下来的镜像,发现历史层信息的层ID是missing,其实是因为原本的层id只存在于构建镜像的宿主机上,一旦转移镜像后,历史层消息中将只保留最新一层的ID


# 只要执行一个命令就会多一层
RUN yum install vim -y
RUN yum install git -y


# 查看镜像分层的命令
docker history  用户名/xiao_books:v1
# 好处:
构建快,分发方便,如果本地有某一层了,这一层就不需要下载了


# 补充:Dcokerfile写命令,建议多条命令合为一条---》只会生成一层
RUN python -m pip install --upgrade pip &&\
python -m pip install --upgrade setuptools &&\
pip install -r requirements.txt

3、私有仓库搭建

自己搭建私有仓库分为两种:

(1)无图形化的搭建步骤

python 复制代码
# 搭建步骤:(使用docker搭建docker私有仓库)
	-第一步:拉取镜像 docker pull registry
    -第二步:运行容器:docker run -di --name=registry -p 5000:5000 registry
    	-就是一个web服务端--》从浏览器中访问它
    -第三步:打开浏览器 输入地址http://10.0.0.101:5000/v2/_catalog看到{"repositories":[]} 表示私有仓库搭建成功并且内容为空
    -第四步:修改daemon.json
    vi /etc/docker/daemon.json
    {
       
        "insecure-registries":["10.0.0.101:5000"]
    } 
    
    -第五步:重启docker 让配置生效
    systemctl restart docker
    docker start registry
    
    -第六步:把某个镜像tag成私有仓库的镜像
    docker tag 镜像名字/id 10.0.0.101:5000/django_books:v1
    docker tag django_books:latest 10.0.0.101:5000/django_books:v1
  
    -第七步:提交到私有仓库
    docker push 10.0.0.101:5000/django_books:v1  
            
    -第八步:其他人,只要配置了私有仓库就可以直接拉取
    docker pull 10.0.0.101:5000/django_books:v1

    docker run -id --name=books -v /root/project/books:/soft -p 8080:8080 10.0.0.101:5000/django_books:v1

十四、docker-compose

1、docker-compose

(1)介绍

Docker帮助我们解决服务的打包安装的问题,随着而来的问题就是服务过多的带来如下问题:

  • 多次使用 Dockerfile、Build、Image 命令或者 DockerHub 拉取 Image,所以需要创建多个Container,多次编写启动命令;

那么Container互相依赖的该如何进行管理和编排呢?

当我们服务数量增多的时候,上面的问题就会更加的被放大,如果这个问题不解决,其实从虚拟机到容器化除了机器减少一些浪费以外,好像没有更多的变化。

Docker有没有什么好的方法,可以让我们通过一个配置就搞定容器编排和运行呢?于是有了Docker-Compose,Docker Compose是一个能一次性定义和管理多个Docker容器的工具,(单机容器编排【定义和管理】)。多机容器编排的话,建议使用 k8s 和 docker swarm,但是后者用得不多。

从Docker官网来看,Docker建议就是一个服务一个容器,不要把多个服务放到一个容器中(这种方案可以,但是不建议)。而Docker Compose可以做到以下几点:

① 提供工具用于定义和运行多个docker容器应用;

② 使用yaml文件来配置应用服务(docker-compse.yml);

③ 可以通过一个简单的命令docker-compse up可以按照依赖关系启动所有服务;

④ 可以通过一个简单的命令docker-compose down停止所有服务;

⑤ 当一个服务需要的时候,可以很简单地通过--scale进行扩容。

另外Docker Compose还有以下特征:

更高的可移植性,Docker Compose仅需一个docker-compse up可以完成按照依赖关系启动所有服务,然后使用docker-compose down轻松将其拆解。帮助我们更轻松地部署复杂的应用程序;

单个主机上的多个隔离环境,Compose可以使用项目名称将环境彼此隔离,这带可以在一台计算机上运行同一环境的多个副本,它可以防止不同的项目和服务相互干扰。

(2)使用步骤

​ Docker Compose是一个用来定义和运行复杂应用的Docker工具。一个使用Docker容器的应用,通常由多个容器组成。使用Docker Compose不再需要使用shell脚本来启动容器。

Compose 通过一个配置文件来管理多个Docker容器,在配置文件中,所有的容器通过services来定义,然后使用docker-compose脚本来启动,停止和重启应用,和应用中的服务以及所有依赖服务的容器,非常适合组合使用多个容器进行开发的场景。

Compose 使用的三个步骤:

首先使用 Dockerfile 定义应用程序的环境;

然后使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行;

最后,执行 docker-compose up 命令来启动并运行整个应用程序。

(3)安装docker-compose

bash 复制代码
 # 第一步:上传或者下载文件
 apt install lrzsz
 rz   # 上传文件
 或者
 wget https://github.com/docker/compose/releases/download/v2.15.1/docker-compose-linux-x86_64
 
 # 第二步:copy到系统可执行文件目录下
 cp ./docker-compose /usr/local/bin/docker-compose # 想在任意路径下执行docker-compose都有相应----》需要把可执行文件放到环境变量所在的目录下
 
 # 第三步:给文件加权限
 使用docker-compose发现权限不够,于是使用ls -al查看该文件有哪些权限,
 chmod 777 /usr/local/bin/docker-compose
bash 复制代码
  r--    ---    ---
# rwx    rwx    rwx
  属主   属组    其他
  r:read 读权限 
  w:wirte 写权限
  x :执行权限

 属主   属组  所有人
 chmod 777 文件名
 chmod +x 

rwx  r-x   -wx
111  101   011 
chmod 753 文件名 
# 以后在任意位置敲docker-compose都可以

如果你使用的是centos的话,当使用yum install xxx 发现仓库并没有,这时候就需要epel源了

  • yum install centos仓库下载,发现软件不全
  • epel源 扩展源
    • nginx
    • redis
    • python
    • 。。。

(4)常用命令

bash 复制代码
# 启动管理容器
docker-compose up  # 会自动搜索当前路径下的 docker-compose.yml文件
docker-compose -f 指定文件 up
docker-compose up -d  # 后台执行,一般我们看日志输出,不用这个

docker-compose stop  # 停止,不会删除容器和镜像
docker-compose down # 停止,并删除关联的容器
docker-compose start  # 启动yml文件管理的容器
docker-compose ps    # 正在运行的容器
docker-compose images # docker-compose管理的镜像

docker-compose exec yml文件中写的service /bin/bash  # 进入到容器内

docker-compose up -d --build # 启动容器但是重新构建镜像,基于重新构建的镜像启动

#####  如果你没装docker,需要先安装docker-ce才能使用docker-compose#######
# 配置yum仓库
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

# 下载 docker-ce  docker-ce-cli docker-compose-plugin
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

2、docker-compose 部署flask

首先部署flask需要两个容器:flask项目容器和redis容器,因此我们可以使用docker-compose来管理容器

(1)新建flask项目

python 复制代码
from flask import Flask
from redis import Redis
import os

app = Flask(__name__)
# redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)
redis = Redis(host='redis', port=6379,decode_responses=True) # 容器的主机名---》flask容器和redis容器是能ping通的,可以通过ip ping 也可以通过主机名ping

@app.route('/')
def hello():
    redis.incr('hits')
    return '你好! 查看 %s 次\n' % (redis.get('hits'))


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)

(2)编写Dockerfile--》用于构建flask项目的镜像

python 复制代码
FROM python:3.10
WORKDIR /app
COPY . /app
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
EXPOSE 5000
CMD [ "python", "app.py" ]

# 是否要构建出镜像---》不用,一会统一使用 docker-compose构建

(3)编写docker-compose的配置文件-docker-compose.yml

python 复制代码
version: "3"
services:
  redis:
    image: redis
  web:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 8080:5000
    environment:
      REDIS_HOST: redis
   

(4)一键启动

python 复制代码
docker-compose up


# 如果redis服务的名字叫redis,我在web服务中(容器中),根据redis名字就能拿到容器
	ping redis

    # 进入到了web,ping redis
    # 安装ping命令,
    apt-get update
    apt-get install inetutils-ping
    ping redis

3、docker-compose 一键部署路飞

(1)环境准备

  • 一台服务器

    • python3.10 环境 djagno +uwsgi+代码
    • nginx软件
    • mysql 5.7
    • redis
  • 每个都做成一个容器

    • djagno项目容器:python3.10 构建的django,项目依赖模块,uwsgi,代码

    • nginx容器:目录映射,映射到宿主机,代理vue前端,编译后的静态文件

    • mysql 容器:创建,创用户,密码,luffy库

    • redis 容器,跑起来即可

  • 操作步骤

    • git clone https://gitee.com/xiao01/luffy.git
    • 修改目录结构
    • 修改前端链接后台的地址:
      • 改后端地址
      • 改前端链接后端地址
    • 编译:npm run build
    • 提交到git
    • 要部署的服务器:git clone https://gitee.com/xiao01/luffy.git
    • docker,docker-compose装好
    • docker-compose up 启动
    • 最后访问宿主机的 80 端口

(2)项目目录结构

python 复制代码
luffy
	-docker_compose_files  # nginx有自己的配置文件,redis自己的配置,mysql的配置
        nginx # 文件夹
        	-default.conf  # nginx配置文件
        redis # 文件夹
        	 redis.conf
        mysql.env#配置文件
    -luffy_api  # 原来路飞后端项目
    	-Dockerfile
        -luffy.ini  # luffy.xml uwsgi的配置文件
    -luffycity  # 前端项目
    
    -docker-compose.yml  # docker-compose的配置文件
    

# 把luffycity/dist 文件夹删除
# 把\luffy\luffycity\src\assets\js\settings.js后端地址改成上线地址(服务器地址)
# 来到前端路径下:luffy\luffycity
cnpm install  安装依赖

# 编译,在\luffy\luffycity\dist文件夹
npm run build

# 提交到git上


# 在部署的机器上,git clone 下来
# 进入到项目目录
docker-compose up

(3)luffy_api/Dockerfile--->构建uwsgi+django

python 复制代码
FROM python:3.8
MAINTAINER lqz
WORKDIR /soft
COPY ./requestment.txt /soft/requestment.txt
RUN pip install -r requestment.txt -i https://pypi.doubanio.com/simple
#CMD ["uwsgi", "-x", "./luffy.xml"]
CMD ["uwsgi", "./luffy.ini"]
#CMD ["python", "manage_pro.py", "runserver"]

(4)docker-compose.yml

python 复制代码
version: "3"

services:
  nginx:
    image: nginx
    container_name: luffy_nginx
    ports:
      - "80:80"
      - "8000:8000"
    restart: always
    volumes:
      - ./luffycity/dist:/var/www/html
      - ./docker_compose_files/nginx:/etc/nginx/conf.d
    depends_on:
      - django
    networks:
      - web

  django:
    build:
      context: ./luffy_api
      dockerfile: Dockerfile
    container_name: luffy_django
#    command: python manage_pro.py makemigrations && python manage_pro.py migrate && uwsgi ./luffy.ini
    restart: always
    ports:
      - "8080:8080"
    volumes:
      - ./luffy_api:/soft
    environment:
      - TZ=Asia/Shanghai
    depends_on:
      - mysql
      - redis
    networks:
      - web
  redis:
    image: redis:6.0-alpine
    container_name: luffy_redis
    ports:
      - "6379:6379"
    volumes:
      - ./docker_compose_files/redis/data:/data
      - ./docker_compose_files/redis/redis.conf:/etc/redis/redis.conf
    command: redis-server /etc/redis/redis.conf
    networks:
      - web
  mysql:
    image: mysql:5.7
    container_name: luffy_mysql
    restart: always
    ports:
      - "3306:3306"
    env_file:
      - ./docker_compose_files/mysql.env
    volumes:
      - ./docker_compose_files/mysql/data:/var/lib/mysql
      - ./docker_compose_files/mysql/logs:/var/log/mysql
      - ./docker_compose_files/mysql/conf:/etc/mysql/conf.d
    networks:
      - web

networks:
  web:

(5)一键部署

bash 复制代码
docker-compose up

十五、远程链接linux开发

  • 刚开始是pycharm选择的python解释器

  • 配置连接远端

  • 这里只展示了使用密码链接,在公司也可以使用ssh链接


  • 上传到远端

  • 上传成功会出现提示

  • 远端也能看见了
相关推荐
李昊哲小课1 分钟前
deepin 安装 zookeeper
大数据·运维·zookeeper·debian·hbase
真真-真真18 分钟前
WebXR
linux·运维·服务器
一勺菠萝丶42 分钟前
MongoDB 常用操作指南(Docker 环境下)
数据库·mongodb·docker
Mitch3111 小时前
【漏洞复现】CVE-2015-3337 Arbitrary File Reading
elasticsearch·网络安全·docker·漏洞复现
Mitch3111 小时前
【漏洞复现】CVE-2015-5531 Arbitrary File Reading
web安全·elasticsearch·网络安全·docker·漏洞复现
wanhengidc1 小时前
短视频运营行业该如何选择服务器?
运维·服务器
雨中rain2 小时前
Linux -- 从抢票逻辑理解线程互斥
linux·运维·c++
-KamMinG2 小时前
Centos7.9安装openldap+phpldapadmin+grafana配置LDAP登录最详细步骤 亲测100%能行
运维·grafana
Bessssss2 小时前
centos日志管理,xiao整理
linux·运维·centos
豆是浪个2 小时前
Linux(Centos 7.6)yum源配置
linux·运维·centos