こんにちは。「Minecraft Bedrockサーバー用コンテナを作る」の第2回です。
おさらい
前回は作業用コンテナを使用し、Dockerfileを作成するための情報を収集しました。今回はその情報を基にDockerfileを作成し、コンテナを起動します。
Dockerfile
以下のDockerfileでBedrock Serverのコンテナを構築可能です。
このDockerfileの内容について説明します。
ビルド処理の詳細
FROM
FROM debian:bookworm-slim AS builder
ここには、第1回の動作検証に利用したdebian:bookworm-slim
のコンテナイメージを指定します。
WORKDIR
WORKDIR /work
作業ディレクトリとして/work
を指定します。ここにBedrockサーバーの起動に必要なファイルをまとめます。
SHELL
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
Bashの使用を明記し、pipefail
オプションを指定することで、パイプライン中のエラーを正しく検出します。
ARG
ARG USER_AGENT='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36' ARG DOWNLOAD_URL='https://www.minecraft.net/en-us/download/server/bedrock' ARG REGEX_PATTERN='https://www.minecraft.net/bedrockdedicatedserver/bin-linux/bedrock-server-[^/]+\.zip'
これらの変数はBedrockサーバーのダウンロード時に使用します。
USER_AGENT
最もシェアが高いと思われる、Windows版Google Chromeのユーザーエージェントを設定します。Bedrockサーバーのダウンロードに必要で、curl
コマンド実行時に指定します。
DOWNLOAD_URL
BedrockサーバーダウンロードページのURLです。
第1回では日本語版のページからバイナリのダウンロードリンクを見つけましたが、マルチバイト文字が問題を起こす可能性を考慮し、英語版のページを設定しています。
REGEX_PATTERN
Bedrockサーバーのダウンロードリンクを正規表現で特定するためのパターンです。
RUN
RUN apt-get -qq update \ && DEBIAN_FRONTEND=noninteractive apt-get -qq install -y --no-install-recommends \ ca-certificates=* \ curl=7.88.1-* \ unzip=6.0-* \ && curl -sSA "$USER_AGENT" "$DOWNLOAD_URL" \ | grep -Eo "$REGEX_PATTERN" \ | xargs curl -sSOA "$USER_AGENT" \ && unzip -q bedrock-server-*.zip -d bedrock-server \ && mkdir /work/lib \ && ldd /work/bedrock-server/bedrock_server \ | grep -oP '[^\s]+(?= \()' \ | xargs -I{} cp {} /work/lib
複雑なので、処理毎に分けて説明します。
パッケージのインストール
Bedrockサーバーのダウンロードに必要なパッケージをインストールします。
RUN apt-get -qq update \ && DEBIAN_FRONTEND=noninteractive apt-get -qq install -y --no-install-recommends \ ca-certificates=* \ curl=7.88.1-* \ unzip=6.0-* \
DEBIAN_FRONTEND
の指定
コンテナイメージのビルド時はインタラクティブな操作をおこなわないため、DEBIAN_FRONTDEND=noninteractive
とします。
設定しないと以下のメッセージが表示されますが、気にならないようなら設定しなくても良いでしょう。
debconf: unable to initialize frontend: Dialog debconf: (TERM is not set, so the dialog frontend is not usable.) debconf: falling back to frontend: Readline debconf: unable to initialize frontend: Readline debconf: (Can't locate Term/ReadLine.pm in @INC (you may need to install the Term::ReadLine module) (@INC contains: /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.36.0 /usr/local/share/perl/5.36.0 /usr/lib/x86_64-linux-gnu/perl5/5.36 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl-base /usr/lib/x86_64-linux-gnu/perl/5.36 /usr/share/perl/5.36 /usr/local/lib/site_perl) at /usr/share/perl5/Debconf/FrontEnd/Readline.pm line 7.) debconf: falling back to frontend: Teletype
--no-install-recommends
オプション
不要な関連パッケージのインストールを回避します。
マルチステージビルドを使うためコンテナのイメージサイズに影響はありませんが、インストール時間が延びるので指定しましょう。
インストールするパッケージ
ca-certificates
とcurl
はBedrockサーバーをHTTPSのプロトコルでダウンロードするときに必要です。
unzip
はダウンロードしたファイルがZIPでアーカイブされているため、それを展開するために必要です。
パッケージはバージョンをゆるく指定していますが、これはhadolintでエラーを出さないためです。
ミッションクリティカルなシステムでなければ、セキュリティも考慮しディストリビューターが提供する最新のパッケージを利用して問題ないでしょう。
Bedrockサーバーのダウンロード
&& curl -sSA "$USER_AGENT" "$DOWNLOAD_URL" \ | grep -Eo "$REGEX_PATTERN" \ | xargs curl -sSOA "$USER_AGENT" \
ARGで設定した3つの変数をここで利用します。
処理の流れ
curl -sSA "$USER_AGENT" "$DOWNLOAD_URL"
でダウンロードページの内容を取得grep -Eo "$REGEX_PATTERN"
でダウンロードリンクを特定xargs curl -sSOA "$USER_AGENT"
でダウンロードリンクからBedrockサーバーをダウンロード
アーカイブの展開
&& unzip -q bedrock-server-*.zip -d bedrock-server \
ダウンロードしたBedrockサーバーのアーカイブを展開します。後続作業のため、-d
オプションでディレクトリを指定します。
ライブラリ配置用ディレクトリ作成
&& mkdir /work/lib{,64} \
Bedrockサーバーの起動に必要なライブラリの配置先ディレクトリとしてlib
とlib64
を作成します。
ライブラリのコピー
&& ldd /work/bedrock-server/bedrock_server \ | grep -oP '(?<= => )[^\s]+?(?= \()' \ | xargs -I{} cp {} /work/lib \ && cp /lib64/ld-linux-x86-64.so.2 /work/lib64
Bedrockサーバーの起動に必要なライブラリを抽出し、先ほど作成したライブラリ用のディレクトリにコピーします。
第1回のldd
コマンド実行結果をもう一度確認してみましょう。
root@8de161ca6300:/work/bedrock-server# ldd bedrock_server libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ffff54fe000) libcurl.so.4 => /lib/x86_64-linux-gnu/libcurl.so.4 (0x00007ffff544f000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ffff5370000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007ffff5350000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ffff534b000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffff516a000) /lib64/ld-linux-x86-64.so.2 (0x00007ffffffcc000) librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007ffff5163000) libnghttp2.so.14 => /lib/x86_64-linux-gnu/libnghttp2.so.14 (0x00007ffff5134000) libidn2.so.0 => /lib/x86_64-linux-gnu/libidn2.so.0 (0x00007ffff5103000) librtmp.so.1 => /lib/x86_64-linux-gnu/librtmp.so.1 (0x00007ffff50e4000) libssh2.so.1 => /lib/x86_64-linux-gnu/libssh2.so.1 (0x00007ffff50a3000) libpsl.so.5 => /lib/x86_64-linux-gnu/libpsl.so.5 (0x00007ffff508f000) libssl.so.3 => /lib/x86_64-linux-gnu/libssl.so.3 (0x00007ffff4fe4000) libcrypto.so.3 => /lib/x86_64-linux-gnu/libcrypto.so.3 (0x00007ffff4b5e000) libgssapi_krb5.so.2 => /lib/x86_64-linux-gnu/libgssapi_krb5.so.2 (0x00007ffff4b0b000) libldap-2.5.so.0 => /lib/x86_64-linux-gnu/libldap-2.5.so.0 (0x00007ffff4aac000) liblber-2.5.so.0 => /lib/x86_64-linux-gnu/liblber-2.5.so.0 (0x00007ffff4a9c000) libzstd.so.1 => /lib/x86_64-linux-gnu/libzstd.so.1 (0x00007ffff49e0000) libbrotlidec.so.1 => /lib/x86_64-linux-gnu/libbrotlidec.so.1 (0x00007ffff49d1000) libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007ffff49b2000) libunistring.so.2 => /lib/x86_64-linux-gnu/libunistring.so.2 (0x00007ffff47fc000) libgnutls.so.30 => /lib/x86_64-linux-gnu/libgnutls.so.30 (0x00007ffff45e0000) libhogweed.so.6 => /lib/x86_64-linux-gnu/libhogweed.so.6 (0x00007ffff4597000) libnettle.so.8 => /lib/x86_64-linux-gnu/libnettle.so.8 (0x00007ffff4547000) libgmp.so.10 => /lib/x86_64-linux-gnu/libgmp.so.10 (0x00007ffff44c6000) libkrb5.so.3 => /lib/x86_64-linux-gnu/libkrb5.so.3 (0x00007ffff43ec000) libk5crypto.so.3 => /lib/x86_64-linux-gnu/libk5crypto.so.3 (0x00007ffff43bf000) libcom_err.so.2 => /lib/x86_64-linux-gnu/libcom_err.so.2 (0x00007ffff43b9000) libkrb5support.so.0 => /lib/x86_64-linux-gnu/libkrb5support.so.0 (0x00007ffff43a9000) libsasl2.so.2 => /lib/x86_64-linux-gnu/libsasl2.so.2 (0x00007ffff438c000) libbrotlicommon.so.1 => /lib/x86_64-linux-gnu/libbrotlicommon.so.1 (0x00007ffff4369000) libp11-kit.so.0 => /lib/x86_64-linux-gnu/libp11-kit.so.0 (0x00007ffff4235000) libtasn1.so.6 => /lib/x86_64-linux-gnu/libtasn1.so.6 (0x00007ffff4220000) libkeyutils.so.1 => /lib/x86_64-linux-gnu/libkeyutils.so.1 (0x00007ffff4217000) libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007ffff4206000) libffi.so.8 => /lib/x86_64-linux-gnu/libffi.so.8 (0x00007ffff41fa000) root@8de161ca6300:/work/bedrock-server#
これより、/lib64
ディレクトリにはld-linux-x86-64.so.2
を/lib
にそれ以外をコピーすれば良さそうです。
ldd
コマンドでBedrockサーバーが参照するライブラリを特定できましたが、抽出には比較的複雑な正規表現が必要になります。
そこで、一致条件について理解しやすいよう以下に表を作成しました。grep
コマンド実行部分も合わせて記します。
| grep -oP '(?<= => )\S+?(?= \()' \
正規表現 | 分類 | 説明 |
---|---|---|
(?<= => ) |
肯定的後読み | => の直後に続く部分を抽出対象とします。 |
\S+? |
マッチ | 空白文字以外の1文字以上の連続をマッチさせます。これが実際に抽出される部分です。 |
(?= \() |
肯定的先読み | ( の直前で終わる部分を抽出対象とします。 |
これにより、ライブラリのパス(/lib/x86_64-linux-gnu/...など)を正確に抽出します。
実行処理
FROM
FROM gcr.io/distroless/static-debian12:nonroot
最終的なコンテナイメージは、プログラムの実行に必要となるファイル以外は極力削り、コンテナイメージのサイズを小さくすることが求められます。
Bedrockサーバー用コンテナイメージもマルチステージビルドの活用と、Bedrockサーバー起動用のベースイメージを小さなものにすることで、ビルド後のコンテナイメージサイズを小さくします。
具体的には、Bedrockサーバー起動用にはgcr.io/distroless/base-debian12:nonroot
を採用しました。
なお、第1回で動作検証にUbuntuベースのイメージではなくDebianベースのイメージを選択した理由は、同コンテナイメージがDebianベースであり極力環境を合わせるためでした。
WORKDIR
WORKDIR /bedrock-server
/bedrock-server
を作業用ディレクトリとして設定し、Bedrockサーバーの実行ファイルはこちらに配置します。
COPY
COPY --from=builder /work/bedrock-server/ /bedrock-server COPY --from=builder /work/lib/ /lib COPY --from=builder /work/lib64/ /lib64
ビルド用コンテナで準備したファイルを、所定のディレクトリにそれぞれコピーします。
なお、/lib
ディレクトリ内のライブラリはデフォルトで読み込まれるようになっているため、LD_LIBRARY_PATH
を設定する必要はありません。
EXPOSE
EXPOSE 19132/udp EXPOSE 19133/udp
IPv4で利用するUDP 19132番ポートとIPv6で利用するUDP 19133番ポートを明記します。
ENTRYPOINT
ENTRYPOINT ["/bedrock-server/bedrock_server"]
Bedrockサーバーのバイナリを指定します。
コンテナのビルド
完成したDockerfileを使い、コンテナのビルドをおこないます。
$ docker build --platform=linux/amd64 -t bedrock-server .
実行結果を以下に記します。
[+] Building 30.9s (13/13) FINISHED docker:desktop-linux => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 1.36kB 0.0s => [internal] load metadata for docker.io/library/debian:bookworm-slim 0.0s => [internal] load metadata for gcr.io/distroless/static-debian12:nonroot 0.2s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [stage-1 1/5] FROM gcr.io/distroless/static-debian12:nonroot@sha256:6cd937e9155bdfd805d1b94e037f9d6a899603306030936a3b11680af0c2ed58 0.4s => => resolve gcr.io/distroless/static-debian12:nonroot@sha256:6cd937e9155bdfd805d1b94e037f9d6a899603306030936a3b11680af0c2ed58 0.4s => CACHED [builder 1/3] FROM docker.io/library/debian:bookworm-slim@sha256:d365f4920711a9074c4bcd178e8f457ee59250426441ab2a5f8106ed8fe948eb 2.0s => => resolve docker.io/library/debian:bookworm-slim@sha256:d365f4920711a9074c4bcd178e8f457ee59250426441ab2a5f8106ed8fe948eb 2.0s => CACHED [stage-1 2/5] WORKDIR /bedrock-server 0.0s => [builder 2/3] WORKDIR /work 0.0s => [builder 3/3] RUN apt-get -qq update && DEBIAN_FRONTEND=noninteractive apt-get -qq install -y --no-install-recommends ca-certificates=* curl=7.88.1-* unzip=6.0- 24.4s => [stage-1 3/5] COPY --from=builder /work/bedrock-server/ /bedrock-server 0.4s => [stage-1 4/5] COPY --from=builder /work/lib/ /lib 0.0s => [stage-1 5/5] COPY --from=builder /work/lib64/ /lib64 0.0s => exporting to image 3.5s => => exporting layers 3.5s => => exporting manifest sha256:a238cd187a47b3382e3eb202c209439a86be17dde8ec7865c8ec18ed8def11c8 0.0s => => exporting config sha256:159312040bbde2575469e938723f169cc72ca803ca290e4a7f1d7d9e1767d691 0.0s => => exporting attestation manifest sha256:198fd3771641c0b8e2f8afcd44ea5d53309e386bfe6d736d706f56eb6ead1195 0.0s => => exporting manifest list sha256:99b3b93585f087dcad5376cf3e2321cecea3765f2295f77289aa356cfab17b16 0.0s => => naming to docker.io/library/bedrock-server:latest 0.0s View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/gwgvz3h9efpt9z1okfc5skors
Bedrockサーバーはx86_64
用のバイナリしか提供されていません。そのため、Apple Silicon搭載のMacを利用している場合はプラットフォームを必ず指定しましょう。
Bedrockサーバーの起動
ビルドしたコンテナでBedrockサーバーが起動するか確認します。
コンテナの起動時もプラットフォームを指定しましょう。また、UDP 19132番ポートも忘れずに指定します。
$ docker container run --platform linux/amd64 -p 19132:19132/udp -it bedrock-server
実行結果を以下に記します。
NO LOG FILE! - setting up server logging... [2024-12-29 03:47:56:653 INFO] Starting Server [2024-12-29 03:47:56:653 INFO] Version: 1.21.51.02 [2024-12-29 03:47:56:653 INFO] Session ID: 08ead009-93ae-45f5-b463-420e4fdb60ff [2024-12-29 03:47:56:653 INFO] Build ID: 29823500 [2024-12-29 03:47:56:653 INFO] Branch: r/21_u5 [2024-12-29 03:47:56:653 INFO] Commit ID: 15737c809ed75cbc4a361ffa3c5c2df76ff78d42 [2024-12-29 03:47:56:653 INFO] Configuration: Publish [2024-12-29 03:47:56:658 INFO] Level Name: Bedrock level [2024-12-29 03:47:56:661 INFO] No CDN config file found for dedicated server [2024-12-29 03:47:56:661 INFO] Game mode: 0 Survival [2024-12-29 03:47:56:661 INFO] Difficulty: 1 EASY [2024-12-29 03:47:56:670 INFO] Content logging to console is enabled. [2024-12-29 03:47:56:933 INFO] Opening level 'worlds/Bedrock level/db' [2024-12-29 03:47:57:126 INFO] [SERVER] Pack Stack - None [2024-12-29 03:47:58:349 INFO] IPv4 supported, port: 19132: Used for gameplay and LAN discovery [2024-12-29 03:47:58:349 INFO] IPv6 supported, port: 19133: Used for gameplay [2024-12-29 03:47:58:381 INFO] Server started. [2024-12-29 03:47:58:382 INFO] ================ TELEMETRY MESSAGE =================== [2024-12-29 03:47:58:382 INFO] Server Telemetry is currently not enabled. [2024-12-29 03:47:58:382 INFO] Enabling this telemetry helps us improve the game. [2024-12-29 03:47:58:382 INFO] [2024-12-29 03:47:58:382 INFO] To enable this feature, add the line 'emit-server-telemetry=true' [2024-12-29 03:47:58:382 INFO] to the server.properties file in the handheld/src-server directory [2024-12-29 03:47:58:382 INFO] ======================================================
サーバーのプロセスが起動しました。
Bedrockサーバーへの接続
MinecraftクライアントからBedrockサーバーへ接続できるか確認します。今回もiOS版Minecraftを利用しました。
「Dedicated Server」をタップしてコンテナに接続します。
接続の確認ができたらゲームを終了します。コンテナ側の標準出力には、以下のようなメッセージが表示されます。
[2024-12-29 03:51:14:563 INFO] Player connected: takenorio, xuid: **************** [2024-12-29 03:51:18:692 INFO] Player Spawned: takenorio xuid: ****************, pfid: **************** [2024-12-29 03:51:34:486 INFO] Player disconnected: takenorio, xuid: ****************, pfid: ****************
標準入力からstop
と入力してサーバーを停止するとコンテナも停止します。
stop [2024-12-29 03:47:35:988 INFO] Server stop requested. [2024-12-29 03:47:36:018 INFO] Stopping server... Quit correctly
まとめ
今回は、Dockerfileからコンテナを作成し、Minecraftのアプリケーションから接続できることを確認しました。
次回は、ワールドデータの永続化と設定ファイルの管理について説明します。