🪓動機
たとえば Alpine でビルドしたのち、他の Linux でも実行できるように静的リンクでビルドさせたい。
Tool | Version |
---|---|
go |
1.16.5 |
rustup |
1.24.3 |
rustc |
1.53.0 |
cargo |
1.53.0 |
⚙️コマンドライン
Go 言語
C 言語コードを呼び出す cgo を使っていると動的リンクされるらしい。
よって cgo を無効化したり、リンカーに静的リンクするオプションを渡したりする。
Example 1. Go
export CGO_ENABLED=0 (1)
go build -ldflags '-extldflags=-static' (2)
strip /path/to/binary (3)
1 | C 言語コードを利用してない場合は cgo を無効化するだけで静的リンクになる。 |
2 | リンカーに静的リンクであることを伝えてビルド。 利用しているパッケージによっては -tags オプションも使って cgo 部分をスキップする。 |
3 | デバッグに用いられるシンボル情報を削除してサイズ縮小。 |
Rust 言語
*-musl
ターゲットを使用すれば静的リンクになる。
Example 2. Rust
x86_64 アーキテクチャの場合
rustup target add x86_64-unknown-linux-musl (1)
cargo build --release --target x86_64-unknown-linux-musl (2)
strip /path/to/binary (3)
1 | musl ライブラリを利用するターゲットを追加。 |
2 | 静的リンクでビルドするには musl ターゲットを使う。 |
3 | デバッグに用いられるシンボル情報を削除してサイズ縮小。 |
静的リンクの確認
|
🐳 Dockerfile マルチステージでの利用例
もともとは Dockerfile でビルドさせたかったので、そのサンプル。
Example 3. Go in dockerfile
FROM golang:1.16-alpine AS build-go
WORKDIR /go/src
RUN \
apk --no-cache add \ (1)
git \
binutils
### Install to '/go/bin' as static binary
ENV CGO_ENABLED=0
ARG GO_INSTALL="go install -ldflags '-extldflags=-static'" (2)
# ghq
RUN ${GO_INSTALL} github.com/x-motemen/ghq@v1.2.1
# stripped
WORKDIR /go/bin
RUN strip $(ls)
# -----------------------
FROM debian:buster-slim
COPY --from=build-go /go/bin /usr/local/bin/
RUN ...
1 | 必要なパッケージ[1]をインストール。 |
2 | リモートリポジトリのパッケージをビルドするため、 go build の代わりに go install を利用。 |
Example 4. Rust in dockerfile
*-unknown-linux-musl
ターゲットを追加して利用することで、静的リンクにできる。
FROM rust:1.53-alpine AS build-rust
ENV CARGO_HOME=/cargo
WORKDIR ${CARGO_HOME}/bin
RUN apk --no-cache add musl-dev (1)
# Install
RUN \
cargo install --version ^0.10.1 exa && \ (2) (3)
cargo install --version ^2.1.0 git-interactive-rebase-tool
# Reduce binary size
RUN strip $(ls)
# -----------------------
FROM debian:buster-slim
COPY --from=build-rust /cargo/bin /usr/local/bin/
RUN ...
1 | ビルドするのに必要な musl-dev パッケージをインストール。 |
2 | Alpine ベースではデフォルトが musl ターゲットなので、ターゲットを追加・指定する必要がない。 |
3 | crates.io に登録されているクレートをビルドするため、 cargo install を利用している。 |