全部产品
云市场

使用 fun install 安装第三方依赖

更新时间:2019-12-27 20:50:04

前言

fun install 是 fun 工具的一个子命令,用于安装 pip 和 apt 依赖,提供了命令行接口和 Funfile 描述文件两种形式。

安装 pip 包依赖

下面的命令安装 python 的 tensorflow 包

  1. $ fun install --runtime python2.7 --package-type pip tensorflow
  2. skip pulling image aliyunfc/runtime-python2.7:build-1.2.0...
  3. Task => [UNNAMED]
  4. => PYTHONUSERBASE=/code/.fun/python pip install --user tensorflow

说明

  • --runtime 指定 runtime,如果已经初始化 fun.yml 文件, 由于 fun.yml 里声明了 runtime ,该选项可以省略。
  • --package-type 指定安装依赖的类型,pip 和 apt 是目前的两个可选值。
  • tensorflow 是一个 pip 包名。

命令执行在 fc-docker 提供的 container 中,容器内部执行的命令会逐行打印出来,比如上面命令中内部真实执行了 PYTHONUSERBASE=/code/.fun/python pip install --user tensorflow 命令。

安装完成以后会在生成一个 .fun 目录, 可执行文件会被放置到 .fun/python/bin 目录下,库文件放置到 .fun/python/lib/python2.7/site-packages 下。

  1. .fun
  2. └── python
  3. ├── bin
  4. ├── freeze_graph
  5. ├── markdown_py
  6. ├── pbr
  7. ├── saved_model_cli
  8. ├── tensorboard
  9. ├── tflite_convert
  10. ├── toco
  11. └── toco_from_protos
  12. └── lib
  13. └── python2.7
  14. └── site-packages
  15. ├── tensorboard
  16. ├── tensorboard-1.12.2.dist-info
  17. ├── tensorflow
  18. ├── tensorflow-1.12.0.dist-info
  19. ├── termcolor-1.1.0.dist-info
  20. ...

相比之前的 pip install -t . <package-name> 方式,fun install 安装文件的存放位置更有组织,依赖文件和代码文件分离开了,便于清理、拆分后借助 OSS 或 NAS 初始化依赖文件。但是组织过后也带来一个新问题,需要用户自定义环境变量库文件才能被程序找到。为了方便用户使用提供了一个 fun install env 打印出必要的环境变量。

  1. $ fun install env
  2. LD_LIBRARY_PATH=/code/.fun/root/usr/lib/x86_64-linux-gnu:/code:/code/lib:/usr/local/lib
  3. PATH=/code/.fun/root/usr/local/bin:/code/.fun/root/usr/local/sbin:/code/.fun/root/usr/bin:/code/.fun/root/usr/sbin:/code/.fun/root/sbin:/code/.fun/root/bin:/code/.fun/python/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/sbin:/bin
  4. PYTHONUSERBASE=/code/.fun/python

关于设定函数计算的环境变量,请参考文档环境变量 。如果您使用 fun localfun deploy 进行调试和部署,您无需关注环境变量问题,已经帮您设定好了。

使用 —save 持久化

install 命令加上 —save 参数,会将命令持久化保存到 Funfile 文件中。

  1. $ fun install --runtime python2.7 --package-type pip --save tensorflow
  2. skip pulling image aliyunfc/runtime-python2.7:build-1.2.0...
  3. Task => [UNNAMED]
  4. => PYTHONUSERBASE=/code/.fun/python pip install --user tensorflow

上面的命令多加了一行 --save 参数,查看 Funfile 内容:

  1. RUNTIME python2.7
  2. RUN fun-install pip install tensorflow

之后直接执行 fun install 不带参数,就可以依次执行任务。

  1. $ fun install
  2. skip pulling image aliyunfc/runtime-python2.7:build-1.2.0...
  3. Task => [UNNAMED]
  4. => PYTHONUSERBASE=/code/.fun/python pip install --user tensorflow

使用 -v 显示详细日志

  1. $ fun install -v
  2. skip pulling image aliyunfc/runtime-python3.6:build-1.2.0...
  3. Task => [UNNAMED]
  4. => apt-get update (if need)
  5. Ign http://mirrors.aliyun.com stretch InRelease
  6. Get:1 http://mirrors.aliyun.com stretch-updates InRelease [91.0 kB]
  7. Get:2 http://mirrors.aliyun.com stretch-backports InRelease [91.8 kB]
  8. Get:3 http://mirrors.aliyun.com stretch/updates InRelease [94.3 kB]
  9. Hit http://mirrors.aliyun.com stretch Release.gpg
  10. Hit http://mirrors.aliyun.com stretch Release
  11. Get:4 http://mirrors.aliyun.com stretch-updates/main Sources [3911 B]
  12. ....

安装 apt 包依赖

函数计算使用 apt-get 安装依赖是另一类常见的安装问题,使用 fun install 也可以方便的安装。

  1. $ fun install --runtime python3 --package-type apt libzbar0
  2. skip pulling image aliyunfc/runtime-python3.6:build-1.2.0...
  3. Task => [UNNAMED]
  4. => apt-get update (if need)
  5. => apt-get install -y -d -o=dir::cache=/code/.fun/tmp libzbar0
  6. => bash -c 'for f in $(ls /code/.fun/tmp/archives/*.deb); do dpkg -x $f /code/.fun/root; done;'
  7. => bash -c 'rm -rf /code/.fun/tmp/archives'

使用方法及其参数和 pip 包依赖类似,只需要将 --package-type 设定成 apt, 包名使用日常 apt-get 可以安装的 deb 包名即可。

使用 Funfile

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

初始化 Funfile 文件

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

  1. $fun install init
  2. ? Select a runtime
  3. nodejs6
  4. nodejs8
  5. nodejs10
  6. python2.7
  7. python3
  8. java8
  9. php7.2
  10. (Move up and down to reveal more choices)

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

  1. RUNTIME nodejs10

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

使用 Funfile 进行构建

无论是使用 fun install、还是 fun build,当操作的函数目录顶级存在 Funfile 时,都会自动执行 Funfile 的构建。举个简单场景的例子,比如要安装一个 pip 的 flask 库。首先第一行通过 RUNTIME 指定要安装的依赖所服务的函数 runtime,后续的命令直接编写相关命令即可,这里只需要对 apt-get 与 pip 的依赖特殊注意下,需要在这两个命令前加上 fun-install 前缀。比如,原来安装 flask 的命令为 pip install flask,现在只需要通过 fun-install pip install flask 即可。

Funfile 内容如下:

  1. RUNTIME python3
  2. RUN fun-install pip install flask

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

  1. $ fun install
  2. using template: template.yml
  3. start installing function dependencies without docker
  4. building pyzbar-srv/pyzbar-fun
  5. Funfile exist, Fun will use container to build forcely
  6. Step 1/2 : FROM aliyunfc/runtime-python3.6:build-1.6.1
  7. ---> 2110e9fa9393
  8. Step 2/2 : RUN fun-install pip install flask
  9. ---> Using cache
  10. ---> 992b0d65136d
  11. sha256:992b0d65136dfa63b9566b8280881bb4cf22c4f1b68155713545e4b61ada8dd9
  12. Successfully built 992b0d65136d
  13. Successfully tagged fun-cache-e95a9bfa-a6fa-4d70-b5b4-0084613e2b8d:latest
  14. copying function artifact to /Users/tan/code/fun/examples/install/pyzbar_example
  15. could not find any manifest file for pyzbar-srv/pyzbar-fun, [install] stage for manifest will be skipped
  16. Tips for next step
  17. ======================
  18. * Invoke Event Function: fun local invoke
  19. * Invoke Http Function: fun local start
  20. * Build Http Function: fun build
  21. * Deploy Resources: fun deploy

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

Funfile 支持的语法

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

  1. RUNTIME nodejs8
  2. COPY ./package.json .
  3. RUN npm install

复杂的语法举例,比如在函数计算中安装 ralng 的例子,Funfile 内容如下:

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

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

使用 Funfile 的优势

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