深入浅出Docker

978-7-115-50489-0
作者: 【英】Nigel Poulton(奈吉尔 波尔顿)
译者: 李瑞丰刘康
编辑: 陈聪聪

图书目录:

详情

本书是一本Docker入门图书,共分为17章,将每个元素分成不同的部分,然后将这些部分分解为简短的摘要,深入的分析以及相关的命令。如果您只是在寻找复习课程,这可以提供更好的理解和快速参考指南。新版在内容上进行了充实和完善,帮助读者更加深刻地认识Docker。本书适合开源容器服务Docker感兴趣的开发人员、Docker的初学者阅读。

图书摘要

版权信息

书名:深入浅出Docker

ISBN:978-7-115-50489-0

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。


著    [英] 奈吉尔•波尔顿(Nigel Poulton)

译    李瑞丰  刘 康

责任编辑 陈聪聪

人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

读者服务热线:(010)81055410

反盗版热线:(010)81055315


Simplified Chinese translation copyright ©2018 by Posts and Telecommunications Press

All rights reserved.

Docker Deep Dive, by Nigel Poulton, ISBN 9781521822807

Copyright © 2018 by Nigel Poulton

本书中文简体版由作者授权人民邮电出版社出版。未经出版者书面许可,对本书的任何部分不得以任何方式或任何手段复制和传播。

版权所有,侵权必究。


本书是一本Docker入门图书,全书分为17章,从Docker概览和Docker技术两部分进行全面解析,深入浅出地介绍了Docker的相关知识,清晰详细的操作步骤结合大量的实际代码帮助读者学以致用,将Docker知识应用到真实的项目开发当中。

本书适合对Docker感兴趣的入门新手、Docker技术开发人员以及运维人员阅读,本书也可作为Docker认证工程师考试的参考图书。

教育激励并且创造机会。

我希望这本书,以及我所有的视频培训课程,能够启发您,创造新的机会!

非常感谢我的妻子和孩子们忍受了家里的一个极客——我认为自己是一群在中端生物硬件之上并运行在容器内的软件。和我生活在一起真的很不容易!

非常感谢每一个观看我的Pluralsight视频的人。我很乐意与你们交流,感谢这么多年来大家给我的反馈,这促使我决定写这本书!我希望它帮助你,从而推动你的事业发展。

如果你打算参加DCA考试——祝你好运!

@nigelpoulton


这是一本关于Docker的图书。本书的宗旨是从零开始学习Docker,因此读者无须任何前置知识储备。

本书非常适合对Docker感兴趣,希望了解Docker工作原理以及如何正确使用Docker的读者。

如果只是学习Docker的使用方法,而不关心其内部实现机制,则本书并适合。

Docker于2017年秋发布了第1版专业资质认证,称为Docker认证工程师(Docker Certified Associate, DCA),面向想要评估自身Docker管理水平的人群。

本书覆盖了认证考试的所有知识点,但本书并非应试书,而是一本易于阅读的实用技术图书。

祝愿读者考试顺利!

虽然现如今电子书非常棒,但我依然钟情于油墨与纸张,当然这并无冒犯Leanpub和亚马逊Kindle之意。所以,本书的英文纸质版本在亚马逊有售(并非黑白版)。

说到亚马逊,我非常希望收到读者在亚马逊上对本书的评价,当然也包括在Leanpub上购买本书的读者的评价。感谢!

如今Docker无处不在,这是不争的事实。开发人员都很喜欢它,运维工程师也需要它。他们都需要深入了解如何在关键业务环境中构建和维护符合生产级别要求的容器化应用,本书将帮助读者掌握它。

对于认为Docker是开发人员专属工具的人来说,恐怕要准备好颠覆自己的认知了。

容器化应用需要有地方运行,也需要有人来管理。如果认为只是开发人员来管理它,那就大错特错了,事实上运维需要构建和运行高性能、生产级别的Docker基础架构。对于专注于运维工作却尚未掌握Docker的朋友来说,日子恐怕不太好过。不过不必焦虑,本书将帮你掌握Docker。

本书分为两部分。

Docker技术篇的多数章节都可以分为3个部分——简介、详解和命令。

“简介”部分是大约两三段的简要介绍,用于概括性地阐述相应章节的内容,也能够方便读者在复习时快速回忆相关的内容。

“详解”部分会详细介绍工作原理,并配有示例的介绍。

“命令”部分会以一种易于阅读的方式列出所有相关命令及其简要说明。

希望读者能够喜欢这种方式。


本书由异步社区出品,社区(https://www.epubit.com/)为您提供相关资源和后续服务。

本书提供如下资源:

本书配套资源请到异步社区本书购买页处下载。

要获得以上配套资源,请在异步社区本书页面中点击,跳转到下载界面,按提示进行操作即可。注意:为保证购书读者的权益,该操作会给出相关提示,要求输入提取码进行验证。

作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。

当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,点击“提交勘误”,输入勘误信息,点击“提交”按钮即可。本书的作者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。

我们的联系邮箱是contact@epubit.com.cn。

如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。

如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者也可以到异步社区在线提交投稿(直接访问www.epubit.com/selfpublish/submission即可)。

如果您是学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。

如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接发邮件给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。

“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT技术图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT技术图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。

“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近30年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、AI、测试、前端、网络技术等。

异步社区

微信服务号



现在容器无疑成为了一种潮流,为了让读者更加全面地了解Docker,本书就从容器的发展之路开始娓娓道来。

本章主要向读者介绍如下内容。

业务是基于应用(Application)运转的。如果应用出现故障,业务也就无法正常运行,甚至会导致商业公司的破产。这种情况是真实的,甚至每天都在发生。

大部分应用是运行在服务器之上的。曾经,每个服务器只能运行单一应用。Windows和Linux操作系统都没有相应的技术手段来保证在一台服务器上稳定而安全地同时运行多个应用。

在那个时代,经常会出现这样一幕:每次业务部门想要增加一个新的应用时,IT部门就需要去采购一个新的服务器。大部分情况下,没有人知道新增应用所需的服务器性能究竟是怎样的,这意味着IT部门需要凭借经验去猜测所购买的服务器型号和规格。

因此,IT部门在采购的时候就不得不买那些性能大幅优于业务需求的服务器。毕竟无论是IT部门还是业务部门,都不想看到服务器性能不足的情况出现。因为服务器性能不足,可能会导致某些交易失败,而交易失败会使得公司客户流失、收益下降,所以IT部门通常采购的都是更大、更好的服务器。这种做法导致了大部分服务器长期运行在他们额定负载5%~10%的水平区间之内。这对公司资产和资源是一种极大的浪费!

为了解决上面的问题,VMware公司给全世界带来了一个礼物——虚拟机(VM)。然后几乎是一夜之间,世界就变得美好了!人们终于拥有了一种允许多应用能够稳定、安全地同时运行在一个服务器中的技术。

虚拟机是一种具有划时代意义的技术!每当业务部门需要增加应用的时候,IT部门无须采购新的服务器。取而代之的是,IT部门会尝试在现有的,并且有空闲性能的服务器上部署新的应用。

突然之间,人们发现这种技术能够让现有的资产(如服务器)拥有更大的价值,从而最终为公司节省大量的资金支出。

但是……总有这么一个但是!就连VM这么伟大的技术,也远未做到十全十美!

实际上,虚拟机最大的缺点就是依赖其专用的操作系统(OS)。OS会占用额外的CPU、RAM和存储,这些资源本可以用于运行更多的应用。每个OS都需要补丁和监控。另外在某些情况下,OS需要许可证才能运行。这对运营成本(OPEX)和资金性支出(CAPEX)都是一种浪费。

虚拟机技术也面临着一些其他挑战。比如虚拟机启动通常比较慢,并且可移植性比较差——虚拟机在不同的虚拟机管理器(Hypervisor)或者云平台之间的迁移要远比想象中困难。

长期以来,像谷歌(Google)这样的大规模Web服务(Big Web-Scale)玩家一直采用容器(Container)技术解决虚拟机模型的缺点。

容器模型其实跟虚拟机模型相似,其主要的区别在于,容器的运行不会独占操作系统。实际上,运行在相同宿主机上的容器是共享一个操作系统的,这样就能够节省大量的系统资源,如CPU、RAM以及存储。容器同时还能节省大量花费在许可证上的开销,以及为OS打补丁等运维成本。最终结果就是,容器节省了维护成本和资金成本。

同时容器还具有启动快和便于迁移等优势。将容器从笔记本电脑迁移到云上,之后再迁移到数据中心的虚拟机或者物理机之上,都是很简单的事情。

现代的容器技术起源于Linux,是很多人长期努力持续贡献的产物。举个例子,Google LLC就贡献了很多容器相关的技术到Linux内核当中。没有大家的贡献,就没有现在的容器。

近几年来,对容器发展影响比较大的技术包括内核命名空间(Kernel Namespace)控制组(Control Group)联合文件系统(Union File System),当然更少不了Docker。再次强调一遍,当今的容器生态环境很大程度上受益于强大的基金会,而基金会是由很多独立开发者以及公司组织共同创建并维护的。感谢你们!

虽然容器技术已经如此出色,但对于大部分组织来说,容器技术的复杂度是阻止其实际应用的主要原因。直到Docker技术横空出世,容器才真正被大众所接受。

 

注:  

有很多跟容器类似的操作系统虚拟化技术要早于Docker和现代容器技术出现,有些甚至可以追溯到大型机上的System/360操作系统当中。BSD Jails和Solaris Zones也是在类UNIX操作系统上众所周知的容器化技术。但本书讨论内容范围主要会限制在由Docker主导的现代容器技术之中。

 

本书会在第2章中讨论更多有关Docker的细节。但在这里,不得不感叹Docker确实是使Linux容器技术得到广泛应用的技术。换个角度来说,是Docker这家公司使容器变得简单。

在过去的几年中,微软(Microsoft Corp.)致力于Docker和容器技术在Windows平台的发展。

在本书成稿之际,Windows容器已经能在Windows 10和Windows Server 2016平台上使用了。为了实现这个目标,微软跟Docker公司、社区展开了深入合作。

实现容器所需的核心Windows内核技术被统称为Windows容器(Windows Container)。用户空间是通过Docker来完成与Windows容器之间交互的,这使得Docker在Windows平台上的使用体验跟在Linux上几乎一致。那些熟悉Linux Docker工具的研发人员和系统管理员,在切换到Windows容器之后也会很快适应。

本书修订版的大部分练习都包含了Linux和Windows的示例。

运行中的容器共享宿主机的内核,理解这一点是很重要的。这意味着一个基于Windows的容器化应用在Linux主机上是无法运行的。读者也可以简单地理解为Windows容器需要运行在Windows宿主机之上,Linux容器(Linux Container)需要运行在Linux宿主机上。但是,实际场景要比这复杂得多……

在本书撰写过程中,在Windows机器上运行Linux容器已经成为可能。例如,Windows版Docker(由Docker公司提供的为Windows 10设计的产品)可以在Windows容器模式和Linux容器模式之间进行切换。这是一个正在快速发展的领域,如果读者想要了解,需要查阅 Docker 最新文档。

迄今为止,还没有出现Mac容器(Mac Container)。

但是读者可以在Mac系统上使用Docker for Mac来运行Linux容器。这是通过在Mac上启动一个轻量级Linux VM,然后在其中无缝地运行Linux容器来实现的。这种方式在开发人员中很流行,因为这样可以在Mac上很容易地开发和测试Linux容器。

Kubernetes是谷歌的一个开源项目,并且开源之后迅速成为容器编排领域的领头羊。有一种很流行的说法:Kubernetes是保证容器部署和运行的软件体系中很重要的一部分。

在本书撰写时,Kubernetes已经采用Docker作为其默认容器运行时(container runtime),包括Kubernetes启动和停止容器,以及镜像的拉取等。但是,Kubernetes也提供了一个可插拔的容器运行时接口CRI。CRI能够帮助Kubernetes实现将运行时环境从Docker快速替换为其他容器运行时。在未来,Kubernetes中的默认容器运行时可能由Docker替换为containerd。关于containerd在本书后续部分有更详细的介绍。

关于Kubernetes,读者现在需要了解的就是——Kubernetes是Docker之上的一个平台,现在采用Docker实现其底层容器相关的操作。

可以通过阅读我Kubernetes的图书,以及观看Getting Started with Kubernetes视频课程来进一步了解Kubernetes的相关内容。

在过去,每当业务部门想运行新的应用时,IT部门就需要购买新的服务器来满足需求。接下来VMware的出现终结了这个时代,使得IT部门可以更高效地利用现有的和新的机器资源,产生更大的价值。但即使VMware和虚拟机模型这么优秀的技术,也存在其缺点。在VMware和Hypervisor成功之后,出现了更高效并且更轻量级的虚拟化技术——容器。但容器技术在发展之初是很难应用于生产环境的,并且只在拥有Linux内核工程师的Web巨头的数据中心内才能看到实际应用。接下来Docker公司出现了,突然之间容器虚拟化技术开始被大众广泛使用。

说到Docker,接下来就请读者跟随本书一起,来了解Docker是什么,以及为什么要使用Docker吧!


关于容器技术的图书和探讨总是不可避免地涉及Docker。但是当有人提到“Docker”时,可能是指如下3种概念之一。

如果读者希望在容器的世界中有所作为,那么需要对以上3个内容都有所了解。

Docker是一种运行于Linux和Windows上的软件,用于创建、管理和编排容器。Docker是在GitHub上开发的Moby开源项目的一部分。Docker公司,位于旧金山,是整个Moby开源项目的维护者。Docker公司还提供包含支持服务的商业版本的Docker。

以上是一个简要介绍。下面针对每个概念进行详细介绍。此外还包含对容器生态的探讨,以及对开放容器计划(Open Container Initiative, OCI)的介绍。

Docker公司位于旧金山,由法裔美籍开发者和企业家Solumon Hykes创立,其标志如图2.1所示。

有意思的是,Docker公司起初是一家名为dotCloud的平台即服务(Platform-as-a-Service, PaaS)提供商。底层技术上,dotCloud平台利用了Linux容器技术。为了方便创建和管理这些容器,dotCloud开发了一套内部工具,之后被命名为“Docker”。Docker就是这样诞生的!

2013年,dotCloud的PaaS业务并不景气,公司需要寻求新的突破。于是他们聘请了Ben Golub作为新的CEO,将公司重命名为“Docker”,放弃dotCloud PaaS平台,怀揣着“将Docker和容器技术推向全世界”的使命,开启了一段新的征程。

如今Docker公司被普遍认为是一家创新型科技公司,据说其市场价值约为10亿美元。在本书撰写时,Docker公司已经通过多轮融资,吸纳了来自硅谷的几家风投公司的累计超过2.4亿美元的投资。几乎所有的融资都发生在公司更名为“Docker”之后。

图2.1 Docker标志

公司更名为Docker之后,进行了几次小规模的未公开价格的收购,来丰富其产品和服务组合。

至本书撰写时,Docker公司拥有约300~400名雇员,并举办名为DockerCon的年度会议。DockerCon的目标是聚拢不断发展的容器生态,并促进Docker和容器技术的推广。

本书将始终使用“Docker公司”来指代Docker这家公司,其他地方出现的“Docker”都是指容器技术或开源项目。

 

注: 

“Docker”一词来自英国口语,意为码头工人(Dock Worker),即从船上装卸货物的人。

 

多数技术人员在谈到Docker时,主要是指Docker引擎。

Docker引擎是用于运行和编排容器的基础设施工具。有VMware管理经验的读者可以将其类比为ESXi。ESXi是运行虚拟机的核心管理程序,而Docker引擎是运行容器的核心容器运行时。

其他Docker公司或第三方的产品都是围绕Docker引擎进行开发和集成的。如图2.2所示,Docker引擎位于中心,其他产品基于Docker引擎的核心功能进行集成。

Docker引擎可以从Docker网站下载,也可以基于GitHub上的源码进行构建。无论是开源版本还是商业版本,都有Linux和Windows版本。

在本书撰写时,Docker引擎主要有两个版本:企业版(EE)和社区版(CE)。

每个季度,企业版和社区版都会发布一个稳定版本。社区版本会提供4个月的支持,而企业版本会提供12个月的支持。

社区版还会通过Edge方式发布月度版。

图2.2 围绕Docker引擎进行开发和集成的产品

从2017年第一季度开始,Docker版本号遵循YY.MM-xx格式,类似于Ubuntu等项目。例如,2018年6月第一次发布的社区版本为18.06.0-ce。

 

注: 

2017年第一季度以前,Docker版本号遵循大版本号.小版本号的格式。采用新格式前的最后一个版本是Docker 1.13。

 

“Docker”一词也会用于指代开源Docker项目。其中包含一系列可以从Docker官网下载和安装的工具,比如Docker服务端和Docker客户端。不过,该项目在2017年于Austin举办的DockerCon上正式命名为Moby项目。由于这次改名,GitHub上的docker/docker库也被转移到了moby/moby,并且拥有了项目自己的Logo,如图2.3所示。

图2.3 Moby的Logo

Moby项目的目标是基于开源的方式,发展成为Docker上游,并将Docker拆分为更多的模块化组件。Moby项目托管于GitHub的Moby代码库,包括子项目和工具列表。核心的Docker引擎项目位于GitHub的moby/moby,但是引擎中的代码正持续被拆分和模块化。

作为一个开源项目,其源码是公开可得的,在遵循Apache协议2.0的情况下,任何人都可以自由地下载、贡献、调整和使用。

如果查看项目的提交历史,可以发现其中包含来自如下公司的基础技术:红帽、微软、IBM、思科,以及HPE。此外,还可以看到一些并非来自大公司的贡献者。

多数项目及其工具都是基于Golang编写的,这是谷歌推出的一种新的系统级编程语言,又叫Go语言。使用Go语言的读者,将更容易为该项目贡献代码。

Mody/Docker作为开源项目的好处在于其所有的设计和开发都是开放的,并摒弃了私有代码闭源开发模式下的陈旧方法。因此发布过程也是公开进行的,不会再出现某个秘密的版本提前几个月就宣布要召开发布会和庆功会的荒唐情况。Moby/Docker不是这样运作的,项目中多数内容都是开放并欢迎任何人查看和作出贡献的。

Moby项目以及更广泛的Docker运动一时间掀起了一波热潮。GitHub上已经有数以千计的提交请求(pull request),以及数以万计的基于容器化技术的项目了,更不用说Docker Hub上数十亿的镜像下载。Moby项目已经给软件产业带来了翻天覆地的变化。

这并非妄想,Docker已经得到了广泛的应用!

Docker公司的一个核心哲学通常被称为“含电池,但可拆卸”(Batteries included but removable)。

意思是许多Docker内置的组件都可以替换为第三方的组件,网络技术栈就是一个很好的例子。Docker核心产品内置有网络解决方案。但是网络技术栈是可插拔的,这意味着Docker内置的网络方案可以被替换为第三方的方案。许多人都会这样使用。

早期的时候,经常出现第三方插件比 Docker 提供的内置组件更好的情况。然而这会对Docker公司的商业模式造成冲击。毕竟,Docker公司需要依靠盈利来维持基业长青。因此,“内置的电池”变得越来越好用了。这也导致了生态内部的紧张关系和竞争的加剧。

简单来说,Docker内置的“电池”仍然是可插拔的,然而越来越不需要将它们移除了。

尽管如此,容器生态在一种良性的合作与竞争的平衡中还是得以繁荣发展。在谈及容器生态时,人们经常使用到诸如“co-opetition”[1]与“frenemy”[2]这样的字眼。这是一个好现象!因为良性的竞争是创新之母

如果不谈及开放容器计划(The Open Container Initiative, OCI)的话,对Docker和容器生态的探讨总是不完整的。图2.4所示为OCI的Logo。

图2.4 OCI的Logo

OCI是一个旨在对容器基础架构中的基础组件(如镜像格式与容器运行时,如果对这些概念不熟悉的话,不要担心,本书后续会介绍到它们)进行标准化的管理委员会。

同样,如果不谈历史的话,对OCI的探讨也是不完整的。和所有的历史记录一样,其版本取决于谁来讲述它。所以,以下是我眼中的容器历史。

我讲述的这段简短的历史是,一个名为CoreOS的公司不喜欢Docker的某些行事方式。因此它就创建了一个新的开源标准,称作“appc”,该标准涉及诸如镜像格式和容器运行时等方面。此外它还开发了一个名为rkt(发音“rocket”)的实现。

两个处于竞争状态的标准将容器生态置于一种尴尬的境地。

这使容器生态陷入了分裂的危险中,同时也令用户和消费者陷入两难。虽然竞争是一件好事,但是标准的竞争通常不是。因为它会导致困扰,降低用户接受度,对谁都无益。

考虑到这一点,所有相关方都尽力用成熟的方式处理此事,共同成立了OCI——一个旨在管理容器标准的轻量级的、敏捷型的委员会。

在本书写作时,OCI已经发布了两份规范(标准):镜像规范和运行时规范。

提到这两项标准时,经常用到的比喻就是铁轨。它们就像对铁轨的尺寸和相关属性达成一致,让所有人都能自由地建造更好的火车、更好的车厢、更好的信号系统、更好的车站等。只要各方都遵循标准就是安全的。没人会希望在铁轨尺寸问题上存在两个相互竞争的标准!

公平地说,这两个OCI规范对Docker的架构和核心产品设计产生了显著影响。Docker 1.11版本中,Docker引擎架构已经遵循OCI运行时规范了。

到目前为止,OCI已经取得了不错的成效,将容器生态团结起来。然而,标准总是会减慢创新的步伐!尤其是对于超快速发展的新技术来说更是如此。这在容器社区引起了热烈的讨论。以我之见,这是好事!容器技术正在重塑世界,走在技术前列的人们有热情、有想法,这很正常。期待关于标准和创新有更加热烈的讨论!

OCI在Linux基金会的支持下运作,Docker公司和CoreOS公司都是主要贡献者。

本章介绍了Docker公司,这是一家位于旧金山的立志于变更软件行业的科技创业公司。可以说他们是现今容器革命的先行者和推动者。但是现在已经形成了一个由作者和竞争者组成的大型生态。

Docker项目是开源的,其上游源码位于GitHub的moby/moby库。

开放容器计划(OCI)在容器运行时格式和容器镜像格式的标准化方面发挥了重要作用。

[1] 意即合作与竞争,英文中co-operation与competition合并的词。——译者注

[2] 英文中朋友friend与敌人enemy合并的词。——译者注


相关图书

Kubernetes零基础实战
Kubernetes零基础实战
Kubernetes快速入门(第2版)
Kubernetes快速入门(第2版)
云原生测试实战
云原生测试实战
深入浅出Windows API程序设计:核心编程篇
深入浅出Windows API程序设计:核心编程篇
深入浅出Windows API程序设计:编程基础篇
深入浅出Windows API程序设计:编程基础篇
云原生技术中台:从分布式到云平台设计
云原生技术中台:从分布式到云平台设计

相关文章

相关课程