distrolessをベースにminecraftサーバーを立ち上げてみたので、そのメモ書き。
そもそもdistorolessってなに?
distrolessはGoogleが作ってるコンテナで、「アプリケーションの実行に必要なもの以外全部取っ払った」潔いコンテナ。
潔く取っ払いすぎて、debianベースなのにaptもシェル(sh, bashとか)も無い。
そのおかげで、軽量でセキュアなコンテナになっている。あとglibcが使えるので、互換性も案外問題なさそう。(alpine使うとcランタイムがmuslなので色々なところで面倒があった……)
Dockerfile作成
distrolessだとシェルもパッケージ管理もないのでマルチステージビルドでサーバーファイルをダウンロードしてCOPYコマンドでコンテナに入れる方法で作成。
FROM alpine as Download
RUN apk add curl && \
curl https://piston-data.mojang.com/v1/objects/05e4b48fbc01f0385adb74bcff9751d34552486c/server.jar -o /tmp/server.jar && \
echo "eula=true" > /tmp/eula.txt
FROM gcr.io/distroless/java21-debian12 as RUNNER
COPY --from=Download /tmp/server.jar /app/server.jar
COPY --from=Download /tmp/eula.txt /app/eula.txt
WORKDIR /app
CMD ["-Xmx1024M", "-Xms1024M", "server.jar", "--nogui"]
eula.txtはminecraftサーバーの利用規約に同意したことを示すファイル。これも事前に作成してCOPYで実行コンテナにコピー。
distolessのjavaコンテナにはデフォルトでENTRYPOINT=["java" "-jar"]
がついた状態なので、CMDコマンドでメモリの設定とサーバーファイルの指定と–noguiの設定を渡している。
コンテナのビルド
docker buildでもいいんだけど、今回はpodmanを採用
podman build -t minecraft:latest --rm=true .
通常通りpodman build
でOK
コンテナの実行
podman run --name minecraft -p "25565:25565" -v "$(pwd)/world:/app/world" -v "$(pwd)/server.properties:/app/server.properties" -v "$(pwd)/ops.json:/app/ops.json" -v "$(pwd)/whitelist.json:/app/whitelist.json" minecraft:latest
- worldディレクトリはminecraftのワールドを保存しているディレクトリ
- server.propertiesはサーバーの設定。
- ops.json, whitelist.jsonはユーザーの設定関係のファイル
なので、これらのファイルを-vでバインドして実行。
サーバーに接続
minecraftを実行して「マルチプレイ」からの「ダイレクト接続」でlocalhost
を指定する

……と、Connection refused: getsockopt
とエラーが出て接続できない。

サーバーに接続できないのが原因のようなので調べてみたところ
$ lsof -i:25565 -P
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
rootlessp 16887 user 11u IPv6 253693 0t0 TCP *:25565 (LISTEN)
IPv6でしかLISTENしてないようなので、IPv6のlocalhostにあたる::1
で接続


無事にサーバーにログイン成功。
コンテナ確認
alpineベースの現行コンテナとdistrolessコンテナベースでサイズを比較
$ sudo docker images | grep minecraft
minecraft latest 75ccfed6d298 55 seconds ago 249MB
server/minecraft latest ce799900ac71 22 hours ago 273MB
24MBくらい軽くなってるかな。