架构和工作原理 ##################### 基本概念 ========== **应用程序** 一个可以在新浪云容器平台上运行的应用程序包含以下两个部分: - 源代码。可以是NodeJS、Ruby、Java等代码。 - 依赖描述文件。描述了运行应用程序需要的相关依赖包以及如何运行应用程序。 **构建程序** 构建程序将用户提交的应用程序代码编译为Docker镜像。 **镜像** 镜像是你的应用程序+依赖包+基础运行环境,在新浪云容器平台上也就是Docker镜像,打包好的镜像可以在容器中运行。 所有部署到新浪云容器平台的应用程序会被打包成镜像分发到容器去运行。 **容器** 应用程序的运行实例运行在一个一个容器中,容器将一个一个的应用隔离开来。新浪云容器平台使用 `Docker `_ 作为容器来运行应用程序。 **应用实例** 也就是你的应用程序运行的进程,其运行在服务器上的一个一个容器中,接受负载均衡路由过来的HTTP请求并处理。 .. image:: ./images/basic-flow.png 镜像构建 ============ 当你在新浪云容器的管理页面中点击 *部署* 的时候,服务端会导出你提交到应用仓库的代码,调用构建程序将应用程序构建为Docker镜像,构建的过程大致如下(包括但不限于): - 初始化一个基础运行环境(目前是 `debian:jessie `_ )。 - 检测应用程序使用的语言。 - 安装对应语言的运行环境(如NodeJS会安装node、npm等程序)。 - 安装应用程序指定的依赖库(如NodeJS会执行npm install安装所有的依赖)。 - 如有必要编译你的应用程序(如Python语言会将.py文件编译为.pyc文件)。 - 执行一些和语言以及web框架相关的脚本(如Python语言的Django框架的collectstatic程序)。 - 将以上所有打包为一个Docker镜像。 我们尽力让您可以将提交到git仓库中代码在不做额外修改的情况下直接部署到新浪云容器平台上(只需添加一个git remote以及一次git push)。而不需要去额外的编写Dockerfile或者新浪云平台专属的配置文件。让您可以专心于应用的开发上,而不是其它繁琐的部署细节。因此每个语言的构建程序都是遵循了该语言的开发者的常用开发模式。 比如,当构建程序检测到应用是NodeJS应用的时候,它会读取应用根目录下的package.json文件,执行npm install安装所有的依赖包,并取其中指定的命令作为应用实例运行的命令。 当然,如果用到和新浪云相关的一些服务或者需要手工指定一些配置时,还是会需要配置一些特殊的配置文件(后文会描述)。 应用程序运行 ============== 镜像构建完后会上传到一个镜像仓库中。然后云容器管理平台会根据用户的设置选择一些服务器去运行这些应用程序。服务器收到运行应用程序的指令后,会按照以下步骤来运行应用程序: - 从镜像仓库下载应用的镜像。 - 创建一个新的容器,将应用的镜像解压到该容器中。 - 在容器中执行应用程序指定的命令启动应用实例。 这个应用实例需要监听在0.0.0.0这个interface上,并且监听环境变量PORT指定的端口(默认为5050),处理前端负载均衡转发过来的HTTP请求。 云容器管理平台会监控各个服务器的状态,如果有服务器宕机,会立刻将这个机器上所有的应用实例迁移到其它运行正常的机器上。 .. warning:: 很多web框架自带的运行程序默认监听在localhost(127.0.0.1)上,这会导致应用程序的运行实例收不到任何请求,请监听在0.0.0.0这个interface上。 HTTP请求路由 =============== 新浪云平台前端的负载均衡会将一个应用的请求转发到其对应的应用程序实例指定的端口上。默认采用Round-Robin策略,并且请求一个upstream失败的情况下会将请求转发到其它upstream去。 日志 ============== 应用运行示例产生的标准输出(stdout)和标准错误输出(stderr)会被发送到新浪云的日志中心中,你可以在容器云的管理平台的日志页面里查看这些日志。 .. _Procfile: Procfile ============== 应用可以通过代码根目录下的 ``Procfile`` 文件指定在容器中运行的程序命令。 ``Procfile`` 文件每一行声明一条需要运行的命令,格式如下: :: name: command 目前name仅支持 ``web`` , 也就是web进程,前端负载均衡的请求会被转发给运行这些命令的容器。 比如一个Rail程序可以使用以下命令来启动其Web进程: :: web: bundle exec rails server -p $PORT 本地文件系统 =================== 每个运行的容器都有一个本地文件系统。 - 写入这个本地文件系统的文件只有写入的进程以及其所在容器中的其它进程可以读取。 - 这些文件是 **非持久化** 的,如果容器中的应用程序进程异常退出,容器云会再创建一个新的容器,这个容器中是没有之前写入的那些文件的。 如果你有需要持久化的数据或者需要在容器之间共享数据,建议使用 :doc:`共享存储 ` ,数据库、云存储等服务。