• Stars
    star
    607
  • Rank 73,845 (Top 2 %)
  • Language
    Rust
  • License
    Apache License 2.0
  • Created over 4 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

🔨 Build minimal docker images without static linking

magicpak

Actions Status Actions Status License

magicpak enables you to build minimal docker images without any bothersome preparation such as static linking.

# 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"]

That's it! The resulting image shall only contain what your executable requires at runtime. You can find more useful examples of magicpak under example/.

Feature

magicpak is a command-line utility that analyzes and bundles runtime dependencies of the executable. magicpak basically collects all shared object dependencies that are required by a dynamic linker at runtime. Additionally, magicpak's contributions are summarized as follows:

  • Simple. You can build a minimal image just by adding a few lines to your Dockerfile.
  • Full-featured. You can bundle, test, and compress your executable at once. You can focus on your business because magicpak handles all Dockerfile-specific matters to decrease image size.
  • Dynamic analysis. --dynamic flag enables a dynamic analysis that can discover dependencies other than dynamically linked libraries.
  • Flexible. We expose a full control of resulting bundle with a family of options like --include and --exclude. You can deal with dependencies that cannot be detected automatically.
  • Stable. We don't parse undocumented and sometimes inaccurate ldd(1) outputs. Instead, we use dlopen(3) and dlinfo(3) in glibc to query shared library locations to ld.so(8).

magicpak is especially useful when you find it difficult to produce a statically linked executable. Also, magicpak is powerful when building from source is bothering or the source code is not public, because magicpak only requires the executable to build a minimal docker image.

Usage

You can start with magicpak path/to/executable path/to/output. This simply analyzes runtime dependencies of your executable statically and put everything your executable needs in runtime to the specified output directory. Once they've bundled, we can simply copy them to the scratch image in the second stage as follows.

RUN magicpak path/to/executable /bundle

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

Some executables work well in this way. However, others fail to run properly because magicpak's static analysis isn't enough to detect all files needed by them at runtime. For this case, magicpak has --include <GLOB> option to specify the missing requirements manually. Moreover, you can use --dynamic to automatically include files that are accessed by the executable during execution.

Despite our careful implementation, our analysis is unreliable in a way because we can't completely determine the runtime behavior before its execution. To ensure that magicpak collected all dependencies to perform a specific task, --test option is implemented. --test enables testing of the resulting bundle using chroot(2).

The size of the resulting image is our main concern. magicpak supports executable compression using upx. You can enable it with --compress.

Supported options

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 images

We provide some base images that contain magicpak and its optional dependencies to get started.

name description
magicpak/debian magicpak/debian library/debian with magicpak
magicpak/cc magicpak/cc library/debian with build-essential, clang, and magicpak
magicpak/haskell magicpak/haskell library/haskell with magicpak
magicpak/rust magicpak/rust library/rust with magicpak

Example

The following is a dockerfile using magicpak for a docker image of clang-format, a formatter for C/C++/etc. (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"]

Note on name resolution and glibc

If your program uses glibc for name resolution (most likely it does), the call to getaddrinfo(3) will result in an error after bundled by magicpak. This can be resolved by manually including the NSS-related shared libraries as shown below.

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

Note on jemalloc

If your program depends on libjemalloc, magicpak may fail with the following message.

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

You can use --experimental-noload-resolver flag to workaround this. See #19 for details.

Disclaimer

magicpak comes with absolutely no warranty. There's no guarantee that the processed bundle works properly and identically to the original executable. Although I had no problem using magicpak for building various kinds of images, it is recommended to use this with caution and make a careful examination of the resulting bundle.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

More Repositories

1

misskey-rs

✌️ Client library for Misskey 🥰
Rust
57
star
2

mlml

self-hosted compiler for a subset of OCaml
OCaml
50
star
3

ccc

optimizing compiler for a subset of C language
C
34
star
4

scopion

a statically-typed programming language with powerful syntax
C++
31
star
5

expressi

Expression-oriented toy programming language written in Rust
Rust
19
star
6

kaisantantoudaijin

Discordの通話が解散できないオタクを解散させる解散担当大臣
Rust
17
star
7

cart

convert c/c++ code into well-formed ascii art
C++
14
star
8

r53ddns

command-line utility to update A record in Route53 with current global IP address
Rust
7
star
9

epgstation_exporter

Prometheus exporter for EPGStation metrics
Go
6
star
10

CopyBundleID

This Tweak adds a quick action shortcut to every app that will copy the app's bundle identifier.
Objective-C
6
star
11

slide-coinslt1000-slsa

5分でSLSA
CSS
6
star
12

ad-hoc-poly

Implementation of type classes
Haskell
6
star
13

impl-outsidein

Toy implementation of type inference for GADTs and TypeFamilies
Haskell
5
star
14

DSP6951

Library for DSP6951 DSP Radio IC.
C++
4
star
15

slide-specialseminar21-reimpl-functional-package-manager

純粋関数型パッケージマネージャの追実装
CSS
4
star
16

slide-type-class-impl

Haskellで作ってわかる型クラス
4
star
17

slide-coins20lt-outsidein-type-inference

OutsideIn(X) 型推論
CSS
3
star
18

oir

oir: OtakuAssembly Vol.2 第一章『データフロー最適化の実装』サンプル実装
C
3
star
19

mirakurun_exporter

Prometheus exporter for Mirakurun metrics
Go
3
star
20

article-ccc-backend

cccコンパイラのバックエンド
TeX
2
star
21

GT20L16J1Y

GT20L16J1Y Japanese Font ROM Driver Library for Arduino
C++
2
star
22

mkbookpdf

command-line utility for booklet printing
Rust
2
star
23

ili9328SPI

ILI9328 Driver Library for Arduino
C++
2
star
24

slide-coins20lt-misskey-rs

misskey-rs 紹介
CSS
2
star
25

rlenv

Scaffold reinforcement learning experiment environment
Python
2
star
26

discord-link2github

A bot for Discord that links Issue/PR to GitHub
JavaScript
2
star
27

bd

Bash Framework to accelerate your daily scripting
Shell
2
star
28

vrm-render

(wip) VRM renderer CLI
TypeScript
2
star
29

coord-e.com

Nix
2
star
30

slide-coins20lt-prove-using-ghc

"Theorem Proving using GHC" at coins20LT#1
1
star
31

minidots

minimal sufficient dotfiles
Shell
1
star
32

serialmon

A simple UART monitor built with Arduino
C++
1
star
33

slide-ps1

PS1芸
1
star
34

sats

Toy DPLL and CDCL SAT solver implementation
Rust
1
star
35

dotfiles

my .files
Emacs Lisp
1
star
36

runbot

Runbot runs your code on Discord using Wandbox API
Rust
1
star
37

linux_dvb_exporter

Prometheus exporter for DVB device metrics
Go
1
star
38

slack-send

Send message to Slack via webhook
Rust
1
star
39

pca9685

PCA9685 driver library
C++
1
star
40

slide-coins20lt-fold-for-all

fold for all
CSS
1
star
41

line-discord-webhook-adaptor

Adaptor between LINE Messaging API and Discord Webhooks.
JavaScript
1
star
42

eagle-libraries

My collection of libraries for Autodesk EAGLE
1
star
43

new-year-countdown

$ npx new-year-countdown
JavaScript
1
star
44

slide-coins20lt-rust-intro

Introduction to Rust
1
star
45

discord-minutes

Create a minute of meeting in Discord using GCP's Speech API
JavaScript
1
star