【第2回】Minecraft Bedrockサーバー用コンテナを作る

こんにちは。「Minecraft Bedrockサーバー用コンテナを作る」の第2回です。

おさらい

前回は作業用コンテナを使用し、Dockerfileを作成するための情報を収集しました。今回はその情報を基にDockerfileを作成し、コンテナを起動します。

blog.kenor.io

Dockerfile

以下のDockerfileでBedrock Serverのコンテナを構築可能です。

BedrockサーバーのDockerfile

この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

最もシェアが高いと思われる、WindowsGoogle Chromeのユーザーエージェントを設定します。Bedrockサーバーのダウンロードに必要で、curlコマンド実行時に指定します。

DOWNLOAD_URL

BedrockサーバーダウンロードページのURLです。

第1回では日本語版のページからバイナリのダウンロードリンクを見つけましたが、マルチバイト文字が問題を起こす可能性を考慮し、英語版のページを設定しています。

www.minecraft.net

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-certificatescurlは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サーバーの起動に必要なライブラリの配置先ディレクトリとしてliblib64を作成します。

ライブラリのコピー

    && 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を採用しました。

github.com

なお、第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サーバーへ接続できるか確認します。今回もiOSMinecraftを利用しました。

The Dedicated Server is displayed on the screen.
Bedrockサーバーが表示される

「Dedicated Server」をタップしてコンテナに接続します。

Successfully connected to the Bedrock Server container.
Bedrockサーバーのコンテナへの接続が成功

接続の確認ができたらゲームを終了します。コンテナ側の標準出力には、以下のようなメッセージが表示されます。

[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のアプリケーションから接続できることを確認しました。

次回は、ワールドデータの永続化と設定ファイルの管理について説明します。

【第1回】Minecraft Bedrockサーバー用コンテナを作る

こんにちは。今回はMinecraft Bedrockサーバー(以下、Bedrockサーバー)を動かすコンテナイメージを作成します。

長くなりそうなので、記事は3回程に分けて投稿する予定です。

はじめに

Minecraft(統合版)はPC、Nintendo SwitchiOSAndroidなどのプラットフォームで展開されている有名なサンドボックスゲームです。

また、クロスプレイにも対応しておりRealmsやサーバーを利用することで、離れた場所にいるプレイヤーと一緒に遊べます。

本記事ではMinecraft公式のBedrockサーバーをコンテナで動かし、コンテナやDockerfileの作り方について学んでいきます。

想定読者

  • Dockerは使っているけれど、Dockerfileは何となく書いている方
  • Minecraftをみんなで遊びたい方

前提

  • 筆者の環境はApple Silicon搭載のMac
  • Docker Desktop for Macを導入済み

なぜコンテナ化するのか

Bedrockサーバーはステートレスではないため、一般的なWebサービスと比べるとコンテナ化のメリットは少ないでしょう。

ただし、アーキテクチャの制約や永続ボリュームの利用、設定ファイルの管理など、コンテナ化に際して考慮すべき点が多い分、それらを学ぶ良い機会にもなります。

さらに、近年はARMを採用するコンピュータが増えているため、Dockerを利用してx86_64のバイナリを動作させられる環境を用意しておくことで、環境構築の手間を大幅に削減できるでしょう。

(もっとも、実際のところは趣味が理由で、理屈は後付けです…)

作業用コンテナを使った動作確認

今回は作業用コンテナを使用して、Bedrockサーバーが起動し、Minecraftクライアント(アプリ)から接続できるところまで確認します。

作業用コンテナの起動

Bedrockサーバーはx86_64のバイナリイメージしか配布されていないため、作業用に同アーキテクチャのコンテナを立ち上げます。

もし、x86_64のマシンを使っている場合でも、これから作成するDockerfileの挙動を把握するために作業用コンテナを立ち上げましょう。

また、コンテナとMinecraftクライアントで通信ができるように、あらかじめUDPの19132番ポートを開放します。

Bedrockサーバーは公式でUbuntuをサポートしていますが、今回はDebianベースのコンテナイメージを選択しました。理由は次回説明します。

$ docker container run --platform=linux/amd64 --rm -p 19132:19132/udp -it debian:bookworm-slim /bin/bash
root@8de161ca6300:/#

作業用コンテナのセットアップ

Bedrockサーバーを起動するためにいくつかのパッケージが必要です。以下のコマンドで必要なパッケージをインストールします。

パッケージのインストールはDockerfile作成を考慮し、aptではなくapt-getを利用し、必要最小限のパッケージのみ導入します。

root@8de161ca6300:/# apt-get update && apt-get install -y --no-install-recommends ca-certificates curl unzip

また、作業用ディレクトリを作成し、以降の作業はそのディレクトリ内でおこないます。

root@8de161ca6300:/# mkdir work
root@8de161ca6300:/# cd work/
root@8de161ca6300:/work#

サーバーのダウンロード

Minecraftの公式サーバーをダウンロードします。ブラウザで以下のサイトを開きます。

www.minecraft.net

今回は「UBUNTU (LINUX) 用 MINECRAFT 専用サーバーのソフトウェア」を利用しますが、作業用コンテナ内でファイルを利用したいためダウンロードリンクを確認します。

リンクを確認したら、コンテナ内でcurlコマンドを利用してアクセスするため、User-Agentを指定してダウンロードします。User-Agentを指定しないと、ダウンロードが失敗します。

root@8de161ca6300:/work# curl -s \
  -H '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' \
  -O 'https://www.minecraft.net/bedrockdedicatedserver/bin-linux/bedrock-server-1.21.51.02.zip'
root@8de161ca6300:/work#

これで、Bedrockサーバーがダウンロードされました。

アーカイブの展開と確認

ダウンロードしたファイルをunzipコマンドで展開し、lsコマンドで中身を確認します。

root@8de161ca6300:/work# unzip -q bedrock-server-1.21.51.02.zip -d bedrock-server
root@8de161ca6300:/work# cd bedrock-server
root@8de161ca6300:/work/bedrock-server# ls -l
total 165712
-rw-rw-r--  1 root root         3 Dec 10 17:35 allowlist.json
-rwxrwxr-x  1 root root 169604952 Dec 10 17:47 bedrock_server
-rw-rw-r--  1 root root     28041 Dec 10 17:35 bedrock_server_how_to.html
drwxrwxr-x 55 root root      4096 Dec 10 17:47 behavior_packs
drwxrwxr-x  3 root root      4096 Dec 10 17:47 config
drwxrwxr-x  9 root root      4096 Dec 10 17:47 definitions
-rw-rw-r--  1 root root         3 Dec 10 17:35 permissions.json
-rw-rw-r--  1 root root      8548 Dec 10 17:42 profanity_filter.wlist
-rw-rw-r--  1 root root       398 Dec 10 17:35 release-notes.txt
drwxrwxr-x  5 root root      4096 Dec 10 17:47 resource_packs
-rw-rw-r--  1 root root     10007 Dec 10 17:35 server.properties
root@8de161ca6300:/work/bedrock-server#

bedrock_serverというサーバー本体のバイナリが確認できたので、起動に必要なライブラリが揃っているか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#

必要なライブラリも揃っていることが確認できました。

Bedrockサーバーの起動

コンテナ内でBedrockサーバーが起動できるか試します。

root@8de161ca6300:/work/bedrock-server# ./bedrock_server
NO LOG FILE! - setting up server logging...
[2024-12-22 02:56:52:683 INFO] Starting Server
[2024-12-22 02:56:52:683 INFO] Version: 1.21.51.02
[2024-12-22 02:56:52:683 INFO] Session ID: 8fc0339d-ce9d-420b-84bf-5b0392cb06c1
[2024-12-22 02:56:52:683 INFO] Build ID: 29823500
[2024-12-22 02:56:52:683 INFO] Branch: r/21_u5
[2024-12-22 02:56:52:683 INFO] Commit ID: 15737c809ed75cbc4a361ffa3c5c2df76ff78d42
[2024-12-22 02:56:52:683 INFO] Configuration: Publish
[2024-12-22 02:56:52:686 INFO] Level Name: Bedrock level
[2024-12-22 02:56:52:689 INFO] No CDN config file found for dedicated server
[2024-12-22 02:56:52:690 INFO] Game mode: 0 Survival
[2024-12-22 02:56:52:690 INFO] Difficulty: 1 EASY
[2024-12-22 02:56:52:697 INFO] Content logging to console is enabled.
[2024-12-22 02:56:52:953 INFO] Opening level 'worlds/Bedrock level/db'
[2024-12-22 02:56:53:150 INFO] [SERVER] Pack Stack - None
[2024-12-22 02:56:54:409 INFO] IPv4 supported, port: 19132: Used for gameplay and LAN discovery
[2024-12-22 02:56:54:409 INFO] IPv6 supported, port: 19133: Used for gameplay
[2024-12-22 02:56:54:443 INFO] Server started.
[2024-12-22 02:56:54:443 INFO] ================ TELEMETRY MESSAGE ===================
[2024-12-22 02:56:54:443 INFO] Server Telemetry is currently not enabled.
[2024-12-22 02:56:54:443 INFO] Enabling this telemetry helps us improve the game.
[2024-12-22 02:56:54:443 INFO]
[2024-12-22 02:56:54:443 INFO] To enable this feature, add the line 'emit-server-telemetry=true'
[2024-12-22 02:56:54:443 INFO] to the server.properties file in the handheld/src-server directory
[2024-12-22 02:56:54:443 INFO] ======================================================

気になるメッセージがいくつかでていますが、サーバーのプロセスは無事に起動しました。

Bedrockサーバーへの接続

MinecraftクライアントからBedrockサーバーへ接続できるか確認します。

動作確認にはiOS版のMinecraftを使用します。アプリを起動し「プレイ」ボタンをタップ後、「フレンド」タブをタップします。

すると「LAN ゲーム」の項目に「Dedicated Server」が表示されます。しばらく待っても表示されない場合は、ファイアウォールやDockerのネットワークを見直しましょう。

The Dedicated Server is displayed on the screen.
Bedrockサーバーが表示される

次に、表示された「Dedicated Server」をタップしてコンテナに接続します。こちらも上手く接続できました。

Successfully connected to the Bedrock Server container.
Bedrockサーバーのコンテナへの接続が成功

接続の確認ができたらゲームを終了します。コンテナ側の標準出力には、以下のようなメッセージが表示されます。

[2024-12-22 03:03:18:985 INFO] Player connected: takenorio, xuid: ****************
[2024-12-22 03:03:22:794 INFO] Player Spawned: takenorio xuid: ****************, pfid: ****************
[2024-12-22 03:04:12:626 INFO] Player disconnected: takenorio, xuid: ****************, pfid: ****************

Bedrockサーバーを停止し、exitコマンドでコンテナも終了します。

^C
root@8de161ca6300:/work/bedrock-server# exit
exit

まとめ

作業用コンテナ上のBedrockサーバーにMinecraftのアプリケーションから接続できることを確認しました。

次回は作業用コンテナの動作確認結果を元にDockerfileを作成します。

モジュール分割単位の考え方

こんにちは。Findy SREチームの大矢(@takenorio)です。この記事はFindy Advent Calendar 2024 16日目の投稿です。

はじめに

Terraformでシステムを構築する中で、モジュールの分割単位に悩むことはないでしょうか。

モジュールの適切な分割はコードの再利用性を高め、保守性を向上させる重要な要素です。しかし、どのように分割すればよいか、経験が少ないと難しく感じることはないでしょうか。

本記事ではモジュールの分割単位を考えるための具体的なアイディアを発信いたします。

想定読者

  • Terraformを使用しているがモジュールを利用していない人
  • モジュールを使っているが分割単位に悩んでいる人

話すこと

  • モジュールの分割単位の考え方

話さないこと

モジュールの導入の契機

システムが小さいうちはTerraformでモジュールを使わない場合もあるでしょう。

しかし、開発規模が大きくなり、開発環境、ステージング環境、本番環境というように複数の環境ができると、モジュールの実装が必要になる場面が増えてくるのではないでしょうか。

例えば、以下のような利点を考えると、モジュールの導入は非常に効果的です。

  • 複数環境で同一のモジュールを利用できるため、環境ごとの構築作業を軽減、作業ミスを防止できる
  • モジュールを修正する場合、すべての環境に反映できるため、メンテナンスが簡素になる
  • ソースコードの見通しがよくなる、ソースコードを理解しやすくなる

これらの理由から、複数の環境が存在する場合やシステムごとに共通のリソースが必要となる場合には、モジュールを積極的に導入するとよいでしょう。

モジュールの分割単位

考え方

Terraformでモジュールを作成するさい、どのような単位で分割すればよいのでしょう。以下のポイントを考慮してみてください。

役割が明確であること

モジュールは、静的ウェブサイトを作る、コンテナのクラスターを作るなど、特定の目的に特化させると良いでしょう。役割を絞ることで再利用性が高まり、ソースコードの保守は容易になります。逆にさまざまなパターンを想定し汎用性を求めすぎないようにしましょう。

疎結合であること

他のリソースとの依存関係を極力減らし、モジュール単体で意味のあるリソース群ができる設計を心がけましょう。特にRemote StateやData Sourcesを使ったリソース感の参照を最小限にすることで、依存関係の複雑化を防ぎます。

再利用可能であること

モジュールは、開発環境、ステージング環境、本番環境など複数の環境で再利用できることを目指しましょう。また、他のシステムやプロジェクトでも使える設計にすることで、生産性向上にもつながるでしょう。

具体例

考え方に沿った分割例

ウェブサイトをAWS上に構築する場合、以下のようなリソースが必要になります。

さらに細かい話をするとS3を1つとっても、バケットポリシー、ロギング、アクセスコントロール、暗号化などの設定をコード化する必要があります。これらを1つのモジュールとしてまとめて管理することで、モジュールの利用者はウェブサイトを構築するという目的が容易に達成できるようになります。

同様の考え方でコンテナのクラスターやデータベースといったバックエンドに必要なリソースを作成します。モノレポでTerraformのソースコードを管理した場合、以下のようなディレクトリ構成になるでしょう。

.
├── environments
│   ├── develop
│   ├── production
│   └── staging
└── modules
    ├── container
    ├── database
    ├── network
    └── website

考え方に沿っていない分割例

前述の考え方に沿わず、S3、CloudFront、KMSなどリソース単位でモジュールを分割するとRemote StateやData Sourcesを利用した参照が多くなり依存関係は複雑化します。

以下の例ではCloudFrontはオリジンを特定するためS3を参照します。また、S3はバケットの暗号化のためにKMSを参照、KMSは暗号化されたS3へのアクセス許可をおこなうためCloudFrontを参照します。

その結果、CloudFront、S3、KMS間での循環参照が発生することで、ソースコードの修正なしにTerraformからリソースをApplyできなくなってしまいます。

.
├── environment
│   ├── develop
│   ├── production
│   └── staging
└── modules
    ├── alb
    ├── cloudfront
    ├── ecs
    ├── kms
    ├── rds
    ├── s3
    └── vpc

HCP TerraformとPrivate Registry

上記の例はモノレポでソースコードを管理している場合を想定しましたが、HCP Terraform提供のPrivate Registryを利用すればPrivateな環境でモジュールの管理と利用が可能です。

システム間でモジュールを共有する場合はそちらを利用することになりますが、本記事では紹介のみとさせていただきます。

モジュールを使うことが難しい例

モジュールも万能ではありません。システム特有の要件や頻繁な変更がある場合、モジュールを使わないほうが良い場合もあります。適切な用途を決めた上で使用することが重要です。

Route 53において環境に差分が多数ある場合

Zoneは各環境で作成し、モジュールからはZoneに対してレコードを追加する程度にとどめると良いでしょう。

CloudFrontでOriginとCache Behaviorを細かく制御したい場合

OriginやCache Behaviorの情報を環境側で定義し、モジュール側でdynamicを使えば実現可能です。しかし、モジュールの呼び出し元で多くの設定をコーディングしなければならず、その結果可読性は低くなるでしょう。

複雑な設定になりそうな場合は、システム間での共通利用は避けて同一システムの複数環境間での利用にとどめると良いでしょう。

おわりに

本記事では、モジュールの役割を明確にし、他のリソースとの依存関係を減らし、再利用可能な設計を目指すことの重要性をお伝えしました。また、モジュール分割の具体例や、失敗しやすいリソース単位での分割についても触れました。

モジュールは万能ではないため、システムの要件や規模に応じて適切に使い分けることが大切です。この記事がTerraform運用の一助となりましたら幸いです。