magicpak
enables you to build minimal docker images without any bothersome preparation such as static linking.
```dockerfile
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/.
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:
Dockerfile
.magicpak
handles all Dockerfile
-specific matters to decrease image size.--dynamic
flag enables a dynamic analysis that can discover dependencies other than dynamically linked libraries.--include
and --exclude
. You can deal with dependencies that cannot be detected automatically.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.
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.
```dockerfile 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
.
``` Usage: magicpak [OPTIONS] ...
Arguments: ... Input executable
Options:
-i, --include
We provide some base images that contain magicpak
and its optional dependencies to get started.
| name | description |
| ------------------------------------------------------------ | ------------------------------------------------------------ |
| magicpak/debian | library/debian with
magicpak
|
| magicpak/cc | library/debian with
build-essential
, clang
, and magicpak
|
| magicpak/haskell | library/haskell with
magicpak
|
| magicpak/rust | library/rust with
magicpak
|
The following is a dockerfile using magicpak
for a docker image of clang-format
, a formatter for C/C++/etc. (example/clang-format)
```dockerfile 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"] ```
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.
```dockerfile
RUN magicpak path/to/executable /bundle --include '/lib/x8664-linux-gnu/libnss*' ```
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.
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.
Licensed under either of
at your option.
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.