在 Docker 中进行 snapcraft 构建

背景

在尝试通过源码编译 Anbox snap 的时候,遇到了以下错误:

  • Failed to fetch stage packages: Error downloading packages for part 'anbox': The package 'libboost-thread1.58.0' was not found
  • The linker version '2.23' used by the base 'core' is incompatible with files in this snap:

通过搜索引擎了解到,libboost-thread1.58.0 等包只在 Ubuntu 16.04 及以前版本的软件源中提供,而在我的机器上安装的 Ubuntu 18.04 LTS 所使用的软件源中已经不再提供,取而代之的是 libboost-thread1.65.1 以及 libboost-thread1.62.0。另外查看 anbox 在 snapcraft.io 提供的在线构建服务的构建日志,发现其中的编译环境是 Ubuntu 16.04,也就是说 Ubuntu 16.04 应该是可以进行 Anbox snap 构建的环境。

在关于 snapcraft 与 linker version 的搜索结果中了解到 snapcraft 有一个叫做 cleanbuild 的功能,可以在一个 lxd 容器(默认选择 Ubuntu 16.04 环境)中进行 snapcraft 构建,从而解决依赖缺失、linker 版本不符等问题。但是在尝试使用 snapcraft cleanbuild 的过程中遇到了诸多琐碎的小问题,最终是未能成功完成构建。后来想到在我目前使用的系统中已经装有 Docker,也可以提供特定版本的干净环境用于构建,于是尝试在 Docker 中进行并完成了 snapcraft 的构建操作,以下是此方案的一系列步骤记录。

环境

  • 安装并配置好 Docker
  • (可选)当前用户已加入 docker 组(以便在执行 docker 的相关命令时不需要加上 sudo

容器准备

既然要使用 Docker,那么第一步自然是要决定使用何种容器。有以下两种选择:

查看 snapcore/snapcraftdockerfile ,发现其基础镜像为 ubuntu:xenial (也就是 Ubuntu 16.04),在其中已经安装配置好了 snapcraft。方便起见,直接选择 snapcore/snapcraft:stable 这一镜像进行后续步骤。

操作:执行以下命令拉取镜像。

$ docker pull snapcore/snapcraft:stable

环境配置与调整

以下假设:

  • 要执行 snapcraft 的项目目录在宿主机的路径为 /path/to/project_dir/

下述命令将完成以下配置:

  • /path/to/project_dir/ 挂载到容器的 /build 目录,以供构建
  • 设置容器的工作目录为 /build ,以便操作便利
  • 设置容器名称为 snapcraft ,以便进行后续操作

操作:执行以下命令配置并启动容器,进入容器的 Shell。

$ docker run -it \
      -v /path/to/project_dir/:/build \
      -w /build \
      --name snapcraft \
      snapcore/snapcraft:stable

默认的 ubuntu:xenial 镜像使用的 APT 源为 http://archive.ubuntu.com/ ,不带根据地区的自动重定向且服务器位于英国,软件包下载较慢。考虑到构建过程中需要下载诸多依赖的软件包,在进行 snapcraft 之前需要对此进行更改。

考虑以下情况:

  • 由于镜像里面缺文本编辑器(没有 vi),所以简单使用 echo 以及输出重定向以修改 /etc/apt/sources.list 文件。
  • 由于镜像里面没有 APT 的 HTTPS 支持(没有 apt-transport-https),所以先切换到国内的清华镜像源(HTTP),安装 apt-transport-https 以后再切换到 HTTPS 镜像源。(当然也可以直接使用 HTTP 的镜像源。

操作:执行以下命令将 APT 软件源切换到清华镜像源(HTTP),并更新软件包列表。

# echo -e "deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main restricted universe multiverse\ndeb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates main restricted universe multiverse\ndeb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-backports main restricted universe multiverse\ndeb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security main restricted universe multiverse" > /etc/apt/sources.list
# apt-get update

操作(可选但建议):执行以下命令安装 apt-transport-https ,将 APT 软件源切换到清华镜像源(HTTPS),并更新软件包列表。

# apt-get install apt-transport-https
# echo -e "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main restricted universe multiverse\ndeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates main restricted universe multiverse\ndeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-backports main restricted universe multiverse\ndeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security main restricted universe multiverse" > /etc/apt/sources.list
# apt-get update

进行构建

操作

# snapcraft

然后耐心等待构建完成。

整理

操作:退出容器的 Shell,关闭容器,然后删除容器(如有需要,可以保留该容器以备再次使用)。

# exit
$ docker stop snapcraft
$ docker rm snapcraft

由于容器内是以 root 身份执行 snapcraft 的,因此在构建过程中创建的文件的 owner 也为 root

操作:执行以下命令重新获得项目目录下的文件的所有权。(注:$USER 为环境变量,其值为当前登录的用户名,可以不作改动)

$ sudo chown -R $USER:$USER $PROJECT_PATH

参考资料

  1. Build on Docker | Snapcraft Documentation
  2. snapcore/snapcraft | Docker Hub
  3. Ubuntu 镜像使用帮助 | 清华大学开源软件镜像站
本文采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。
本文作者:KeNorizon
本文链接:https://blog.kenorizon.cn/solution/snapcraft-build-on-docker.html

评论

暂无

添加新评论