Build 一个最小的 Redis Docker Image

好吧,我承认这么说可能违反了广告法,但是……它确实挺小的。

可以对比一组数据:

  • 官方的 Redis 镜像:105MB
  • 官方的基于 alpine 的 Redis 镜像:32.3MB
  • 在 ubuntu 下面用默认配置 Build 出来的 redis-server binary:13M
  • 一个什么都没有的 alpine:latest docker 镜像:5.6MB
  • 上图中的 Redis 镜像:1.69MB

所以……可以说,确实挺小了。

当然生产环境肯定不差 100M 这点空间,还是带上一些常用的工具在生产环境跑比较好。本文只是在玩 Nix 时候的自娱自乐,没有什么实际意义。

这个镜像是用 Nix build 的,实际上,就是玩了一下 Nix 网站上的 Cover Demo。用到的手段有:

  1. 使用 Nix 来 build 这个 image;
  2. 编译的时候关闭了 systemd 的支持,Docker 里面不需要这种东西;
  3. 使用 musl 静态链接编译;
  4. 把除了 redis-server 之外的东西删除掉;
  5. 编译完成使用 strip -s 对最终的 binary 再次做删减。

具体的编译方法

首先在 Nix 创建一个文件,来编译 Redis,这里实际上使用的 Nix 打包好的 Redis,我只是对其通过 preBuildpostInstall 做了一些操作,替换 musl 和 strip 之类的。

然后再需要一个文件描述如何 build docker image:

非常简单,以至于不需要解释。

然后运行下面这个命令,build 就可以了。因为我已经 build 好了,所以 Nix 不会再出现 build 的日志。

Docker (容器) 的原理 曾经解释过,Docker image 本质上就是一个 tar 包。我们使用 docker load -i ./result 可以 load 这个 image。然后就可以运行了:

可能你发现了这个 image 有一些奇怪:Created 51 years ago. 其实这是对的。因为 Nix 号称是完全 reproducible 的,但是 image 如果有一个创建时间的话,那么每次 build 出来的产物都会因为这个创建时间,而导致每次的产物 hash 都不一样。所以 Nix 将 Docker image 产物的 Created 时间设置成 0 了。即 timestamp = 0.

看看这个镜像里面都有什么?

读者可以在 Docker hub 上下载这个镜像,然后使用 docker save 将它保存成 tar 再解压,看看里面都有什么。我这里直接去解压 Nix build 好的 image,每一层 layer 下面的 layer.tar 也都解压到对应的 layer 下面了。

可以看到,里面一层只有一个 redis-server 的 binary,上面一层是一个 bianry 的符号链接。符号链接是 Nix 的逻辑,符号链接很小,就懒得去删除了。

体验这个镜像

我把这个镜像放到了 Docker hub 上。可以直接运行 docker run laixintao/redis-minimal:v1 redis-server 来体验一下。

 

Docker 在 NixOS 里面的安装可以参考这里

Build 一个最小的 Redis Docker Image”已经有8条评论

    • 不会的,strip 只是删除了一些符号(大部分都是用于 debug 的),会让 debug 和反向工程难度更大一些,但是不会影响程序的执行。

Leave a comment

您的电子邮箱地址不会被公开。 必填项已用*标注