我们在《snap打包Nginx实践》中,熟悉了使用snapcraft工具打包nginx的过程,但nginx启动所需要的配置文件,是我们手动从只读区拷贝到可读写区的,下面我们就来了解一下snap hook技术,并实践通过snap hook技术来实现nginx snap包在安装过程中,自动把配置文件从只读区拷贝到可读写区。
1.什么是snap hook
snap hook通常是一个可执行文件,由某种操作触发,可以在snap的沙箱环境中运行。
snap hook的常用场景有:
1) 通知发生了什么事情
比如snap app升级的时候,可能需要触发hook更新配置文件、升级数据格式等。
2) 通知正在发生什么操作
比如snap app可能需要知道特定的interface何时连接或断开。
snap hook文件需要放在跟snapcraft.yaml文件同级目录的snap/hooks目录下,可执行文件的名称跟hook类型一致,比如我们即将用到的install hook的文件名称就是install,这样使用snapcraft工具打包后,snapd就会根据操作来触发snap hook。
snap hook通常只能访问沙箱内部的资源,如果要访问沙箱外部资源,需要通过interface机制的slots and plugs来实现。
snap hook按照触发操作分为configure hook、install hook、interface hook、pre-refresh hook、post-refresh hook、remove hook、prepare-device hook。
2.编写hook实现nginx配置文件拷贝
nginx的配置文件,是需要在install过程中进行拷贝的,所以我们需要编写install hook。
编写之前,我们要了解一下snap沙箱环境的一些环境变量。以nginx为例,我们可以通过以下命令来查看nginx沙箱环境中的环境变量。
pp@pp-ThinkPad-S2-2nd-Gen:~$ snap run --shell nginx
To run a command as administrator (user "root"), use "sudo ".
See "man sudo_root" for details.
pp@pp-ThinkPad-S2-2nd-Gen:/home/pp$ env
......
SNAP_USER_COMMON=/home/pp/snap/nginx/common
SHELL=/bin/bash
TERM=vt100
SNAP_CONTEXT=mgFGMhdv9hPbNnQyYNnTRKKmcHmWQSNq3nPtQjdwQKq3
TMPDIR=/tmp
SNAP_LIBRARY_PATH=/var/lib/snapd/lib/gl:/var/lib/snapd/lib/gl32:/var/lib/snapd/void
SNAP_INSTANCE_NAME=nginx
SNAP_COMMON=/var/snap/nginx/common
SNAP_USER_DATA=/home/pp/snap/nginx/x1
SNAP_DATA=/var/snap/nginx/x1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
TEMPDIR=/tmp
PWD=/home/pp
SNAP_REVISION=x1
HOME=/home/pp/snap/nginx/x1
SNAP_NAME=nginx
SNAP_COOKIE=mgFGMhdv9hPbNnQyYNnTRKKmcHmWQSNq3nPtQjdwQKq3
SNAP_ARCH=amd64
SNAP_VERSION=1.17.7
SNAP=/snap/nginx/x1
XDG_RUNTIME_DIR=/run/user/1000/snap.nginx
......
这些环境变量,在沙箱环境中是可以直接用的,我们需要进行拷贝动作的源目录和目标目录分别是 S N A P 和 SNAP和 SNAP和SNAP-COMMON, S N A P 是 只 读 区 , SNAP是只读区, SNAP是只读区,SNAP-COMMON是可读写区。我们在snapscaft.yaml同级的snap目录下添加并编辑install hook文件。
pp@pp-ThinkPad-S2-2nd-Gen:~/nginx-snap/snap$ ls
snap snapcraft.yaml
pp@pp-ThinkPad-S2-2nd-Gen:~/nginx-snap/snap$ cd snap/hooks/
pp@pp-ThinkPad-S2-2nd-Gen:~/nginx-snap/snap/snap/hooks$ ls
install
install文件的内容如下:
#!/bin/sh -e
cp -R $SNAP/var/snap/nginx/common/conf $SNAP_COMMON/
cp -R $SNAP/var/snap/nginx/common/logs $SNAP_COMMON/
cp -R $SNAP/var/snap/nginx/common/run $SNAP_COMMON/
mkdir -m 0777 $SNAP_COMMON/lib
在install文件中,我们把只读区中的文件拷贝到可读写区中,并创建lib目录。
用snapcraft工具重新打包,并安装后,我们看一下目标目录。
pp@pp-ThinkPad-S2-2nd-Gen:/var/snap/nginx/common$ ls
conf lib logs run
nginx的配置文件和启动所需要的文件都复制成功,执行nginx命令也成功。
pp@pp-ThinkPad-S2-2nd-Gen:~/nginx-snap/snap$ sudo nginx
pp@pp-ThinkPad-S2-2nd-Gen:~/nginx-snap/snap$ ps -A | grep "nginx"
18109 ? 00:00:00 nginx
18110 ? 00:00:00 nginx
3.后续工作
我们使用snap install hook实现了安装是自动把配置文件从只读区拷贝到可读写区,基本完成了snapcraft打包nginx的所有工作,但只是在现有的16.04环境中验证了snap包,这是不够的,需要在全新的ubuntu环境中进行验证。由于频繁安装ubuntu环境比较繁琐,后续我们将搭建lxc容器,在lxc的ubuntu实例中验证nginx snap包,请大家持续关注。
nginx包的snapcraft工程文件请访问https://github.com/dangelzjj/enjoy_snap.git
4.参考资料:
https://tutorials.ubuntu.com/tutorial/create-your-first-snap
https://snapcraft.io/docs/t/pre-built-apps/6739
https://snapcraft.io/docs/snapcraft-parts-metadata
https://snapcraft.io/docs/snapcraft-app-and-service-metadata
https://snapcraft.io/docs/supported-plugins
https://snapcraft.io/docs/autotools-plugin
https://snapcraft.io/docs/environment-variables
https://snapcraft.io/docs/supported-snap-hooks