www.91084.com

GVKun编程网logo

从「集装箱」思考 Docker 风潮(集装箱 chrome)

17

如果您想了解从「集装箱」思考Docker风潮的相关知识,那么本文是一篇不可错过的文章,我们将对集装箱chrome进行全面详尽的解释,并且为您提供关于167dockerdocker构建nginx容器系列

如果您想了解从「集装箱」思考 Docker 风潮的相关知识,那么本文是一篇不可错过的文章,我们将对集装箱 chrome进行全面详尽的解释,并且为您提供关于167 docker docker构建nginx容器系列问题 docker registry docker run docker toolbo、Docker 04 应用部署与迁移备份 Dockerfile 与 Docker 私有仓库、Docker Compose比Docker Swarm和Docker Stack有什么好处?、Docker in Docker(实际上是 Docker outside Docker): /var/run/docker.sock的有价值的信息。

本文目录一览:

从「集装箱」思考 Docker 风潮(集装箱 chrome)

从「集装箱」思考 Docker 风潮(集装箱 chrome)

前言

在许多革命性转折里,经常出现集装箱的身影;它就像幸运草一般,总是带来许多幸福和财运。现在 Docker 风起云涌,再现集装箱身影,如果开放视野、大力支持它,持续发挥它的潜能和力量,则幸运草就会出现在我们身旁了。

由于 Docker 集装箱带来的商机,其最直接的受益者是软件管理者 (或称维运者),例如软件测试工具业者、测试人员等。因此在今天,不论您是开发者或是维运者,最好是从维运者的角度、扩大视野来支持它,便能站在制高点上拟订最佳策略,掌握了需求碎片化的潮流,进而成为新世代的领头羊。

在这新世代里,除了拿 Docker 集装箱来打包微服务 (micro-service) 来满足需求碎片之外。我们还要以广大的视野、创新的思维,将碎片组合出各式各样、气象万千的商业服务。就像飞机设计师一样,把一群各自 < 不会飞 > 的模块 (如轮胎、引擎、机翼、油箱等),以创新模式将它们组合起来,竟然整体就<能飞>上天空了。于是,创新组合的接口 (interface) 的定义权成为兵家必争之地,唯有掌握接口才有话语权。


1、缘由

自從 2014 年以來,Docker 的集装箱 (container) 技术,可说是红透半天边,而且势如破竹、蔚为风潮,正在强力改变云 (cloud) 服务的世界。这跟半世纪前,海上船运业的集装箱风潮,对整个产业的革命性改变,其力道来源和产生经济效益,可说具有异曲同工之妙。

图 - 1、Docker 平台的标志 (Logo)

这项力道和潮流的直接受益者,是管理者 (operator, 又称维运者),而不是开发者 (developer)。因此,在本文里,我将从管理者的视角来说明 Docker 集装箱即将带来的革命性潮流,让读者们皆能兴奋地迎接这项已经来到身边的潮流,并且能从中获利。

2、回顾半世纪前的船运集装箱风潮

在半世纪之前,集装箱发挥了巨大的力量,改变了整个运输产业,也改变了人们的生活。就如 Intel 公司总裁葛洛夫 (Andrew Grove) 曾举集装箱为例说道:

短短的十年,实际上只是航运史上一个极短促的时间,造船设计即走向标准化,冷冻运输船也诞生了,最重要的是集装箱化作业的兴起,这种容许船货更快速装卸的技术在航运的生产力上引进了『十倍速』的改变,逆转了节节升高的成本趋势,..... 有些港口做了改变,有些虽尽力改革,却无法做到,许多则坚持抗拒这种潮流,结果,这些新技术引发了全世界货运港口的重新洗牌,.... 没有采行新技术的港口(如新加坡及西雅图)可能被重新规画,成为购物中心、休闲场所或河岸公寓大厦。

图 - 2、集装箱让运输费用降低一半 (以下摘自百度图片)

长荣海运公司总裁 张荣发 先生在其回忆录上写道:

为了配合集装箱化运输时代的来临,海运事业的整体运作型态也产生了重大的转变,无论在海上运送、码头作业以及陆运转接上,都有革命性的改变。陆上拖车运输业应时而兴,扮演极为重要的角色,以集装箱拖车配合集装箱船运输,具有简化包装、防止窃盗、加速货物搬运及便利关务检验等优点,使集装箱运输作业更加灵活。为了能确实掌握海上及陆上的运送服务质量和效率,就率先于 1973 年 9 月成立了长荣运输公司。


图 - 3、世界航运巨擘:长荣 (Evergreen)

集装箱的威力是来自于它提供了一致的接口 (interface),简化了运输业的工具。例如以前,在集装箱尚未普及之前,在公路上,必须为汽车业而设计特殊的拖车;在港口码头,也必须为木材业而设计特殊的卸货吊车及仓库等等。这些特殊设计对于运输管理、港口管理、仓储管理等都是很麻烦的事。有了集装箱之后,就出现了专门运集装箱的轮船,也有专门拖集装箱的拖车,高速公路的弯曲度也因集装箱拖车的安全而修正,仓库的管理也变得很单纯。集装箱不一定带给汽车业、木材业、玩具业带来直接的方便,也许反而带来不方便 (如大汽车必须拆解开来才能装进集装箱里)。但是运输业等获得好处,所以运输业会很乐意把集装箱拱抬起来,促成集装箱的革命性风潮。

将之对应到 Docker 风潮,可知道 Docker 集装箱的效益在于:让所有云服务都有一致的操作 (operation) 界面,包括部署、管理等方式。众多云平台就像众多码头一样,都使用一致的方式来操作集装箱,例如卸货器具、拖车等。Docker 公司的 Scott Johnston 曾说道:

你将不再需要使用各项单独的 IT 管理工具来分别进行 App 的管理、部署、监控和扩容等功能操作,在整个企业内这些操作都可得到一致性、统一性。

3、从 <国王的皮鞋> 领悟 Docker 集装箱的经济效益

古代有一位国王在它的国境里视察,因为路面崎岖不平,还有很多碎石头,刺得国王的脚又痛又麻。

图 - 4、赤脚国王的故事 (摘自百度图片)

回到了王宫后,他下了一道命令,要将国内所有的道路都铺上一层牛皮。让他自己和] 全国的人走路不再受刺痛之苦。众大臣听了国王的话都一筹莫展,知道这很难。即便杀尽国内所有的牛,也凑不到足够的牛皮来铺路,而且花费昂贵。这时,一个聪明的仆人向国王建言:可以试着用牛皮将脚包起来,大王的脚就不会忍受痛苦了。国王听道而顿悟了,便收回命令,采纳了建议,于是,皮鞋就这样发明了出来了。

图 - 5、国王的皮鞋


我想,大家一定都听说过上述的皮鞋故事了。其解决脚痛不方便的方案有二:第 1 方案是:将所有道路都铺上一层牛皮 (如 VMware),实在不经济实惠。 第 2 方案是:用两片牛皮包住脚,这就是皮鞋 (Docker 集装箱)。那么,你领悟到什么呢?至少明显知道第 2 方案可带来可观的经济效益。

从上述皮鞋故事的比喻,可知道传统的虚拟化 (virtualization) 技术就相当于在各道路 (实体机器) 上铺一层牛皮 (VM, 虚拟机),然后让国王的脚 (App) 在牛皮 (VM) 上走路 (执行)。传统上云平台采取虚拟化手段来满足用户个别的资源需求分配,以及确保其可用性和隔离性。然而无论是 KVM 还是 Xen 等 Guest OS 都很浪费资源又难于管理,都不如 Docker 集装箱 (皮鞋) 来的更加灵活、快速和节省资源。

4、Docker 如何运输 (ship) 集装箱?

顾名思义,Docker 就是 “码头搬运工人” 之意。而集装箱的主要用途就是运输东西。所以,我们把焦点放在 Docker 集装箱和如何运输上,也就是从运输 (shipping) 的角度来认识 Docker 及其集装箱。

设想在开发平台上,开发者撰写一份 dockerfile 档,让 Docker (码头搬运工人) 在此平台上建立一个 Docker 集装箱,此集装箱运行于开发平台上的一个用户进程 (process) 里,包含了执行某一特定 App 程序的所需要的 OS、软件库、配置文件和资料,是一个可移植的运行单位。那么,如何把这个集装箱运输 (移植) 到云平台上呢?这时,Docker (码头搬运工人) 就从这个集装箱 (或其 dockerfile) 产生出它的镜像 (image),通称为 Docker (集装箱) 镜像;然后把该 (集装箱的) 镜像传输到云平台上。云平台上的 Docker 会依据这镜像,修改一下配置模块,就在云平台上创建一个新的 Docker 集装箱了,让 App 在此集装箱里执行。相对上,一个 Docker 镜象是一个模子 (template),可用来创建多个 Docker 集装箱对象或实例 (instance)。

由于 Docker 集装箱及其镜像,是由 dockerfile 文件的脚本所创建的;所以也可直接将 dockerfile 文件传输到云平台,并依据其脚本而在云平台上创建新的 Docker 集装箱。集装箱的 dockerfile 文件和镜像两者都是模子,都可用来 (在云平台上) 创建集装箱实例,并让 App 顺畅执行起来。软件专家波金 (Lucas Perkins) 在其文章:“ Docker and Shipping Containers: An Imperfect Analogy” 里,就拿一棵树来比喻一个 Docker 集装箱,而不是拿船运集装箱来比喻。他说道:

  • The shipping container analogy is apt, but for me it completely breaksdown on one crucial point: when shippingcontainers go down, their cargo is lost.(拿船运集装箱来比喻是可以的,但有一点会失真:当集装箱沉入大海,货物就消失了。)

  • Docker containers don''t work this way. When they go down, you simplyrebuild the container.(Docker 集装箱并非如此,当它损毁了,只要重建一个就行了。)

  • In this sense, Docker containers are more like plants than shippingcontainers. If a plant dies, you simply plant a seed and replace it. (以此观之,Docker 集装箱更像树木。如果一棵树枯死了,只要播下种子,长出一棵新树就行了。)

  • If a Docker container goes down, .... You can simply use the oldcontainer''s Dockerfile (think of it as a container seed) to sprout a newcontainer identical to the old one. Even better, Dockerfiles, like seeds, tendto be quite small , but they can grow into mighty oaks.(如果一个 Docker 集装箱损毁了,你只要使用原来的 dockerfile (就像种子) 来重新长出一棵一样的树就行了。而且一个小小的 dockerfile,就能长出一棵大树。)

上述 dockerfile 是一种脚本文件,用来描述如何把二进制 (binary) 文件装进一个 Docker 集装箱镜像 (Dockerimage),并做好配置。当你使用 docker build 命令的时候,Docker 会读取这 dockerfile 文件,执行其脚本内容来构建立一个 Docker 镜像。所以,DockerFile 的用途就 (像樹的種子) 用来构建 Docker 镜像。我想,从上所述,你应该可以领悟 Docker 集装箱运输的涵意了。

5、从 LXC 容器到 Docker 集装箱

Docker 集装箱是基于 LXC 容器而发展出来的。其实,这里的集装箱和容器都是 “Container” 术语的的中文翻译。那么,为何我称 LXC 容器,而称 Docker 集装箱呢?其主要原因是:LXC 容器是特定平台的虚拟化,不能充分独立于底层机器 (平台) 的配置 (configuration),例如 networking, storage, logging, distro 等等。所以,LXC 本身无法充分跨 (机器) 平台,导致 App 也无法跨平台。也就说,LXC 难以通过标准化的模板制作、重建、复制和移植,无法如船运集装箱一般,可以跨越各地港口和码头。

后来,Docker 弭补了这项缺点。Docker 在 LXC 与平台之间定义了标准接口,提供一种安全、可重复的执行环境,让各集装箱都运行于自己的网络空间、虚拟界面和 IP 地址;并能自动部署和更新软件版本。这种跨平台的新型 LXC 就成为 Docker 集装箱。就像船运集装箱与各港口的码头、各公司货轮或拖车的型号、配置是无关的。

简而言之,虽然 LXC 容器很成熟了,只是缺乏跨平台性,不方便在多平台 (机器) 之间移动;也不方便于创建管理,不易于重复操作和共享等。基于成熟的 LXC 容器功能,Docker 集装箱解决了上述问题,成为可移植、易于改版与整合的新一代虚拟化技术。“集装箱” 一词强调了 Docker 集装箱的效益在于:让所有云服务都有一致的部署、传输、改版等管理方式。众多云平台就像众多码头一样,都使用一致的方式来操作集装箱,例如卸货器具、拖车等。

6、认识 LXC 容器

LXC 仰赖 namespace 来实现隔离性。让每个容器都有自己的命名空间,确保不同容器之间不会相互影响,让每个容器成为拥有自己进程和网络空间的虚拟环境,都成为一个独立运行的单位。此外,LXC 藉由内核的 cgroup 来对各个容器 (的进程) 使用的系统资源做严格的限制。

简而言之,LXC 基于 namespace 的隔离机制和 cgroup 的资源控制功能,来管理容器。例如可建立一个 cgroup 来限制某个 (容器) 进程对 CPU 的占用率不能超过 50%。而 Docker 则在 LXC 基础上,加上 Docker 境像管理方式,就成为 Docker 集装箱了。

Docker 借鉴了虚拟机 (VM) 的模式,让用戶像管理 VM 一样的管理他们的集装箱镜像。

6.1 隔离性

LXC 运行于一个用戶空间进程里,在既有的进程管理架构上,增添了资源管理和隔离机制。所以 LXC 是针对某一 App 提供资源隔离和控制的轻量型虚拟系统。LXC 仰赖 namespace 来实现隔离性。让每个容器都有自己的命名空间,比如 pid/net/ipc/mnt/uts 等命名空间,以及不同的 user id 和 group id。有了 namespace 从进程、网络、IPC、档系统、UTS 和用户角度进行隔离,我们就能 e 确保在不同容器之间不会相互影响,每个容器都成为一个独立运行的单位。从容器里而观之,它是一个完整的 Linux 的世界。在整个平台而观之,容器运行于一个普通的用户空间进程,namespace 创造了这种映射和隔离效果,云平台承载着一个个容器,就如同造物者创造了许多世外桃源一般。

6.2 资源控制

LXC 仰赖 cgroup 来限制各个进程对系统资源的使用能力。通常会创建多个 cgroup,形成一个树状结构 (hierarchy)。然后 subsystem 会关联连接到这个树状结构上。一个 subsystem 代表着一项资源,例如 CPU、Memory 或 I/O 等。例如下图:

图 - 6、cgroup 树状结构

这图里的 cgroup 组织形式是树状结构的,包含一个父 cgroup 和三个子 cgroup,其关联到两个 subsystem (即 CPU 和 memory)。这 subsystem 是经由 cgroup 来与 task (典型的就是进程) 连结,以便实现对 task 的资源管理与控制。一个 task 可加入到树状结构上的一个 cgroup,由此 cgroup 来限制该 task 的资源使用。其中,cgroup 与 task 是多对多 (N:N) 的连结关系。亦即,一个 cgroup 可以连结到多个 task。而一个 task 也可连结到多个 cgroup,但是在一个树状结构里只能加入一个 cgroup。例如,针对一个 (容器) 进程,先创建名为cpuset 的 cgroup,然后将一个进程 (/mytask) 的 PID 写入 /sys/fs/cgroup/cpuset/ tasks 文件里,就把这个 mytask 加入到该 cgroup 了。如下图:

图 - 7、cgroup 与 task 的 N:N 连结关系

这个 mytask 连结到两个 cgroup:即 “cpuset” 和 “ioset”,各连结到一个 subsystem (即 CPU 和 I/O 资源)。

7、认识 Docker 园丁 (Runtime)

刚才说明了,我们在运输 (ship) 或移植一个 Docker 集装箱时,就像移植一棵树一样, 但是移植树的种子 (seed) 到另一个花园 (平台) 里,重新打造出一样的 (identical) 环境 (花盆) 并重新长出一样的树。例如,一个 dockerfile 就是种子,体积很小,运输快速。如下图:

图 - 8、以树来比喻 Docker 集装箱的运输

那么,我们在电脑上,需要有位园丁来打造花盆、准备资源 (如水、泥土) 等工作。这位园丁就是:Docker Runtime。它是由三个模块所组成,包括:Docker Server、Docker Engine 和 Docker Daemon 三部分。通常,人们是透过 Docker Client 来与 Docker Server 建立通信 (两者是 C/S 架构)。例如,我们可以将 docker build 命令传送给 Docker Server 来依据指定的 dockerfile 来创建一个 Docker 镜像。

图 - 9、Docker Runtime 的结构

Docker Server 接受 DockerClient 所传送来的请求,然后转给 Docker Engine 去转换出一连串的工作 (job) 来管理集装箱。例如,向 Docker Registry 获取镜像、通过 GraphDriver 执行集装箱镜像的建立、通过 NetworkDriver 执行容器网络环境的配置、通过 ExecDriver 执行集装箱内部的软件等。

8、认识 Docker 集装箱集散地 (Hub)

Docker 公司不仅仅提供上述的 Docker 园丁来帮你搬运集装箱,还提供 DockerHub 来做为集装箱的共享平台。Docker 公司提供的開放平台,主要包括:

Platform = Docker Engine + Docker Hub + APIs + Ecosystem

如下图:

图 - 10、<Docker Engine + Docker Hub> 开放性平台

我们在开发平台上,使用 Docker 引擎来将 App 打包到集装箱里,然后透过 DockerHub API 来将集装箱 (的镜像) 放到 DockerHub 上。于是,Docker Hub 成为一个集装箱集散地,也就是一个共享的集装箱平台。需要时,可从这 Hub 寻找到集装箱,并下载到云服务平台 (如阿里云或 Google 云) 上去运行。


图 - 11、Docker Hub 集装箱共享平台

所以,Docker Engine 和 Docker Hub 两者联手,为开发者和系统管理员设计出一个易于发布和运行分布式 App 的开放性平台。

9、阐述 <集装箱> 幕后的架构设计思维

9.1 序中有乱

前面,介绍过了台湾长荣海运公司繁荣发达的历史经验,可让你体会出集装箱如何带来巨大经济价值。集装箱的外表简单有序、能叠得很高、而且井然有序;集装箱的内部是空的,用来容纳多样化而繁杂的物品;这种情形称为:序中有乱 (变化)。序中有乱的巨大威力,改变了整个运输产业,也改变了人们的生活。

俗语说:科学家从乱中找序,而设计师 (艺术家) 则规划序中有乱。无论是乱中有序序中有乱,两者都要呈现出序 (order),并包容乱 (change),只是手段不同而已。两种手段都能带来巨大经济价值,精通这两种手艺,是当今需求碎片化时代哩,将云平台上的微服务 (micro-service) 迅速创新组合成为 App 的不二法门。序中有乱的 < 乱 > 是变化、成长与繁荣之意。

「乱中有序」与「序中有乱」两者之间,只是人们抽象视角 (viewpoint) 的不同心智 (mental) 呈现而已,并外在世界的真实事物 (和景像)。就像大家孰悉的「横看成岭侧成峰,远近高低各不同」诗句里,因为视角不同而呈现于内心的不同景像。例如,台北 101 大楼的钢骨结构,可从「序中有乱」视角来看它;也可以从「乱中有序」来看它。再如,一盆看来很漂亮的枫叶,既可从「序中有乱」视角来看它;也可以从「乱中有序」来看它。

图 - 12、「乱中有序」还是「序中有乱」呢?

其实,中文字的 <易>,并不代表简单 (easy);而是代表变化 (change) 之意。当我们找到一种容器 (container),来包装变化,就得到简单了。因此,「容易」两个字组合在一起,才代表简单 (easy or simple) 之意。于是,Docker 集装箱以容器来包装复杂多变,任人们拥有 < 简单而容易 > 的方式来实践 App 的维运。它的幕后蕴藏了典型的「序中有乱」架构设计思维。


9.2 < > 的设计法则

在我所写的书籍:《思考软件、创新设计:A 段架构师的思考技术》(北京电子工业出版社) 里,我也详细阐述了集装箱的设计哲理,我书中写道:

这来自于自然界的造物之道。自然界生物之设计,其主要限制是:信息的有限性(Information Limitations)。由于这项限制,一个生物形体的造成,是出自一个概括性的计划:<单纯的造形>。随着生物的成长、与环境的交互信息越多,逐渐在细节上修修补补,就发展出 < 不同的内涵 >。然后,基于单纯的造形,不断进行 < 重复的组合 >。例如,漂亮的枫叶林,就是合乎 “单纯造形、不同内涵、重复组合” 三项特性。许多造形相同(且不同细节)的枫叶,组合出一遍美丽的树林。

图 - 13、「序中有乱」带来的美感

再如人们的手掌的造形也都极为相似,其细节纹路也各不相同,也满足上述三项特性。关于 <信息的有限性> 与自然造物法则,在生物学界的探讨论文已经非常多了,在此就不多叙述了。在最具爆发力的工业设计品中,你常常可以发现其杰作具有其特色:简单造形、内涵不同、无限重复。集装箱就是典型的单纯造形,它兼具了这三项特质。更重要的是,它带来无比巨大的商业潜力和商机。举凡能包容变化之体系,都有三项共同之特性:

  • 特性 1:构造简单— 单一元素。

  • 特性 2:容易组合— 简单的 (如线性、树状或网状) 组合规律,呈现出美好的序。

  • 特性 3:包容变化— 集装箱能装无限形式之物。

因为单一元素,简单组合,具有极大的包容力和弹性,发挥 <序中有乱> 的特质,带来一样的巨大潜能,蔚为风潮。

欢迎您有空时,可阅读我所写的这本书,并多多赐教。

在這本書裡,我詳细说明了,如何把变化封装起来,凸显简单秩序,让人们因为秩序简单而令人着迷,因为变化无穷而令人惊叹它的无限潜能。这就是船运集装箱、Docker 软件集装箱等具有革命性威力的来源,就是:和谐而充满能量。

9.3 世界首富:比尔。盖兹 (Bill Gates) 也在思考集装箱

鼎鼎大名的微软创始人比尔。盖兹,在 2013 年阅读了上百本书籍,他阅读之后也做了笔记。颇令人好奇的是,他第一份阅读笔记,竟然是有关于<集装箱运输>。这本书名是:The BoxHow the Shipping Container Made the World Smaller and theWorld Economy Bigger.(By Marc Levinson)

图 - 14、比尔。盖兹也在思考集装箱

 如果您有兴趣,也可以观看我的线上视频课程,其中有一个视频课程 (免费),名称是:“新一代架构师:像 Bill Gates 一样_思考集装箱”。

在这视频中,我详细地阐述了集装箱的架构设计思维。观看网址:

http://www.cnblogs.com/smartADT。

10、Docker 潮流下的赢家策略

10.1 从 Operator 视角看 Docker 集装箱,掌握商机

  集装箱带来的商业利益,其直接受惠是运输业者,并不是货物制造者或应用者。所以集装箱内部的包装业,如纸盒制造业、打包工人等;拖车汽车厂、拖车行、拖车司机;还有造船厂、海运公司、码头工人等都会迅速蓬勃发展起来。

图 - 15、从 Operator 视角看集装箱

同样地,Docker 集装箱带来的商业利益,直接受惠是软件管理者或称维运者 (operator),例如软件测试工具业者、测试人员等。至于大多数的软件开发者 (developer),通常等到 Docker 集装箱变得普遍流行起来了,大家才会大大感受到非用它不可了。因此,不论您是身为开发者,还是维运者,都应该站在维运者的视角和立场来感受 Docker 集装箱潮流的力量,以便采取最佳策略,抓住这道力量带来的巨大商机。否则您将成为潮流下的后知后觉者。

10.2 采取<组合创新>架构设计思维

自从 1980 年代,面向對象 (object-oriented) 软件技术流行以来,架构设计有两个基本技艺:分类 (classification) 与组合 (composition)。逐渐地衍生了以下两种不同的架构设计思维:

  • 古典抽象思维:偏于乱中有序,从复杂变化中分析出次序;其追求共通性。

  • 创新组合思维:偏于「序中有乱」,力求设计出次序来容纳复杂变化;其追求独特性。这种思维,最常见的比喻是 “集装箱”,因为从集装箱的发展历史,很容易让我们体会出 < 序中有乱 > 如何带来巨大经济价值。

如今,在这需求碎片化时代里,Docker 集装箱将成为打包微服务 (micro-service) 的最佳载体。于是,我们将需要有创造的架构来将云端的微服务,组合形为具有独特性的 App 了。于是,需要有<组合创新>的架构设计思维。就像飞机设计师一般,其把一群各自 < 不会飞 > 的模块 (如轮胎、引擎、机翼、机尾、油箱等),以创新的模式将它们组合起来,竟然整体就<能飞>上天空了。


10.3 掌握接口 (interface),拥有话语权

集装箱就是基于「序中有乱」思维,把复杂多变 (的内容) 包装起来,呈现出简单易用的序。这个序呈现出来,就是集装箱的接口了。同样地,Docker 集装箱也定义了一群标准的接口。

然而,软件产业是一个强龙与地头蛇混杂的丛林世界。大哥 (强龙) 订定接口为标准,小弟 (地头蛇) 遵循标准接口。唯有掌握接口制定权才能成为强龙,获得话语权,成为最大获利者。例如,Docker 就是基于标准的 LXC 容器 (也是集装箱) 而在制定自己的接口,成为产业新标准接口,而建立其强龙地位。

同样地,在 Docker 集装箱的潮流下,将涌现更多的小集装箱和接口,也将涌现较大的集装箱和接口。于是强龙处处有,获利无穷时。如果您有兴趣,也可以观看我的线上视频课程,其中有一个视频课程 (免费),名称是:“新一代架构师:掌握接口,才有话语权”。


如果你觉得 dotNET 跨平台还不错,那就收藏下面的二维码关注吧(长按下面的二维码图片、并选择识别图中的二维码)。别忘记分享给你的朋友。^_^


本文分享自微信公众号 - dotNET 跨平台(opendotnet)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与 “OSC 源创计划”,欢迎正在阅读的你也加入,一起分享。

167 docker docker构建nginx容器系列问题 docker registry docker run docker toolbo

167 docker docker构建nginx容器系列问题 docker registry docker run docker toolbo

docker构建nginx容器系列问题


background : 最近为小伙伴们筹划docker系列的技术分享,研究了一会docker相关技术, 在此记录一下构建nginx容器时候的坑

1.nginx服务器根目录问题

docker 官方镜像提供的nginx基于debian/jessie平台,其文件结构和ubuntu中的nginx中并不相同

eg:

run一个niginx容器

<span>//80端口被占用,so...</span>
$ sudo docker run <span>-it</span><span>-p</span><span>800</span>:<span>800</span> nginx
$ sudo docker ps 

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                   NAMES
<span>1801</span>a32aab54        nginx               <span>"nginx -g ''daemon off"</span><span>2</span> minutes ago       Up <span>2</span> minutes        <span>80</span>/tcp, <span>443</span>/tcp, <span>0.0</span><span>.0</span><span>.0</span>:<span>800</span><span>-&gt;</span><span>800</span>/tcp   berserk_kare
登录后复制

进入容器内部

<span>$ </span>sudo docker exec -it <span>1801</span>a32aab54 /bin/bash
root<span>@1801a32aab54</span><span>:/</span><span># </span>
登录后复制

查看nginx目录

<span># cd /etc/nginx/</span>
conf<span>.d</span>/         koi-utf         mime<span>.types</span>      nginx<span>.conf</span>      uwsgi_params    
fastcgi_params  koi-win         modules/        scgi_params     win-utf  
登录后复制

可以看到不仅没有熟悉的 /sites-available,也没有 /sites-enabled

继续查看nginx配置

<span># cat /conf.d/default.conf</span><span>server</span> {
    listen       <span>80</span>;
    server_name  localhost;

    <span>#charset koi8-r;</span><span>#access_log  /var/log/nginx/log/host.access.log  main;</span>    location / {
        root   /usr/share/nginx/html;
        <span>index</span><span>index</span>.html <span>index</span>.htm;
    }

    <span>#error_page  404              /404.html;</span><span># redirect server error pages to the static page /50x.html</span><span>#</span>
    error_page   <span>500</span><span>502</span><span>503</span><span>504</span>  /<span>50</span>x.html;
    location = /<span>50</span>x.html {
        root   /usr/share/nginx/html;
    }
    <span>#...省略php-fpm配置,好长..</span>
}
登录后复制

根目录配置: root /usr/share/nginx/html;

测试

<span># cd /usr/share/nginx/html</span><span># touch index.html</span><span># echo "test nginx in docker" &gt;index.html</span>
登录后复制

php-fpm配置相关

'').addClass(''pre-numbering'').hide(); $(this).addClass(''has-numbering'').parent().append($numbering); for (i = 1; i '').text(i)); }; $numbering.fadeIn(1700); }); });

以上就介绍了167 docker docker构建nginx容器系列问题,包括了docker,nginx方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

Docker 04 应用部署与迁移备份 Dockerfile 与 Docker 私有仓库

Docker 04 应用部署与迁移备份 Dockerfile 与 Docker 私有仓库

MySQL 部署   

    拉取 mysql 镜像    docker pull centos/mysql-57-centos7

    创建 MySQL 容器    docker run -di --name=mysql01 -p 33306:3306 -e MYSQL_ROOT_PASSWORD=320512 centos/mysql-57-centos7

    -p 代表端口映射,格式为 宿主机映射端口:容器运行端口
    -e 代表添加环境变量 MYSQL_ROOT_PASSWORD 是 root 用户的登录密码

Tomcat 部署

    拉取镜像 docker pull tomcat:7-jre7

    创建容器 创建容器 -p 表示地址映射

    docker run ‐di ‐‐name=mytomcat ‐p 9000:8080

    ‐v /usr/local/webapps:/usr/local/tomcat/webapps tomcat:7‐jre7

Nginx 部署

    拉取镜像    docker pull nginx

    创建容器    docker run ‐di ‐‐name=mynginx ‐p 80:80 nginx

Redis 部署

    拉取镜像    docker pull redis

    创建容器    docker run ‐di ‐‐name=myredis ‐p 6379:6379 redis

 

 

迁移与备份

    容器保存为镜像

    我们可以通过以下命令将容器保存为镜像

    docker commit 容器名称 镜像名称

镜像备份

    我们可以通过以下命令将镜像保存为 tar 文件

    docker save -o tar 文件名称 镜像名称

恢复镜像

    docker load -i tar 文件名称

Dockerfile

    Dockerfile 是由一系列命令和参数构成的脚本,这些命令应用于基础镜像并最终创建一个新的镜像。

    1、对于开发人员:可以为开发团队提供一个完全一致的开发环境;

    2、对于测试人员:可以直接拿开发时所构建的镜像或者通过 Dockerfile 文件构建一个新的镜像开始工作了;

    3、对于运维人员:在部署时,可以实现应用的无缝移植。

常用命令

命令 作用
FROM image_name:tag 定义了使用哪个基础镜像启动构建流程
MAINTAINER user_name 声明镜像的创建者
ENV key value 设置环境变量 (可以写多条)
RUN command 是 Dockerfile 的核心部分 (可以写多条)
ADD source_dir/file dest_dir/file 将宿主机的文件复制到容器内,如果是一个压缩文件,将会在复制后自动解压
COPY source_dir/file dest_dir/file 和 ADD 相似,但是如果有压缩文件并不能解压
WORKDIR path_dir 设置工作目录

使用脚本创建镜像

步骤:
(1)创建目录

    mkdir –p /usr/local/dockerjdk8

(2)下载 jdk-8u171-linux-x64.tar.gz 并上传到服务器(虚拟机)中的 /usr/local/dockerjdk8 目录

(3)创建文件 Dockerfile vi Dockerfile

#依赖镜像名称和 ID
FROM centos:7
#指定镜像创建者信息
MAINTAINER ITCAST
#切换工作目录
WORKDIR /usr
RUN mkdir /usr/local/java
#ADD 是相对路径 jar, 把 java 添加到容器中
ADD jdk‐8u171‐linux‐x64.tar.gz /usr/local/java/
#配置 java 环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_171
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH
$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH

(4)执行命令构建镜像(注意后边的空格和点,不能省略)

docker build ‐t=''jdk1.8'' .

参看镜像是否建立完成

docker images

 

Docker 私有仓库

私有仓库搭建与配置

(1)拉取私有仓库镜像(此步省略)

    docker pull registry

(2)启动私有仓库容器

    docker run ‐di ‐‐name=registry ‐p 5000:5000 registry

  (3)    打开浏览器输入地址 http://ip:5000/v2/_catalog,看到 {"repositories":[]} 表示私有仓库搭建成功并且内容为空。

  (4)    修改 daemon.json    vi /etc/docker/daemon.json

            添加以下内容,保存退出,这是为了让 docker 信任私有仓库地址 {"insecure-registries":["ip:5000"]}

重启 docker 服务

    systemctl restart docker

 

镜像上传到私有仓库

    标记此镜像为私有仓库的镜像    docker tag jdk1.8 ip:5000/jdk1.8    

再次启动私服容器

    docker start registry

上传标记的镜像

    docker push ip:5000/jdk1.8

Docker Compose比Docker Swarm和Docker Stack有什么好处?

Docker Compose比Docker Swarm和Docker Stack有什么好处?

从我读到的内容来看,似乎Docker-Compose是一个在单个主机上创建多个容器的工具,而Docker Swarm是一个可以完全相同但具有更多控制权的工具,并且在Docker Stack的帮助下可以在多个主机上完成.我浏览了教程,也遇到了这个帖子:

docker-compose.yml vs docker-stack.yml what difference?

而且我得出的结论是,当你可以将Docker Swarm与Docker Stack一起使用时,没有理由使用Docker-Compose.他们甚至可以使用相同的docker-compose.yml.

似乎Docker-compose出现在swarm和堆栈之前,并且可能是swarm堆栈的新解决方案使得compose过时,但它仍然是遗留原因.这个想法是否正确?如果没有,在构建开发或生产环境方面,Docker-Compose对Docker Swarm和Docker Stack有什么好处?

最佳答案

It seems that Docker-compose came before the swarm and stack and maybe the new solution of swarm + stack makes compose obsolete,but it still remains for legacy reasons. Is this thinking correct?

简而言之,是的. Compose在所有Swarm之前出现(它起源于名为fig的第三方实用程序).更糟糕的是,甚至还有两个不同的Swarms,旧的Swarm(一个是单独的工具)和Swarm模式(这些日子内置于docker二进制文件中).

它似乎正在演变为内置于Docker中的服务和部署概念.但我猜想Docker Compose和Swarm Mode部署的东西会并存一段时间.

知道Docker Compose基础是一个名为libcompose(https://github.com/docker/libcompose)的库是有益的,其他第三方实用程序使用它来支持用于部署的docker-compose.yml文件格式(参见Rancher和rancher-compose作为示例) .我想他们会努力继续支持libcompose.

我不清楚Docker Swarm部署的东西是否实际上使用了libcompose.在我粗略的搜索中,Swarm模式似乎没有实现libcompose并且做了自己的事情.我不确定这与Docker Compose和libcompose的未来有何关系.你认为合适的解释……

Docker in Docker(实际上是 Docker outside Docker): /var/run/docker.sock

Docker in Docker(实际上是 Docker outside Docker): /var/run/docker.sock

在 Docker 容器里面使用 docker run/docker build

Docker 容器技术目前是微服务/持续集成/持续交付领域的第一选择。而在 DevOps 中,我们需要将各种后端/前端的测试/构建环境打包成 Docker 镜像,然后在需要的时候,Jenkins 会使用这些镜像启动容器以执行 Jenkins 任务。

为了方便维护,我们的 CI 系统如 Jenkins,也会使用 Docker 方式部署。 Jenkins 任务中有些任务需要将微服务构建成 Docker 镜像,然后推送到 Harbor 私有仓库中。 或者我们所有的 Jenkins Master 镜像和 Jenkins Slave 镜像本身都不包含任何额外的构建环境,执行任务时都需要启动包含对应环境的镜像来执行任务。

我们的 Jenkins Master、Jenkins Slaves 都是跑在容器里面的,该如何在这些容器里面调用 docker run 命令启动包含 CI 环境的镜像呢? 在这些 CI 镜像里面,我们从源码编译完成后,又如何通过 docker build 将编译结果打包成 Docker 镜像,然后推送到内网仓库呢?

答案下面揭晓。

一、原理说明:/var/run/docker.sock

Docker 采取的是 Client/Server 架构,我们常用的 docker xxx 命令工具,只是 docker 的 client,我们通过该命令行执行命令时,实际上是在通过 client 与 docker engine 通信。

我们通过 apt/yum 安装 docker-ce 时,会自动生成一个 systemd 的 service,所以安装完成后,需要通过 sudo systemctl enable docker.service 来启用该服务。 这个 Docker 服务启动的,就是 docker engine,查看 /usr/lib/systemd/system/docker.service,能看到有这样一条语句:

ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

默认情况下,Docker守护进程会生成一个 socket(/var/run/docker.sock)文件来进行本地进程通信,因此只能在本地使用 docker 客户端或者使用 Docker API 进行操作。 sock 文件是 UNIX 域套接字,它可以通过文件系统(而非网络地址)进行寻址和访问。

因此只要以数据卷的形式将 docker 客户端和上述 socket 套接字挂载到容器内部,就能实现 "Docker in Docker",在容器内使用 docker 命令了。具体的命令见后面的「示例」部分。

要记住的是,真正执行我们的 docker 命令的是 docker engine,而这个 engine 跑在宿主机上。所以这并不是真正的 "Docker in Docker".

二、示例

在容器内部使用宿主机的 docker,方法有二:

  1. 命令行方式:将 /usr/bin/docker 映射进容器内部,然后直接在容器内部使用这个命令行工具 docker
    • 需要的时候,也可以将 /etc/docker 文件夹映射到容器内,这样容器内的 docker 命令行工具也会使用与宿主机同样的配置。
  2. 编程方式:在容器内部以编程的方式使用 docker
    • 通过 python 使用 docker: 在 Dockerfile 中通过 pip install docker 将 docker client 安装到镜像中来使用

容器的启动方式也有两种,如下:

1. 直接通过 docker 命令启动

示例命令如下:

docker run --name <name> \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v /usr/bin/docker:/usr/bin/docker \
    --user root \
    <image-name>:<tag>

**必须以 root 用户启动!(或者其他有权限读写 /var/run/docker.sock 的用户)**然后,在容器内就能正常使用 docker 命令,或者访问宿主机的 docker api 了。

2. 使用 docker-compose 启动

docker-compose.yml 文件内容如下:

version: ''3.3''
services:
  jenkins-master:
    image: jenkinsci/blueocean:latest
    container_name: jenkins-master
    environment:
      - TZ=Asia/Shanghai  # 时区
    ports:
      - "8080:8080"
      - "50000:50000"
    volumes:
      - ./jenkins_home:/var/jenkins_home  # 将容器中的数据映射到宿主机
      - /usr/bin/docker:/usr/bin/docker  # 为容器内部提供 docker 命令行工具(这个随意)
      - /var/run/docker.sock:/var/run/docker.sock  # 容器内部通过 unix socket 使用宿主机 docker engine
    user: root  # 必须确保容器以 root 用户启动!(这样它才有权限读写 docker.socket)
    restart: always

然后通过 docker-compose up -d 即可后台启动容器。

Docker 中的 uid 与 gid

通过上面的操作,我们在容器内执行 docker ps 时,还是很可能会遇到一个问题:权限问题

如果你容器的默认用户是 root,那么你不会遇到这个问题,因为 /var/run/docker.sock 的 onwer 就是 root.

但是一般来说,为了限制用户的权限,容器的默认用户一般都是 uid 和 gid 都是 1000 的普通用户。这样我们就没有权限访问 /var/run/docker.sock 了。

解决办法:

方法一(不一定有效):在构建镜像时,最后一层添加如下内容:

# docker 用户组的 id,通常都是 999
RUN groupadd -g 999 docker \
    && usermod -aG docker <your_user_name>

这样我们的默认用户,就能使用 docker 命令了。

P.S. 999 不一定是 docker 用户组,所以上述方法某些情况下可能失效。这时还是老老实实通过 docker run -u root 启动容器吧。(或者在 docker-compose.yml 中添加 user: root 属性)

参考

  • Docker in Docker - 王柏元

今天关于从「集装箱」思考 Docker 风潮集装箱 chrome的讲解已经结束,谢谢您的阅读,如果想了解更多关于167 docker docker构建nginx容器系列问题 docker registry docker run docker toolbo、Docker 04 应用部署与迁移备份 Dockerfile 与 Docker 私有仓库、Docker Compose比Docker Swarm和Docker Stack有什么好处?、Docker in Docker(实际上是 Docker outside Docker): /var/run/docker.sock的相关知识,请在本站搜索。

本文标签:

上一篇用 Docker 构建分布式 Redis 集群(docker搭建redis集群)

下一篇.NET Core 使用 Consul 服务注册发现(.net 服务注册与发现)