docker 官网:http://www.docker.com
官网文档: https://docs.docker.com/get-docker/
Docker Hub官网:https://hub.docker.com (仓库)
docker 是一个开源的容器化平台,可以将应用程序及其所有依赖项打包在一个独立、可移植的容器中。它通过利用容器技术来实现应用程序的快速部署、可扩展性和跨平台性。
docker 的核心概念是容器,它是一个完全独立、可执行的软件包,包含了应用程序的代码、运行时环境、系统工具和系统库。与虚拟机相比,容器更加轻量级,因为它们共享主机操作系统的内核,并且没有额外的操作系统负担。
使用 docker,开发人员可以将应用程序及其所有依赖项打包在一个容器中,然后将该容器部署到任何支持 docker 的主机上,无论是开发环境、测试环境还是生产环境。容器提供了一致的运行环境,确保应用程序在不同环境中以相同的方式运行。
docker 还提供了一套强大的命令行工具和 API,使得容器的创建、部署、启动、停止和管理变得简单和可靠。它支持容器的版本控制和快速部署,方便应用程序的更新和回滚。
使用 docker,开发人员可以更快速地构建和交付应用程序,运维人员可以更轻松地管理和扩展应用程序的部署。docker 已经成为现代化软件开发和部署的重要工具,被广泛应用于云计算、微服务架构、持续集成和持续部署等领域。
问题:
一款产品从开发到上线,从操作系统,到运行环境,再到应用配置。作为开发+运维之间的协作我们需要关心很多东西,这也是很多互联网公司都不得不面对的问题,特别是各种版本的迭代之后,不同版本环境的兼容,对运维人员是极大的考验!
环境配置如此麻烦,换一台机器,就要重来一次,费力费时。很多人想到,能不能从根本上解决问题,软件可以带环境安装?也就是说,安装的时候,把原始环境一模一样地复制过来。解决开发人员说的“ 在我的机器上可正常工作”的问题。
之前在服务器配置一个应用的运行环境,要安装各种软件,就拿一个基本的工程项目的环境来说吧,Java/Tomcat/MySQL/JDBC 驱动包等。安装和配置这些东西有多麻烦就不说了,它还不能跨平台。假如我们是在 Windows 上安装的这些环境,到了 Linux 又得重新装。况且就算不跨操作系统,换另一台同样操作系统的服务器,要移植应用也是非常麻烦的。
传统上认为,软件编码开发/测试结束后,所产出的成果即是程序或是能够编译执行的二进制字节码文件等(Java 为例)。而为了让这些程序可以顺利执行,开发团队也得准备完整的部署文件,让维运团队得以部署应用程式,开发需要清楚的告诉运维部署团队,用的全部配置文件+所有软件环境。不过,即便如此,仍然常常发生部署失败的状况。
解决方案:
docker 之所以发展如此迅速,也是因为它对此给出了一个标准化的解决方案。
docker 镜像的设计,使得 docker 得以打破过去「程序即应用」的观念。通过 docker 镜像 ( images ) 将应用程序所需要的系统环境,由下而上打包,达到应用程序跨平台间的无缝接轨运作。
第一个概念:docker 里面所有的应用,打包为镜像。版本迭代管理…
docker 的思想来自于集装箱,集装箱解决了什么问题?在一艘大船上,可以把货物规整的摆放起来。并且各种各样的(docker 镜像容器等都是标准化)货物被集装箱标准化了,集装箱和集装箱(docker 容器)之间不会互相影响。那么我就不需要专门运送水果的船和专门运送化学品的船了。只要这些货物在集装箱里封装的好好的,那我就可以用一艘大船把他们都运走。
docker 就是类似的理念。
- 镜像标准化
- 容器化隔离
2010年,几个搞IT的年轻人,在美国旧金山成立了一家名叫“dotCloud”的公司。
这家公司主要提供基于PaaS的云计算技术服务。具体来说,是和LXC有关的容器技术。
后来,dotCloud 公司将自己的容器技术进行了简化和标准化,并命名为—— docker。
docker 技术诞生之后,并没有引起行业的关注。而 dotCloud 公司,作为一家小型创业企业,在激烈的竞争之下,也步履维艰。
正当他们快要坚持不下去的时候,脑子里蹦出了“开源”的想法。
什么是“开源”?开源,就是开放源代码。也就是将原来内部保密的程序源代码开放给所有人,然后让大家一起参与进来,贡献代码和意见。
有的软件是一开始就开源的。也有的软件,是混不下去,创造者又不想放弃,所以选择开源。自己养不活,就吃“百家饭”嘛。
2013年3月,dotCloud 公司的创始人之一,docker 之父,28岁的 Solomon Hykes 正式决定,将 docker 项目开源。
不开则已,一开惊人。
越来越多的 IT工程师发现了 docker 的优点,然后蜂拥而至,加入 docker 开源社区。
docker 的人气迅速攀升,速度之快,令人瞠目结舌。
开源当月,docker 0.1 版本发布。此后的每一个月,docker 都会发布一个版本。到2014年6月9日,docker 1.0 版本正式发布。
此时的 docker,已经成为行业里人气最火爆的开源技术,没有之一。甚至像 Google、微软、Amazon、VMware 这样的巨头,都对它青睐有加,表示将全力支持。
软件技术革命从来都是懒人推动的。
docker 和容器技术为什么会这么火爆?说白了,就是因为它“轻”。
重量级的环境隔离:虚拟机
在容器技术之前,业界的网红是虚拟机。虚拟机技术的代表,是 VMWare和 OpenStack。
相信很多人都用过虚拟机。虚拟机,就是在你的操作系统里面,装一个软件,然后通过这个软件,再模拟一台甚至多台“子电脑”出来。
在“子电脑”里,你可以和正常电脑一样运行程序,例如开QQ。如果你愿意,你可以变出好几个“子电脑”,里面都开上QQ。“子电脑”和“子电脑”之间,是相互隔离的,互不影响。
虚拟机属于虚拟化技术。而 docker 这样的容器技术,也是虚拟化技术,属于轻量级的虚拟化。
虚拟机虽然可以隔离出很多“子电脑”,但占用空间更大,启动更慢,虚拟机软件可能还要花钱(例如 VMWare)。
而容器技术恰好没有这些缺点。它不需要虚拟出整个操作系统,只需要虚拟一个小规模的环境(类似“沙箱”)。
它启动时间很快,几秒钟就能完成。而且,它对资源的利用率很高(一台主机可以同时运行几千个 docker 容器)。此外,它占的空间很小,虚拟机一般要几GB到几十GB的空间,而容器只需要MB级甚至KB级。
正因为如此,容器技术受到了热烈的欢迎和追捧,发展迅速。
docker 是基于 Go 语言实现的云开源项目。
docker 的主要目标是 “Build,Ship and Run Any App , Anywhere”,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的APP(可以是一个 WEB 应用或数据库应用等等)及其运行环境能够做到“一次封装,到处运行”。
Linux 容器技术的出现就解决了这样一个问题,而 docker 就是在它的基础上发展过来的。将应用运行在 docker 容器上面,而 docker 容器在任何操作系统上都是一致的,这就实现了跨平台、跨服务器。只需要一次配置好环境,换到别的机子上就可以一键部署好,大大简化了操作。
之前的虚拟机技术
虚拟机(virtual machine)就是带环境安装的一种解决方案。
它可以在一种操作系统里面运行另一种操作系统,比如在 Windows 系统里面运行 Linux 系统。应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。这类虚拟机完美的运行了另一套系统,能够使应用程序,操作系统和硬件三者之间的逻辑不变。
虚拟机的缺点:
-
资源占用多
-
冗余步骤多
-
启动慢
容器虚拟化技术
由于前面虚拟机存在这些缺点,Linux 发展出了另一种虚拟化技术:Linux 容器(Linux Containers,缩写为 LXC)。
Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。有了容器,就可以将软件运行所需的所有资源打包到一个隔离的容器中。容器与虚拟机不同,不需要捆绑一整套操作系统,只需要软件工作所需的库资源和设置。系统因此而变得高效轻量并保证部署在任何环境中的软件都能始终如一地运行。
比较了 docker 和传统虚拟化方式的不同之处:
- 传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;
- 而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。
- 每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。
虚拟机与容器的对比
docker是怎么工作的
docker 是一个 Client-Server 结构的系统,docker 守护进程运行在主机上, 然后通过 socket 连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。 容器,是一个运行时环境,就是我们前面说到的集装箱。
为什么Docker比较 VM 快
- docker 有着比虚拟机更少的抽象层。由于 docker 不需要 Hypervisor 实现硬件资源虚拟化,运行在 docker 容器上的程序直接使用的都是实际物理机的硬件资源。因此在 CPU、内存利用率上 docker 将会在效率上有明显优势。
- docker 利用的是宿主机的内核,而不需要 Guest OS。因此,当新建一个容器时,docker 不需要和虚拟机一样重新加载一个操作系统内核。仍而避免引寻、加载操作系统内核返个比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载 Guest OS,返个新建过程是分钟级别的。而docker 由于直接利用宿主机的操作系统,则省略了返个过程,因此新建一个 docker 容器只需要几秒钟。
更快速的应用交付和部署:
传统的应用开发完成后,需要提供一堆安装程序和配置说明文档,安装部署后需根据配置文档进行繁杂的配置才能正常运行。docker 化之后只需要交付少量容器镜像文件,在正式生产环境加载镜像并运行即可,应用安装配置在镜像里已经内置好,大大节省部署配置和测试验证时间。
更便捷的升级和扩缩容:
随着微服务架构和 docker 的发展,大量的应用会通过微服务方式架构,应用的开发构建将变成搭乐高积木一样,每个 docker 容器将变成一块“积木”,应用的升级将变得非常容易。当现有的容器不足以支撑业务处理时,可通过镜像运行新的容器进行快速扩容,使应用系统的扩容从原先的天级变成分钟级甚至秒级。
更简单的系统运维:
应用容器化运行后,生产环境运行的应用可与开发、测试环境的应用高度一致,容器会将应用程序相关的环境和状态完全封装起来,不会因为底层基础架构和操作系统的不一致性给应用带来影响,产生新的 BUG。当出现程序异常时,也可以通过测试环境的相同容器进行快速定位和修复。
更高效的计算资源利用:
docker 是内核级虚拟化,其不像传统的虚拟化技术一样需要额外的 Hypervisor [管理程序] 支持,所以在一台物理机上可以运行很多个容器实例,可大大提升物理服务器的 CPU 和内存的利用率。
docker 具有以下几个主要的优点:
- 轻量级和快速:相比传统虚拟化技术,docker 容器更为轻量级,因为它们共享主机操作系统的内核,避免了额外的操作系统负担。这使得容器的启动、停止和迁移更加快速,也节约了硬件资源和时间成本。
- 可移植性和一致性:docker 容器提供了一种统一的部署环境,可以在不同的操作系统和硬件平台上运行。开发人员可以在其本地开发环境中构建容器,然后将其部署到测试环境、生产环境或云平台上,而无需担心环境差异导致的应用程序问题。这种可移植性确保了应用程序在不同环境中以相同的方式运行。
- 高效的资源利用:docker 容器可以在同一主机上运行多个相互隔离的容器,共享主机的操作系统和硬件资源。这使得容器可以更好地利用主机资源,提高了资源利用率。
- 简化部署和管理:docker 提供了一套强大的命令行工具和 API,使得容器的创建、部署、启动、停止和管理变得简单和可靠。容器可以通过复制和共享镜像来快速创建多个相同的实例,实现快速部署和扩展。docker 还支持容器的版本控制和快速部署,方便应用程序的更新和回滚。
- 提高开发效率:docker 容器通过将应用程序及其所有依赖项打包在一个容器中,简化了开发环境的搭建和配置过程。开发人员可以在容器中构建、测试和调试应用程序,减少了开发环境之间的不一致性和冲突。
总的来说,docker 的优点包括轻量级、快速、可移植性、一致性、高效的资源利用和简化的部署和管理。它提供了一种现代化的应用程序开发、交付和运行方式,已经被广泛应用于云计算、微服务架构、持续集成和持续部署等领域。
docker 在许多不同的应用场景中都有广泛的应用,下面列举了一些主要的应用场景:
- 应用程序的快速交付和部署:docker 可以将应用程序及其所有依赖项打包在一个容器中,实现应用程序的快速交付和部署。开发人员可以在其本地开发环境中构建容器,然后将其部署到测试环境、生产环境或云平台上,无需担心环境差异导致的应用程序问题。
- 微服务架构:docker 容器非常适合构建和管理微服务架构。每个微服务可以被打包在一个独立的容器中,并且可以独立部署、扩展和管理。这样可以实现服务之间的解耦和灵活的水平扩展,同时简化了部署和维护的复杂性。
- 持续集成和持续部署:docker 可以与持续集成和持续部署工具集成,实现自动化的构建、测试和部署流程。开发人员可以使用 docker 容器来创建一致的开发和测试环境,并且可以在不同的环境中快速部署和测试应用程序。
- 多租户环境:docker 的容器技术可以实现资源的隔离和安全性,使得在多租户环境下更容易管理和部署应用程序。每个租户可以被分配一个独立的容器,可以在同一主机上运行多个容器实例,提高了资源利用率。
- 快速搭建开发环境:docker 可以帮助开发人员快速搭建开发环境,而无需手动配置和安装依赖项。开发人员可以使用预先配置的 docker 镜像,快速创建包含所需开发工具和库的开发环境。
- 跨平台开发和测试:docker 容器可以在不同的操作系统和硬件平台上运行,提供了一种统一的部署环境。这使得开发人员可以在本地开发环境中构建和测试应用程序,并将其部署到不同的目标平台上,而无需进行额外的修改和配置。
总的来说,docker 的应用场景非常广泛,可以用于快速交付和部署应用程序、构建微服务架构、实现持续集成和持续部署、管理多租户环境,以及快速搭建开发环境和跨平台开发和测试等。它已经成为现代化软件开发和部署的重要工具。
docker 的三大必要概念——镜像、容器、仓库
docker 架构图
镜像(image):模版。(web项目:1、环境 2、配置变量 3、上线项目 4、配置项目需要的静态文件)打包成镜像
容器(container):通过镜像来启动运行时容器,就是我们自己封装部署的东西(项目、环境、日志…)
仓库(repository):私有仓库(公司内部)、公有仓库(docker hub,需要配置镜像加速)
小结:
需要正确的理解仓库/镜像/容器这几个概念 :
- image:文件生成的容器实例,本身也是一个文件,称为镜像文件。
- 一个容器运行一种服务,当我们需要的时候,就可以通过 docker 客户端用镜像创建一个对应的运行实例,也就是我们的容器。
- 至于仓库,就是放了一堆镜像的地方,我们可以把镜像发布到仓库中,需要的时候从仓库中拉下来就可以了。那么我就不需要专门运送水果的船和专门运送化学品的船了。只要这些货物在集装箱里封装的好好的,那我就可以用一艘大船把他们都运走。
docker就是类似的理念。
本次使用的是云服务器,版本是 centos,要求版本在3.10以上
- 官方安装参考手册:https://docs.docker.com/engine/install/centos/
- 保证环境是满足要求的
- 卸载以前旧的 docker
- 安装 docker 需要的仓库地址配置
- 安装 docker
- 查看 docker 是否安装成功
- 启动docker
- 下载并运行 hello-world 镜像
出现这个证明我们 docker 已经启动成功了
如果以后想要卸载 docker,执行以下命令
在阿里云工作台中搜索容器镜像服务 ACR,每个人的镜像加速器都是不同的,执行以下命令即可
docker run 镜像名称
- 寻找镜像(如果本地存在,则通过镜像启动容器,不存在,去公开仓库 dockerhub 寻找镜像)
- 下载镜像(如果公开仓库 dockerhub 存在这个镜像,拉取到本地,然后执行,不存在,就直接报错)
下载一个不存在的镜像
查看已经本地下载好的镜像
帮助命令(–help),linux必须要会看帮助文档
可以继续查看其它命令的帮助文档
展示所有的镜像
参数:
- :等价于,显示所有的镜像,包括中间层镜像
默认情况下,命令只显示顶层镜像,即那些没有被其他镜像所依赖的镜像。而使用参数,会显示所有的镜像,包括中间层镜像。中间层镜像是构建镜像过程中生成的临时镜像,它们可能被其他镜像所依赖。
- :等价于,只展示镜像的 id
搜索镜像
参数:
- :等价于,根据条件搜索想要的镜像
拉取镜像
删除镜像
这里删除失败是因为 hello-world 镜像有容器正在运行,如果要删除只能强制删除
参数:
- :等价于,强制删除镜像,即使有容器正在运行
这里镜像ID不一定要是完整的,只要有唯一的一个镜像ID开头满足你输入的ID即可
删除所有镜像,慎用
重新拉取几个镜像进行测试
删除命令如下:
有镜像才能创建容器,我们这里使用 centos 的镜像来测试
根据镜像创建并运行一个容器
参数:
- :为容器指定一个名称,不指定则随机一个名字
- :等价于,后台启动容器并打印容器id
- :等价于,让容器用交互的方式启动
- :等价于,给容器分配一个伪终端,例如
- :等价于,指定端口映射(主机访问的端口:容器端口)
- :大写P,等价于,将所有公开的端口发布到随机端口
用交互的方式启动容器,并进入容器内部
退出容器
查看正在运行中的容器
参数:
- :等价于,显示所有容器,包括已经停止的
- :等价于,只展示容器ID
容器的启动、重启、停止命令
和区别:
命令会向容器发送一个优雅的停止信号(SIGTERM),让容器有机会进行清理和停止。容器将会接收到该信号并尝试优雅地停止运行中的进程。如果容器在一定时间内没有停止,docker 将会发送一个强制停止信号(SIGKILL)来强制终止容器。这个命令给容器一个正常停止的机会,并且容器可以执行一些清理操作,如保存数据、关闭连接等。
命令会立即向容器发送一个强制终止信号(SIGKILL),不给容器进行任何清理操作的机会。容器将会立即停止,正在运行的进程将会被强制中断。这个命令是一种强制终止容器的方式,适用于需要立即停止容器的情况。
删除容器
参数:
- :等价于,强制删除容器
以后台方式启动容器 -d
以后台方式启动容器,查看正在运行时的容器发现没有刚刚启动的容器,这是因为这个镜像 centos 启动的容器里并没有前台进程,所以刚启动一下子就停止了,如果想查询到这个容器,需要加上参数
可以使用参数以交互方式启动 centos,这样就有了一个前台进程,容器就不会停止了
查看日志
参数:
- :等价于,打印时间戳
- :等价于,打印最新日志并继续输出
- :等价于,从日志末尾输出的行数
这里我们启动一个可以输出日志的容器
查看容器相关的进程(top)
查看容器的元数据(inspect)
进入一个正在进行的容器
区别:
- :命令用于在正在运行的容器中执行一个新的命令。它会创建一个新的进程,并在容器中执行指定的命令。该命令会在容器的新进程中执行,不会影响容器原有的主进程。使用可以在容器内部执行命令、进入容器的交互式终端,并且可以在后台运行的容器中执行任务。
- :命令用于连接到正在运行的容器的标准输入(stdin)、输出(stdout)和错误输出(stderr)。该命令会将你的终端会话附加到容器的主进程上,并将容器的输出直接显示在你的终端上。使用可以实时查看和参与到容器内部正在运行的进程中,但是当你退出终端会话时,容器将会停止运行。
拷贝容器内的文件到主机上
常用命令:
这样就完成 nginx 的安装
也可以在外部浏览器访问,输入地址即可访问,如果无法访问说明没有配置安全组,需要在安全组中把3500端口开放
最常用的工具是 portainer
portainer 是一个开源的容器管理平台,它提供了一个简单易用的用户界面,用于管理和监控 docker 容器集群。通过 portainer,用户可以轻松地进行容器的部署、启动、停止、监控和管理等操作,而无需使用复杂的命令行工具。
portainer 支持多种操作系统和容器平台,包括 docker、kubernetes、swarm等,使用户能够在不同的环境中管理和操作容器。它提供了直观的用户界面和可视化的操作方式,使用户能够更加方便地管理和监控容器的状态、日志和资源使用情况。
总之,portainer 是一个功能强大的容器管理平台,可以帮助用户更好地管理和操作 docker 容器集群。
安装命令如下:
安装完成后,浏览器访问:,注意设置阿里云安全组
得到这个页面,随意设置密码即可
选择本地连接即可
在这里就可以查看到当前 docker 的所有信息啦
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
别人给我们生成好的一个环境,或者项目都可以打包成一个镜像
这里我们下载一个 redis 镜像
这里我们可以看到,下载镜像并不是下载一个完整的包,而是分层进行下载,这些层最后组合成了完整的 redis 镜像
我们可以使用来查看镜像分层的详细信息
在最后几行可以看到:
理解:
所有的 docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子,假如基于 Ubuntu Linux 16.04 创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 python 包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
一步步逐层叠加,最后形成完整的镜像
该镜像当前已经包含 3 个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。
在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含 3 个文件,而镜像包含了来自两个镜像层的 6 个文件。
上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。
下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有 6 个文件,这是因为最上层中的文件 7 是文件 5 的一个更新版本。
这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。
docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
Linux 上可用的存储引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。顾名思义,每种存储引擎都基于 Linux 中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
docker 在 Windows 上仅支持 windowsfilter 一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分层和 CoW[1]。
下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。
UnionFS (联合文件系统)
UnionFS(联合文件系统):Union 文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
docker 镜像加载原理
docker 的镜像实际上由一层一层的文件系统组成,这种层级的文件系统 UnionFS。
bootfs(boot file system)主要包含 bootloader 和 kernel,bootloader 主要是引导加载 kernel,Linux 刚启动时会加载 bootfs 文件系统,在docker 镜像的最底层是 bootfs。这一层与我们典型的 Linux/Unix 系统是一样的,包含 boot 加载器和内核。当 boot 加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs 转交给内核,此时系统也会卸载 bootfs。
rootfs(root file system),在 bootfs 之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs 就是各种不同的操作系统发行版,比如 Ubuntu,centos 等等。
平时我们安装进虚拟机的 centos 都是好几个G,为什么 docker 这里才200M?
这是因为对于一个精简的 OS,rootfs 可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用 Host 的 kernel,自己只需要提供 rootfs 就可以了。由此可见对于不同的 linux 发行版,bootfs 基本是一致的,rootfs 会有差别, 因此不同的发行版可以公用 bootfs。
提交容器的副本,让这个容器产生一个新的镜像
参数:
-
:等价于,作者信息(例如:John Hannibal Smith hannibal@a-team.com)
-
:等价于,提交的信息
这里我们根据 redis 镜像创建一个容器,进行修改,然后再用修改后的容器打包成一个新的镜像
这里我们可以看到,新打包的镜像多了一层
对比原来 redis 镜像的分层
可以很明显的看到新的镜像分层多了一层
所以我们可以了解到当创建一个新的镜像时,docker 会基于已有的镜像进行修改和扩展。每个修改操作都会生成一个新的层,并且这些层是按照顺序进行组织的,形成一个层次结构。每个层都只包含了与前一层的差异,这样可以节省存储空间,并且提高镜像的构建效率。
docker 镜像的分层机制带来了以下几个优点:
- 空间效率:由于 docker 镜像的每个层都只包含与前一层的差异,相同的层可以在多个镜像之间共享和重用。这样可以节省存储空间,尤其在使用大量镜像时非常显著。只需存储每个层的差异,而不是整个镜像,大大减少了磁盘占用。
- 构建效率:在构建镜像时,只需要对修改的部分创建新的层,而不需要重新复制整个镜像。这样可以大大加快镜像的构建速度,尤其当镜像层次结构复杂且包含大量文件时,效果更为明显。
- 可维护性:通过分层机制,docker 镜像的每个层都是只读的,不可修改。这意味着镜像的不同版本可以共享相同的底层层,只需在最上层添加新的层来表示不同的版本或修改。这样可以简化镜像的维护和更新过程,提高可维护性。
- 可重用性:由于镜像的每个层都可以在多个镜像之间共享和重用,可以更好地利用已有的层来构建新的镜像。这样可以提高镜像的可重用性,减少重复工作,同时也方便了镜像的分发和共享。
- 容器隔离性:通过每个容器都有自己的可写层,docker 可以实现容器之间的隔离性。每个容器可以独立地修改和管理自己的文件系统,而不会对其他容器或原始镜像的层产生影响。这样可以确保容器的独立性和安全性。
综上所述,docker 镜像的分层机制带来了空间效率、构建效率、可维护性、可重用性和容器隔离性等多个方面的优点,使得 docker 在容器化应用的开发和部署中具有高效性和灵活性。
docker的理念回顾:
将应用和运行的环境打包形成容器运行,运行可以伴随着容器,但是我们对于数据的要求,是希望能够持久化的!
就好比,你安装一个 MySQL,结果你把容器删了,就相当于删库跑路了,这TM也太扯了吧!
所以我们希望容器之间有可能可以共享数据,docker 容器产生的数据,如果不通过 docker commit 生成新的镜像,使得数据作为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了!这样是行不通的!
为了能保存数据在 docker 中我们就可以使用卷!让数据挂载到我们本地!这样数据就不会因为容器删除而丢失了!
作用:
卷就是目录或者文件,存在一个或者多个容器中,由 docker 挂载到容器,但不属于联合文件系统,因此能够绕过 Union File System , 提供一些用于持续存储或共享数据的特性:
卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此 docker不会在容器删除时删除其挂载的数据卷。
特点:
-
持久性:容器数据卷可以在容器的生命周期中保留数据。即使容器被删除或重新创建,数据卷仍然存在,可以被其他容器继续使用。
-
共享性:容器数据卷可以被多个容器同时挂载和使用,实现容器之间的数据共享。这样可以方便地实现容器间的数据传递和共享。
-
独立性:容器数据卷是独立于容器的,它可以存在于容器之外。这意味着即使容器被删除,数据卷仍然保留在主机上,可以被其他容器或主机访问和使用。
所以:总结一句话: 就是容器的持久化,以及容器间的继承和数据共享!
可以使用创建一个容器数据卷,也可以在执行时添加(等价于)参数使用数据卷(推荐)
首先删除所有镜像和容器进行测试
执行以下命令
下载完毕后我们进入服务器的 home 目录下
可以看到, home 目录下多了一个 test 目录
我们再进入到容器的 root 目录下
可以看到同样多了一个 test 目录,这说明挂载了数据卷,自动创建对应的文件夹
接下来,在容器的 test 目录下创建一个文件
看一看服务器的 test 目录
可以看到 test 目录下多了个 文件
再在服务器的 test 目录下创建一个文件
看一看容器的 test 目录
可以看到 test 目录下多了 文件,这说明两边的目录完全共通,都可以进行读写操作
可以查看一下容器的元数据,里面有一段:
删除容器
查看服务器的 test 目录下的数据还在不在?
可以看到数据依然存在
重新运行一个容器进行挂载数据卷
可以看到数据没有丢失
容器数据卷是非常适合于 mysql 的,通过将 mysql 的数据挂载到本地服务器上,即时 mysql 宕机了或者删除了,数据也不会丢失
使用以下命令安装 mysql
安装完成后,进入服务器的 目录下
可以看到有 conf、data 两个目录,进入到 data 目录下
可以看到跟我们在 windows 系统下安装的 mysql 目录一致
我们在外部使用 navicat 连接一下这个数据库
主机就是服务器的 ip 地址,密码为123456
接下来我们创建一个数据库
可以看到数据库的数据已经保存在了本地上
这样即使你的 mysql 容器宕机导致数据丢失了,本地的数据也不会消失
匿名挂载
匿名挂载,顾名思义,在挂载数据卷时没有指定主机的挂载目录,后只有容器内路径
首先我们使用来查看已经拥有的数据卷
接下来我们使用匿名挂载创建一个容器
可以看到数据卷多了一个
我们可以查看一下这个数据卷的信息
可以看到默认情况,会挂载到本地的这个目录下
匿名挂载适用于临时存储或者不需要在多个容器之间共享的数据。例如,可以将日志文件、临时文件或其他容器产生的数据挂载到主机上的特定目录,以便于查看和处理。
需要注意的是,由于匿名挂载是直接指定主机上的路径,所以在不同主机上挂载相同路径的容器可能会导致冲突或数据不一致。因此,在使用匿名挂载时,需要确保主机路径的唯一性和正确性。
在使用 dockerfile 构建镜像时,通过 VOLUME 保留字挂载数据卷就是使用匿名挂载,不会出现忘记挂载目录而导致数据丢失的情况
具名挂载
具名挂载,顾名思义,就是在挂载数据卷时指定了数据卷的名字,为了可以在多个容器中共享重要的数据
可以看到数据卷中多了一个名字为 centosdir 的数据卷,查看一下它的信息
具名挂载提供了一种方便和灵活的方式来管理容器的数据。它可以在多个容器之间共享和重用数据,使容器之间的数据交互更加简单和高效。同时,具名挂载由 docker 自动管理,减轻了手动管理数据的负担。
容器数据卷:容器的持久化
数据卷容器:容器,当做一个持久化的卷。
数据卷容器(Data Volume Container)是一种在 docker 中用于管理和共享数据的特殊容器。它是一种轻量级的容器,主要用于创建和管理数据卷,而不运行实际的应用程序。
数据卷容器的工作原理如下:
- 创建数据卷容器:首先,创建一个专门用于管理数据的容器,称为数据卷容器。可以使用 命令创建一个数据卷容器。
- 挂载数据卷:然后,在其他容器中使用 参数来挂载数据卷容器中的数据卷。这样,其他容器就可以访问和共享数据卷容器中的数据。
- 管理数据卷:数据卷容器可以使用 命令启动和停止,或者使用 和 命令进行管理。通过管理数据卷容器,可以管理和保持数据卷的持久性。
数据卷容器的主要优点如下:
- 数据共享:数据卷容器允许多个容器访问和共享相同的数据卷。它提供了一种简单且可靠的方式来管理和共享数据。
- 数据持久性:通过使用数据卷容器,数据卷的生命周期不再依赖于任何特定的容器。即使容器被删除或重新创建,数据卷仍然存在。
- 简化管理:通过将数据卷的管理和持久性交给数据卷容器,可以简化数据的管理和维护。容器的启动和停止不会影响数据卷的存在。
- 数据版本控制:数据卷容器可以用于管理和保存不同版本的数据。通过创建不同的数据卷容器,可以保存不同时间点的数据快照。
需要注意的是,数据卷容器是一种较早的数据管理方法,现在也有更灵活的数据管理方式,如使用具名挂载(Named Volume)或使用 docker 卷插件。这些方法提供了更多的功能和性能,因此在选择数据管理方式时需要根据实际需求进行选择。
接下来进行测试:
首先删除所有的数据卷和容器
运行容器 centos01,使用匿名挂载
查看所有数据卷
接下来,运行容器 centos02,使用 挂载 centos01 的数据卷
可以看到 centos02 中也存在 test 目录
再次查看所有数据卷
发现数据卷没有增加
这时候在 centos01 和 centos02 的 test 目录下进行测试,发现二者是完全共通的,这就是数据卷容器,类似于 java 中的继承,这里是 centos02 继承了 centos01 的数据卷,二者达成共通
那么在多个相同的容器中,如果想要共享数据,使用数据卷容器,将容器作为一个父数据卷,其他容器来挂载到我这个父卷下,就可以实现共享了
可以再多增加几个容器进行测试,删除父容器查看其余子容器是否共通,自行测试即可,最后可以得出结论:
容器之间配置信息的传递,数据卷的生命周期会一直持续到没有容器使用它为止。
存储在本机的文件则会一直保留!
大家想想,Nginx,tomcat,mysql 这些镜像都是哪里来的?官方能写,我们不能写吗?
我们要研究自己如何做一个镜像,而且我们写的微服务项目打包上云部署,docker 就是最方便的。
微服务打包成镜像,任何装了 docker 的地方,都可以下载使用,极其方便。
流程:开发应用 => 编写 dockerfile => 打包为镜像 => 上传到仓库(私有仓库公司内部,公有仓库 dockerhub)=> 下载镜像 => 启动运行。
还可以方便移植!
dockerfile 是一种用于定义和构建 docker 镜像的文本文件。它包含一系列的指令和参数,用于描述镜像的构建过程,包括基础映像、软件包安装、文件拷贝、环境变量设置等。
通过编写 dockerfile,可以将应用程序、环境和依赖项打包成一个独立的容器镜像,使其可以在不同的环境和平台上运行,实现应用程序的可移植性和可扩展性。
dockerfile 的基本结构包括以下几个部分:
- 基础映像(Base Image):使用 FROM 指令指定基础映像,作为构建镜像的起点。基础映像通常包含了操作系统和一些预装的软件和工具。
- 构建过程指令:使用一系列指令来描述构建过程,例如 RUN 用于执行命令和安装软件包,COPY 用于拷贝文件和目录,ADD 用于拷贝和提取文件,WORKDIR 用于设置工作目录,等等。
- 容器启动指令:使用 CMD 或 ENTRYPOINT 指令来定义容器启动时要执行的命令,也就是默认的容器执行命令。
通过编写 dockerfile,可以自定义构建过程,选择所需的软件和配置,以及设置环境变量、暴露端口等。dockerfile 的语法简单且易于理解,使得镜像的构建过程变得可重复和可维护。
总的来说,dockerfile 是定义和构建 docker 镜像的文本文件,通过编写指令和参数来描述镜像的构建过程和配置,以实现应用程序的打包和部署。它是使用 docker 进行容器化开发和部署的重要工具。
构建步骤:
- 编写 dockerfile 文件
- docker build 构建镜像
- docker run 镜像
基础知识:
- 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
- 指令按照从上到下,顺序执行
- 表示注释
- 每条指令都会创建一个新的镜像层,并对镜像进行提交
流程:
- docker 从基础镜像运行一个容器
- 执行一条指令并对容器做出修改
- 执行类似 docker commit 的操作提交一个新的镜像层
- docker 再基于刚提交的镜像运行一个新容器
- 执行 dockerfile 中的下一条指令直到所有指令都执行完成!
说明:
从应用软件的角度来看,dockerfile,docker 镜像与 docker 容器分别代表软件的三个不同阶段。
- dockerfile 是软件的原材料(代码)
- docker 镜像则是软件的交付品(.apk)
- docker 容器则是软件的运行状态(客户下载安装执行)
dockerfile 面向开发,docker 镜像成为交付标准,docker 容器则涉及部署与运维,三者缺一不可!
- dockerfile:需要定义一个 dockerfile,dockerfile 定义了进程需要的一切东西。dockerfile 涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当引用进行需要和系统服务和内核进程打交道,这时需要考虑如何设计 namespace 的权限控制)等等。
- docker镜像:在 dockerfile 定义了一个文件之后,docker build 时会产生一个 docker 镜像,当运行 docker 镜像时,会真正开始提供服务;
- docker容器:容器是直接提供服务的。
关键字:
dockerhub 中99%的镜像都是通过在 base 镜像(Scratch)中安装和配置需要的软件构建出来的
Scratch 镜像很赞,它简洁、小巧而且快速,它没有 bug、安全漏洞、延缓的代码或技术债务。除了被 docker 添加了 metadata 之外,它基本上是空的。
我们在使用 dockerfile 构建 docker 镜像时,一种方式是使用官方预先配置好的容器镜像。优点是我们不用从头开始构建,节省了很多工作量,但付出的代价是需要下载很大的镜像包。
如果我们的需求是在构建一个符合我们实际业务需求的 docker 镜像的前提下,确保镜像尺寸尽可能的小,应该怎么做呢?
思路是使用空镜像 scratch,可以说是真正的从零开始构建属于自己的镜像,镜像的第一层
发布一个自己编写的 centos
由于阿里云官方的 centos 是不完整的,很多命令都没有(例如 vim、ipconfig 等),我们自定义一个 centos 镜像,,让它能够拥有这些命令
编写 dockerfile 如下:
由于最新版 centos8 有 bug,故使用 centos7.9版本
根据 dockerfile 构建镜像
参数:
- :等价于,指定 dockerfile 文件
- :等价于,指定输出的镜像文件名:版本号
命令最后一定要加一个
根据这个镜像运行容器后发现并没有打印出目录和,这是因为 CMD 指令如果存在多个,只有最后一个会被执行
查看镜像的变更历史
如果你下载了一个镜像,报错了或者你想查看一些构建逻辑,使用
项目中编写 dockerfile 思路
- 基于一个空的镜像
- 下载需要的环境 ADD
- 执行环境变量的配置 ENV
- 执行一些Linux命令 RUN
- 日志 CMD
- 端口暴露 EXPOSE
- 挂载数据卷 VOLUMES
这个过程就是你手动部署项目的过程,你通过 docker 可以再未来实现自动化构建。
两个命令都是指定一个容器启动时要运行的命令,但二者有很大的区别
-
:容器内有多个 CMD 指令时,只有最后一个 CMD 指令会生效,而如果在执行命令时携带了其它命令,将会覆盖掉所有 dockerfile 的 CMD 指令
-
:ENTRYPOINT 的命令不容易被覆盖。在命令中提供的任何参数都会作为 ENTRYPOINT 命令的参数传递。
当两者组合使用时:那么 CMD 将作为 ENTRYPOINT 的默认参数,如果在命令中提供了参数,它将覆盖 CMD 并作为 ENTRYPOINT 的参数传递。
例如:
运行容器时,可以覆盖默认的 CMD:
结果不会打印出
使用 ENTRYPOINT 指令:
运行容器时,可以传递参数给 ENTRYPOINT:
使用空镜像从零构建一个完整的 tomcat
一般一个项目都在一个文件夹中,我们只需要在项目目录下编辑一个 Dockerfile 文件即可
当执行指定时如果没有参数指定 dockerfile 文件,会默认寻找项目目录下的 来构建镜像,所以我们名字通常设定为
准备工作:准备 tomcat 和 jdk 的 jar 包,创建文件,以及一个任意内容的即可
编辑,内容如下:
构建并运行:
运行成功后打开浏览器,输入,即可访问到 tomcat 主页
在我们自定义的 tomcat 服务器中上传一个项目,在本地挂载目录,丢一个项目上去。
首先进入到我们挂载的宿主机目录下下
在 test 目录下丢项目即可
示例:编写一个
浏览器访问
公有仓库:DockerHub
目前 DockerHub 网址无法访问,了解即可
注册dockerhub https://hub.docker.com/signup,需要有一个账号
发布镜像遵循以下几个步骤:
- 登录用户:
参数:
- :等价于,登录所需的用户名
- :等价于,密码
- 给要上传的镜像打上标签
- 上传镜像
私有仓库,一般都是公司内部自行搭建的,步骤跟上述相同
准备工作:清空所有镜像和容器
查看本地网络
-
大型项目微服务(一个服务对应一个容器)这么多,要怎么互相访问?如果通过 ip 来访问,但是当容器重新启动的时候 ip 都会被重新分配,所以显然不能用 ip 来访问容器,所以最好的办法是通过容器名来访问
-
docker 每启动一个容器,就会给他分配一个 ip。docker0 就是 docker 默认给的网络,在我们不指定网络的情况下,创建的容器都在 docker0 网络中,未来开发,我们要自定义网络。
这里我们启动一个容器,查看一下它的 ip
我们对比一下宿主机的网络和容器的网络
可以发现,在启动容器后,容器内会分配一个网络,而宿主机也多了一个网络,它俩是互相配对的
再添加一个容器 web02,进行对比
web02 ip:
宿主机 ip:
总结:
- 只要启动一个容器,默认就会分配一对网卡
- 虚拟接口 # veth-pair 就是一对的虚拟设备接口,它都是成对出现的。一端连着协议栈,一端彼此相连着。
- 就好比一个桥梁,可以连通容器内外。
下面测试,两个容器之间通过 ip 访问情况
发现两个容器是可以通过 ip 来相互 ping 通的
总结:
docker 使用 Linux 桥接,在宿主机虚拟一个 docker 容器网桥(docker0),docker 启动一个容器时会根据 docker 网桥的网段分配给容器一个 IP 地址,称为 Container-IP,同时 docker 网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP 直接通信。
docker 容器网络就很好的利用了 Linux虚拟网络技术,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫 veth pair);
docker 中的网络接口默认都是虚拟的接口。虚拟接口的优势就是转发效率极高(因为 Linux 是在内核中进行数据的复制来实现虚拟接口之间的数据转发,无需通过外部的网络设备交换),对于本地系统和容器系统来说,虚拟接口跟一个正常的以太网卡相比并没有区别,只是他的速度快很多。
前面我们发现容器之间是可以通过 ip 相互 ping 通的,但是一旦容器删除后再次启动一个新的容器,ip 发生了变化怎么办?
所以最好通过容器名来相互访问,我们测试两个容器之间能否通过容器名相互 ping 通
发现两个容器是无法相互 ping 通
怎么解决这个问题?我们可以在容器运行时使用参数指定它可以通过容器名去 ping 通的容器
发现 web03 可以 ping web02,但是 web02 不能 ping web03
我们了解一下它为什么可以 ping 通?
其实它的原理和我们熟知的域名映射原理相同
我们在访问时,流程是先去本机的 hosts 中查找有没有映射,如果没有则去 DNS 找。那么 web02 就相当于,就是在 web03 的 hosts 中配置了 web02 的映射
我们可以通过以下命令证实:
过于麻烦,现在已经不常用了,我们一般都是使用自定义网络
有关 docker 网络命令
列出所有的网络
所有网络模式
我们看一下 docker0 网络
创建容器时指定网络(–net)
- 它是默认的
- 域名访问不通
- –link 域名通了,但是删了又不行
示例:自己定义一个网络
准备:删除所有容器
创建网络命令:
参数:
- :等价于,指定网络模式(默认为 bridge)
- :指定创建的网络的子网 IP 范围
- :指定网络的默认网关
未来可以通过网络来隔离项目,包括集群环境也可以自定义网络去配置
我们通过我们自定义的网络去创建两个容器
创建完成后,查看宿主机的网络:
发现跟默认的 docker0 网络有很大不同
我们测试两个容器能否通过容器名 ping 通?
诶!,我们惊喜地发现两个容器之间可以通过容器名 ping 通了
原理:
当你创建一个自定义网络并将容器连接到该网络时,docker 会为每个容器分配一个 DNS 名称。这个 DNS 名称是容器名,它在网络中是唯一的。docker 内部的 DNS 服务器会将这些容器名映射到相应的容器 IP 地址上。
因此,当一个容器想要访问另一个容器时,它可以使用目标容器的容器名作为主机名进行访问。docker 内部的 DNS 服务器会解析容器名并将其映射到相应的 IP 地址,从而实现容器之间的通信。
这种通过容器名进行访问的机制使得容器之间的通信更加方便和灵活。无论容器的 IP 地址如何变化,容器名始终是唯一且稳定的,可以方便地进行容器之间的通信和访问。
如果两个容器在不同的网络下,无论是通过 ip 还是容器名都无法相互 ping 通,那么怎样能够让两个容器相互访问呢?
我们可以将一个容器连接到另一个网络
我们在 docker0 网络下创建一个容器
接下来我们将容器连接到我们自定义的网络下
经过测试我们发现,它们都可以相互 ping 通了
我们查看一下 docker0 网络和自定义的 mynet 网络信息
docker0 网络:
里面存在容器,IP地址为 172.17.0.2
mynet 网络:
里面同样存在容器,ip 地址为 192.169.0.4
结论:连接之后,这个容器拥有了两个 ip,一个容器是可以有多个 ip 的。
如果要跨网络访问别的服务,就需要使用 连接。
dockercompose官网:https://docs.docker.com/compose/
Docker Compose 是用于定义和运行多容器应用程序的工具。 这是解锁简化和高效的开发和部署体验的关键。
Compose 简化了对整个应用程序堆栈的控制,让您能够在单个易于理解的 yaml 配置文件中轻松管理服务、网络和卷。然后,只需一个命令,即可创建并启动所有服务 从您的配置文件中。
Compose 适用于所有环境;生产、暂存、开发、测试,以及 以及 CI 工作流程。它还具有用于管理应用程序整个生命周期的命令:
- 启动、停止和重新生成服务
- 查看正在运行的服务状态
- 流式传输正在运行的服务的日志输出
- 在服务上运行一次性命令
问题:
前面我们使用 docker 的时候,定义 Dockerfile 文件,然后使用 docker build、docker run 等命令操作容器,然而微服务架构的应用系统一般包含若干个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启停,那么效率之低,维护量之大可想而之。
使用 docker compose 可以轻松,高效的管理容器,它是一个用于定义和运行多容器 Docker 的应用程序工具。
docker compose 优势
使用 docker compose 可简化容器化应用程序的开发、部署和管理:
- 简化控制:Docker Compose 允许您在单个 YAML 文件中定义和管理多容器应用程序。这简化了编排和协调各种服务的复杂任务,使管理和复制应用程序环境变得更加容易。
- 高效协作:Docker Compose 配置文件易于共享,便于开发人员、运营团队和其他利益相关者之间的协作。这种协作方法可以实现更顺畅的工作流程、更快的问题解决速度和更高的整体效率。
- 快速应用程序开发:Compose 缓存用于创建容器的配置。当您重新启动未更改的服务时,Compose 会重新使用现有容器。重用容器意味着您可以非常快速地对环境进行更改。
- 跨环境的可移植性:Compose 支持 Compose 文件中的变量。您可以使用这些变量为不同的环境或不同的用户自定义您的组合。
- 广泛的社区和支持:Docker Compose 受益于充满活力和活跃的社区,这意味着丰富的资源、教程和支持。这个社区驱动的生态系统有助于 Docker Compose 的持续改进,并帮助用户有效地解决问题。
小结
compose 项目是 docker 官方的开源项目,负责实现 docker 容器集群的快速编排
开源代码:https://github.com/docker/compose
我们知道使用 dockerfile 模板文件可以让用户很方便的定义一个单独的应用容器,其实在工作中,经常会碰到需要多个容器相互配合来完成的某项任务情况,例如工作中的 web 服务容器本身,往往会在后端加上数据库容器,甚至会有负责均衡器,比如 LNMP 服务
Compose 就是来做这个事情的,它允许用户通过一个单独的 docker-compose.yml 模板文件(YAML格式)来定义一组相关联的应用容器为一个项目(project)
Compose 中有两个重要的概念:
- 服务(service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例,很多的镜像启动
- 订单服务 image
- 物流服务 image
- 用户服务 image
- 支付服务 image
- 4个容器后面构成一个服务 service
- 项目(project):由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 中定义。
Compose 项目是由 Python 编写的,实际上就是调用了 Docker 服务提供的 API 来对容器进行管理,因此,只要所在的操作系统的平台支持 Docker API,就可以在其上利用 Compose 来进行编排管理。
- yum 安装
- 一般情况下,linux 要安装 python 环境
- 输入命令查看是否安装成功
安装官方演示的案例:https://docs.docker.com/compose/gettingstarted/
- 为项目创建目录
- 创建一个一会要运行的文件
代码如下:
在此示例中,是 redis 容器的主机名应用程序的网络,我们使用 Redis 的默认端口。
- 创建另一个在项目目录中调用的文件,内容如下:
- 创建,内容如下:
这会告诉 docker :
- 从 Python 3.10 映像开始构建映像。
- 将工作目录设置为
- 设置命令使用的环境变量
- 安装 gcc 和其他依赖
- 复制并安装 Python 依赖项
- 将元数据添加到映像,以描述容器正在侦听端口 5000
- 将项目中的当前目录复制到映像中的 workdir,代表当前目录
- 将容器的默认命令设置为
- 在 compose 文件中定义服务,创建文件
此 Compose 文件定义了两个服务:web 和 redis
该服务使用从当前目录中生成的映像。 然后,它将容器和主机绑定到公开的端口,此示例服务使用 Flask Web 服务器的默认端口
该服务使用从 Docker Hub 注册表中提取的映像
- 使用 compose 构建并运行应用
注意文件不要有缺失
在这个目录下执行以下命令构建:
安装完成后打开浏览器输入,会看到以下信息
每刷新一次,数字都会增加
项目完成后,我们查看所有的镜像
会发现多了一个镜像,这个镜像是由(composetest-web)来构成的
查看容器服务:
停止容器服务:
发现多了一个自定义的网络,我们再次启动这个 compose,查看这个自定义网络信息
这里面就有我们刚刚看到的两个容器服务
总结
- 使用 compose 文件构建运行的镜像名字是
- compose 中每一个服务都会生成一个容器,名字是
- 构建时会生成一个自定义网络,所有的容器服务都会在这一个网络下
启动一个容器,启动多个容器(服务网络问题-自定一个网络。所有服务按照项目名来定义,编号)
说明:
一个普通的工作流程以启动应用程序开始。
和命令可以用来验证应用程序的状态,还能帮助调试。
修改代码后,先执行构建新的镜像,然后执行取代运行中的容器。
注意,compose 会保留原来容器中所有旧的数据卷,这意味着即使容器更新后,数据库和缓存也依旧在容器内(这很可能造成混淆,因此要特别小心)。
如果你修改了 compose 的 yaml 文件,但不需要构建新的镜像,可以通过参数使 compose 以新的配置替换容器。
如果想要强制停止 compose 并重新创建所有容器, 和
简单使用:
- 执行命令运行容器:
- 查看镜像:
- 停止和删除容器: 和
模板文件是 compose 的核心,涉及的指令关键字比较多,但是大部分的指令与 docker run 相关的参数的含义是类似的
默认的模板名是
小结
以后我们的微服务项目中,如果有多个微服务,则按照他们的启动顺序,配置对应的规则文件即可!
可以去看看你们的公司项目,有没有 docker-compose.yml 文件,有没有做自动编排!
如果下载的网上开源项目,有 dockerfile + docker-compose ,那我们可以一键搞定!
网上的项目拉下来,mysql 的 sql 文件导入数据库。 docker-compose up 即可!
dockerfile + docker-compose。
工程、服务、容器
- docker compose 将所管理的容器分为三层,分别是工程(project)、服务(service)、容器(container)
- docker compose 运行目录下的所有文件(docker-compose.yml)组成一个工程,一个工程包含多个服务,每个服务中定义了容器运行的镜像、参数、依赖,一个服务可包括多个容器实例!
至此,dokcer compose 搞定!
WordPress 是一款个人博客系统
在目录下编辑文件:
执行以下命令:
启动成功打开浏览器,输入访问
出现这个证明安装成功
进入之后随便发布一篇文章,查看 mysql 中有哪些数据
mysql 用户名是,密码是,上面 yaml 文件中有配置
总结
docker 卷 将 WordPress 所做的所有更新持久化到数据库。
WordPress Multisite 仅适用于 port 和
从你的项目目录运行。
测试访问!
未来只需要一键启动就可以安装好环境了!无论多复杂都是一键。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ri-ji/74880.html