写真公開システムのコンテナがおもったよりデカかったので、マルチステージビルドを試してみた。
それまでのコンテナは「alpineにあれこれ入れてビルドしたあと要らないものは削除する」というやり方だったけど、依存関係で入ったものとか消しきれてなかったりしたのか、600MiBくらいの大きさになってた。
apk delするときに–purgeつければよかったのかもしれないけど、マルチステージビルドでビルドしたものをコピーしたほうが楽そうだったのでそっちにした。
まずはサーバー側から
FROM alpine:latest AS server
RUN mkdir /build
RUN apk –no-cache –virtual build add rust cargo make g++ gcc
RUN apk add –no-cache sqlite-dev
ADD src /build/src
ADD Cargo.toml /build
ADD Cargo.lock /build
RUN cd /build && cargo build –release
なぜかrust:alpineを使うとコピーしたあとsqliteが使えなくなったので、alpineにrustとか入れる方針を継続。
次にフロントエンド側
FROM node:16-alpine AS front
# フロントのビルド
RUN apk add –no-cache python3 g++ make
RUN mkdir /build
ADD front /build/front
ADD public /build/public
WORKDIR /build/front
RUN npm install
RUN npm run build
RUN npm run install-script
node:16-alpineにgypが要求してくるpythonとg++とmakeをインストールしてビルド。生成物はあとでコピーするために纏めておく
最後に実行用コンテナ
FROM alpine:latest AS tiny_web_album
# ビルド結果のコピー
RUN mkdir /twa
RUN mkdir /twa/db
RUN apk add –no-cache sqlite-dev libgcc
RUN echo $’DATABASE_URL=./db\n\
PUBLIC_DIR=./public\n\
PHOTO_DIR=./public/photo\n\
HOST=0.0.0.0:8000\n\
TEMPLATE_DIR=default\n\
LOG_LEVEL=debug\n\
ROOT=/photo/’ | tee /twa/.env
ADD migrations /twa/migrations
ADD templates /twa/templates
COPY –from=server /build/target/release/tiny_web_album /twa/
COPY –from=front /build/public/ /twa/public
EXPOSE 8000
WORKDIR /twa
ENTRYPOINT [ “./tiny_web_album” ]
ファイルを置くディレクトリと必要なライブラリと設定ファイルを用意して各ステージでビルドしたファイルを–fromでコピー元ステージ指定してCOPY。
これで作成したらコンテナサイズが10MiBくらいまで減った。