Funfile 功能介绍

前言

首先介绍下在本文出现的几个比较重要的概念:

函数计算(Function Compute): 函数计算是一个事件驱动的服务,通过函数计算,用户无需管理服务器等运行情况,只需编写代码并上传。函数计算准备计算资源,并以弹性伸缩的方式运行用户代码,而用户只需根据实际代码运行所消耗的资源进行付费。函数计算更多信息 参考
Fun: Fun 是一个用于支持 Serverless 应用部署的工具,能帮助您便捷地管理函数计算、API 网关、日志服务等资源。它通过一个资源配置文件(template.yml),协助您进行开发、构建、部署操作。Fun 的更多文档 参考

备注: 本文介绍的技巧需要 Fun 版本大于等于 3.0.0+。

Funfile 是什么

就如同 Dockerfile 用于构造 docker 镜像,Funfile 可以用于构造函数计算的交付产物。

Funfile 中包含了一系列的命令,这些命令相当于构造函数计算交付产物一个个“步骤”,Fun 会忠实地执行这些步骤,最终产出“交付产物”。

初始化 Funfile 文件

Funfile 文件可以通过执行 fun install init 完成初始化创建。执行 fun install init,会让选择函数运行时:

$fun install init

? Select a runtime
  nodejs6
  nodejs8
 nodejs10
  python2.7
  python3
  java8
  php7.2
(Move up and down to reveal more choices)

比如,这里选择 nodejs10 后,会在当前目录生成一个名为 Funfile 的文件,内容为:

RUNTIME nodejs10

由于 Funfile 就是一个文本文件,不使用 fun 进行初始化,直接创建一个名为 Funfile 的文件,然后填写相应的内容也是可以的。

使用 Funfile 进行构建

无论是使用 fun install、还是 fun build,当操作的函数目录*存在 Funfile 时,都会自动执行 Funfile 的构建。

Funfile 的使用体验

举个简单场景的例子,比如要安装一个 pip 的 flask 库。除了我们在《开发函数计算的正确姿势 —— 依赖安装小结》中介绍的一些方法外,也可以通过 Funfile 进行安装。

首先第一行通过 RUNTIME 指定要安装的依赖所服务的函数 runtime,可以是 python3、python2.7、nodejs8 等等。

然后,后续的命令直接编写相关命令即可,这里只需要对 apt-get 与 pip 的依赖特殊注意下,需要在这两个命令前加上 fun-install 前缀。比如,原来安装 flask 的命令为 pip install flask,现在只需要通过 fun-install pip install flask 即可。

Funfile 内容如下: 

RUNTIME python3
RUN fun-install pip install flask

执行 fun install,可以看到输出:

$ fun install

using template: template.yml
start installing function dependencies without docker

building pyzbar-srv/pyzbar-fun
Funfile exist, Fun will use container to build forcely
Step 1/2 : FROM aliyunfc/runtime-python3.6:build-1.6.1
 ---> 2110e9fa9393
Step 2/2 : RUN fun-install pip install flask
 ---> Using cache
 ---> 992b0d65136d
sha256:992b0d65136dfa63b9566b8280881bb4cf22c4f1b68155713545e4b61ada8dd9
Successfully built 992b0d65136d
Successfully tagged fun-cache-e95a9bfa-a6fa-4d70-b5b4-0084613e2b8d:latest
copying function artifact to /Users/tan/code/fun/examples/install/pyzbar_example

could not find any manifest file for pyzbar-srv/pyzbar-fun, [install] stage for manifest will be skipped

Tips for next step
======================
* Invoke Event Function: fun local invoke
* Invoke Http Function: fun local start
* Build Http Function: fun build
* Deploy Resources: fun deploy

fun install 安装的依赖,会被安装到代码目录,这时,可以通过 fun local 相关命令进行本地调试,也可以通过 fun deploy 一键部署到云端。

Funfile 支持的语法

Funfile 的能力与 Dockerfile 是等价的,Dockerfile 中支持的一些命令例如 COPY、RUN、ENV、USER、WORKDIR 等,Funfile 也都是支持的。比如,这里我们可以将函数目录的某个文件复制到容器执行一些操作:

RUNTIME nodejs8
COPY ./package.json .
RUN npm install

我们也可以拿更复杂的语法举例,比如在函数计算中安装 ralng 的例子,Funfile 内容如下:

RUNTIME python3
RUN fun-install apt-get install libblas3
RUN fun-install pip install pandas
RUN apt-get build-dep -y r-base; \
  curl -L https://fc-demo-public.oss-cn-hangzhou.aliyuncs.com/fun/examples/R-3.5.2.tar.gz | tar -zxf -; \
  cd R-3.5.2 ;  \
  ./configure --prefix=/code/.fun/R/ --enable-R-shlib --with-blas --with-lapack ;  \
  make ;  \
  make install;
RUN PATH=/code/.fun/R/bin:$PATH LD_LIBRARY_PATH=/code/.fun/root/usr/lib/libblas:$LD_LIBRARY_PATH fun-install pip install rpy2
RUN rm -rf R-3.5.2;  \
  rm -rf .fun/root/usr/share;  \
  rm -rf .fun/R/share;  \
  rm -rf .fun/R/lib/R/doc; \
  rm -rf .fun/python/lib/python3.6/site-packages/pandas/tests; \
  rm -rf .fun/R/lib/R/library/*/{help,demo,html,doc}; \
  find .fun -type f -name "*.so" -exec strip --strip-all {} \;

相比较于原生的 Dockerfile 命令,只需要将原来的 apt-get 以及 pip 安装的包前面加个 fun-install 的前缀。

Funfile 的兼容性

(未使用过 fun.yml 的用户可以忽略该内容。)

实际上,我们在 2.0+ 的版本,已经推出过类似的功能,即 fun.yml。Funfile 其实可以看作是 fun.yml 功能的升级,因为 fun.yml 支持的语法,Funfile 也都是支持的,而 Funfile 在原来的基础上,又新增了很多特性。3.0 版本,我们会统一从 fun.yml 迁移到 Funfile。

原先使用 fun.yml 的小伙伴,也不用担心,使用 fun install 功能时,如果我们检测到旧版本的 fun.yml 文件,我们会自动将 fun.yml 转换成等价的 Funfile。如果用户需要增加新的依赖,只需要修改 Funfile 的内容即可。

使用 Funfile 的优势

  1. 通过 Funfile 描述详细的依赖安装步骤,其实更有助于“标准化”开发流程。
  2. 通过将 Funfile 而不是将具体的某些依赖提交到版本控制系统中,也更有利于函数代码的维护。
  3. Funfile 的编写,更接近原生体验,结合 fun install sbox,可以先在交互式环境进行各种尝试,然后将最终安装步骤编写到 Funfile,这个类似与 Dockerfile 的编写。
  4. Funfile 也支持 Dockerfile 的 cache 功能,如果项目的改动对 Funfile 不影响,那么 Funfile 可以利用 cache 直接跳过相应的命令执行过程。这有助于加速 Funfile 的执行过程,提升开发效率。

下面是下载 rlang 依赖的例子,第一次执行编译,需要超过 30 分钟+ 才能编译好,之后再此执行,只要不修改 Funfile 的内容,都可以在 5s 内执行完成:

Funfile 功能介绍

上一篇:开发函数计算的正确姿势 —— 依赖安装方法一览


下一篇:轻松搭建基于 Serverless 的 Egg.js Web 应用