#docker-image #docker #run-time #bundle #static #executable #linker

bin+lib magicpak

构建不带静态链接的最小 Docker 镜像

10 个稳定版本

1.4.0 2022年12月12日
1.3.2 2022年11月23日
1.3.1 2022年6月19日
1.3.0 2022年3月5日
0.1.0 2020年4月3日

#688 in 开发工具

每月35次下载

MIT/Apache

89KB
2.5K SLoC

magicpak

Actions Status Actions Status License

magicpak 允许您在不进行任何繁琐准备(如静态链接)的情况下构建最小 Docker 镜像。

# You prepare /bin/your_executable here...

ADD https://github.com/coord-e/magicpak/releases/download/v1.4.0/magicpak-x86_64-unknown-linux-musl /usr/bin/magicpak
RUN chmod +x /usr/bin/magicpak

RUN /usr/bin/magicpak -v /bin/your_executable /bundle

FROM scratch
COPY --from=0 /bundle /.

CMD ["/bin/your_executable"]

就是这样!生成的镜像将只包含您的可执行文件在运行时所需的文件。您可以在 example/ 下找到更多有用的 magicpak 示例。

功能

magicpak 是一个命令行工具,用于分析并打包可执行文件的运行时依赖项。 magicpak 主要收集在运行时由动态链接器所需的共享对象依赖项。此外,magicpak 的贡献总结如下

  • 简单。您只需在您的 Dockerfile 中添加几行即可构建最小镜像。
  • 功能全面。您可以一次打包、测试和压缩您的可执行文件。您可以专注于您的业务,因为 magicpak 处理所有与 Dockerfile 相关的事项,以减小镜像大小。
  • 动态分析--dynamic 标志启用动态分析,可以发现除动态链接库之外的依赖项。
  • 灵活。我们通过一系列选项(如 --include--exclude)提供了对生成捆绑包的完全控制。您可以处理无法自动检测的依赖项。
  • 稳定。我们不解析未记录的且有时不准确的反汇编器(ldd(1))输出。相反,我们使用 glibc 中的 dlopen(3) 和 dlinfo(3) 来查询共享库的位置以供 ld.so(8) 使用。

magicpak 特别适用于您发现难以生成静态链接可执行文件的情况。当从源代码构建麻烦或源代码不公开时,magicpak 也非常有用,因为 magicpak 只需要可执行文件来构建最小 Docker 镜像。

用法

您可以从以下命令开始:magicpak path//可执行文件路径//输出。这会静态分析您可执行文件的运行时依赖项,并将可执行文件运行时所需的所有内容放入指定的输出目录。一旦捆绑,我们就可以简单地将其复制到第二阶段中的scratch镜像中,如下所示。

RUN magicpak path/to/executable /bundle

FROM scratch
COPY --from=0 /bundle /.

有些可执行文件以这种方式运行良好。然而,其他一些由于magicpak的静态分析不足以在运行时检测到它们所需的全部文件,因此无法正常运行。对于这种情况,magicpak提供了--include <GLOB>选项来手动指定缺失的需求。此外,您可以使用--dynamic来自动包含在执行过程中被可执行文件访问的文件。

尽管我们的实现非常谨慎,但我们的分析在某种程度上是不可靠的,因为我们无法在执行之前完全确定其运行时行为。为了确保magicpak收集了执行特定任务所需的所有依赖项,我们实现了--test选项。--test可以通过chroot(2)测试结果捆绑。

结果镜像的大小是我们主要关注的问题。magicpak支持使用upx进行可执行文件压缩。您可以通过--compress启用它。

支持的选项

Usage: magicpak [OPTIONS] <INPUT>... <OUTPUT>

Arguments:
  <INPUT>...  Input executable
  <OUTPUT>    Output destination

Options:
  -i, --include <GLOB>                Additionally include files/directories with glob patterns
  -e, --exclude <GLOB>                Exclude files/directories from the resulting bundle with glob patterns
      --mkdir <PATH>                  Make directories in the resulting bundle
  -r, --install-to <PATH>             Specify the installation path of the executable in the bundle
      --log-level <LEVEL>             Specify the log level [default: Warn] [possible values: Off, Error, Warn, Info, Debug]
  -v, --verbose                       Verbose mode, same as --log-level Info
  -t, --test                          Enable testing
      --test-command <COMMAND>        Specify the test command to use in --test
      --test-stdin <CONTENT>          Specify stdin content supplied to the test command in --test
      --test-stdout <CONTENT>         Test stdout of the test command
  -d, --dynamic                       Enable dynamic analysis
      --dynamic-arg <ARG>             Specify arguments passed to the executable in --dynamic
      --dynamic-stdin <CONTENT>       Specify stdin content supplied to the executable in --dynamic
  -c, --compress                      Compress the executable with npx
      --upx-arg <ARG>                 Specify arguments passed to upx in --compress
      --busybox <PATH or NAME>        Specify the path or name of busybox that would be used in testing [default: busybox]
      --upx <PATH or NAME>            Specify the path or name of upx that would be used in compression [default: upx]
      --cc <PATH or NAME>             Specify the path or name of c compiler that would be used in the name resolution of shared library dependencies [env: CC=] [default: cc]
      --experimental-noload-resolver  [EXPERIMENTAL] Resolve dynamic library paths without loading in dlopen(3)
  -h, --help                          Print help information

Docker镜像

我们提供了一些基础镜像,其中包含magicpak及其可选依赖项,以便您开始使用。

名称 描述
magicpak/debian magicpak/debian library/debian带有magicpak
magicpak/cc magicpak/cc library/debian带有build-essentialclangmagicpak
magicpak/haskell magicpak/haskell library/haskell带有magicpak
magicpak/rust magicpak/rust library/rust带有magicpak

示例

以下是一个使用magicpak为C/C++/等格式器clang-format创建Docker镜像的Dockerfile,clang-format是一个格式化工具。(example/clang-format

FROM magicpak/debian:buster-magicpak1.4.0

RUN apt-get -y update
RUN apt-get -y --no-install-recommends install clang-format

RUN magicpak $(which clang-format) /bundle -v  \
      --compress                               \
      --upx-arg --best                         \
      --test                                   \
      --test-stdin "int main(  ){ }"           \
      --test-stdout "int main() {}"            \
      --install-to /bin/

FROM scratch
COPY --from=0 /bundle /.

WORKDIR /workdir

CMD ["/bin/clang-format"]

关于名称解析和glibc的说明

如果您的程序使用glibc进行名称解析(很可能是这样),在通过magicpak捆绑后,对getaddrinfo(3)的调用将导致错误。可以通过手动包括以下示例中的NSS相关共享库来解决这个问题。

# example on x86_64 Debian-based image:
RUN magicpak path/to/executable /bundle --include '/lib/x86_64-linux-gnu/libnss_*'

关于jemalloc的说明

如果您的程序依赖于libjemalloc,magicpak可能会失败,并显示以下消息。

error: Unable to lookup shared library: /lib/aarch64-linux-gnu/libjemalloc.so.2: cannot allocate memory in static TLS block

您可以使用--experimental-noload-resolver标志来解决这个问题。有关详细信息,请参阅#19

免责声明

magicpak没有任何保证。无法保证处理的捆绑包能够正确且相同地工作。虽然我在使用magicpak构建各种类型的镜像时没有遇到问题,但建议您谨慎使用,并对生成的捆绑包进行仔细检查。

许可证

根据以下之一获得许可

由你选择。

贡献

除非你明确说明,否则任何由你有意提交并包含在作品中的贡献,根据Apache-2.0许可证的定义,应按照上述方式双许可,不附加任何额外条款或条件。

依赖项

~6–16MB
~214K SLoC