Docker使って超簡単にJava版、BE版クロスプレイ対応Minecraft Serverを建ててみた

# 今回やったこと
- Java版、BE版クロスプレイ対応のMinecraft ServerコンテナをDockerで0から建てる
- セキュリティも少し考慮してホワリスを追加してみる

# 環境
- オンプレサーバ（Ubuntu Server 22.04LTS）

# 全体の流れ

1. Server, client側の前準備
1. MinecraftServerのセットアップ
1. コンテナ起動、ホワリスなどの編集

# 1. 前準備

Docker、Docker-composeのインストまで完了してる人は飛ばしてください

### マイクラのclient側(ランチャー)をインストールしておく

https://www.minecraft.net/ja-jp/download

### rootに昇格（ここからはServer側の作業）

```
# sudo su -
```

### タイムゾーン設定

```
// 設定
# timedatectl set-timezone Asia/Tokyo

// 確認
# timedatectl
               Local time: Sun 2023-07-16 21:02:11 JST   ### JSTとなっていることを確認 ###
           Universal time: Sun 2023-07-16 12:02:11 UTC
                 RTC time: Sun 2023-07-16 12:02:11
                Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no
```

### パッケージのアプデ

```
# apt -y update
# apt -y upgrade
```

### ufw設定

- 本当は必要だけど今回はルーター側でポート転送を設定してあるので不要
- だけど後で設定します

### dockerのインストール

```
// GPGキーを保存するディレクトリを作る
mkdir -p /etc/apt/keyrings

// GPGキーを取得する
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

// Dockerレポジトリを追加する
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

// パッケージリストの更新
apt-get update

// Dockerプラグインのインストール
apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
```

### dockerのテスト

```
docker -v
```

![スクリーンショット 2024-02-02 18.57.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3504047/41cb3aeb-8adf-d1be-8652-5cafd8e73d50.png)

上記のようにバージョンが表示される

```
docker run hello-world
```

![スクリーンショット 2024-02-02 18.58.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3504047/b93ea772-287d-54fd-02e3-cc771dc6dff7.png)

このコマンドに成功すると、上記の写真のように`Hello from Docker!`と表示されます。

### docker-composeのテスト

```
docker-compose -v
```

![スクリーンショット 2024-02-21 15.29.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3504047/3491fdb5-5907-4fc8-238c-1f04fada7dc6.png)

このコマンドに成功すると、写真のようにバージョンが表示される

### 参考

https://qiita.com/Higemal/items/1ed9f2ec3200d6777562

https://qiita.com/sugimochi_1019/items/c022277d48bf6eb398e6

https://www.kagoya.jp/howto/cloud/container/dockerubuntu/


# 2. Minecraft Serverの設定

今回はすでに有志が用意してくれてあるDockerで構築可能なものを使用する

以下の記事を参考にしました

https://qiita.com/mabubu0203/items/59a78b689740b42549c0

このDocker hubからimageを持ってきて使用するイメージです

バージョンはお好みで

https://hub.docker.com/r/itzg/minecraft-server

### Githubのクローン

```
git clone https://github.com/mabubu0203/minecraft_multi.git
```

### Githubのクローンを自分のGithubにpushする

https://yuito-blog.com/repository-change/

```
// リモートレポジトリを変更
git remote set-url origin [変更したいリポジトリのURL]

//　変更を確認
git remote -v
```

あとは普通にpushすればOKです

### 少し修正を加える

基本上記のままで大丈夫ですが、私の使いたい環境に合わせてymlを以下のように修正しました。

- バックアップの無効化（私の環境では不要なため）
- マイクラバージョンの最新化
- docker imageの最新化
- 不要な項目の無効化

```
version: "3.8"

services:
  mc-spigot:
    image: "itzg/minecraft-server:latest"
    container_name: "mc-spigot"
    tty: true
    stdin_open: true
    ports:
      - "19132:19132/udp"
      - "19133:19133/udp"
      - "25565:25565/tcp"
      - "25575:25575/tcp"
    environment:
      # server.properties
      ALLOW_FLIGHT: "false"
      ALLOW_NETHER: "true"
      ANNOUNCE_PLAYER_ACHIEVEMENTS: "true"
      BROADCAST_CONSOLE_TO_OPS: "true"
      BROADCAST_RCON_TO_OPS: "true"
      DEBUG: "false"
      DIFFICULTY: "easy" # 難易度
      ENABLE_COMMAND_BLOCK: "true"
      ENABLE_JMX: "false"
      ENABLE_RCON: "true"
      ENABLE_STATUS: "true"
      ENFORCE_SECURE_PROFILE: "false"
      ENFORCE_WHITELIST: "true" # ホワイトリストの有効化
      FORCE_GAMEMODE: "true"
      FUNCTION_PERMISSION_LEVEL: 2
      GENERATE_STRUCTURES: "true"
      HARDCORE: "false"
      LEVEL_NAME: "world"
      LEVEL_TYPE: "DEFAULT"
      MAX_PLAYERS: 15 # プレイヤー最大人数
      MODE: "survival" # ゲームモード
      ONLINE_MODE: "true"
      OP_PERMISSION_LEVEL: 4
      PREVIEWS_CHAT: "true"
      PVP: "true" # ユーザー同士のダメージを有効にするか
      RCON_PASSWORD: "${RCON_PASSWORD}"
      RCON_PORT: 25575
      SERVER_NAME: "SuwaGeeksMinecraft_Server"
      SERVER_PORT: 25565
      SIMULATION_DISTANCE: 12
      SNOOPER_ENABLED: "false"
      SPAWN_ANIMALS: "true"
      SPAWN_MONSTERS: "true"
      SPAWN_NPCS: "true"
      SPAWN_PROTECTION: 0
      USE_NATIVE_TRANSPORT: "true"
      VIEW_DISTANCE: 12
      WHITELIST: "${WHITELIST}"
      # other
      ENABLE_WHITELIST: "TRUE"
      EULA: "TRUE"
      MAX_MEMORY: "12G" # 最大メモリ
      MEMORY: "6G" # メモリ
      MODS_FILE: "/extras/mods.txt"
      OVERRIDE_SERVER_PROPERTIES: "true"
      REMOVE_OLD_MODS: "true"
      REMOVE_OLD_MODS_DEPTH: 1
      REMOVE_OLD_MODS_INCLUDE: "*.jar"
      TYPE: "SPIGOT"
      TZ: "Asia/Tokyo"
      VERSION: "1.20.4" # バージョン(2024/2/21最新)
    volumes:
      - "./data:/data"
      - "./mods.txt:/extras/mods.txt:ro"
    restart: unless-stopped
```

mods.txtの修正も必須です（リンク切れを起こしてる）

`Geyser-Spigot.jar`はここからダウンロード

https://ci.opencollab.dev//job/GeyserMC/job/Geyser/job/master/

`floodgate-spigot.jar`はここからダウンロード

https://wiki.geysermc.org/floodgate/setup/

最終的にmods.txtはこのようになりました
```
https://ci.opencollab.dev//job/GeyserMC/job/Geyser/job/master/lastSuccessfulBuild/artifact/bootstrap/spigot/build/libs/Geyser-Spigot.jar
https://download.geysermc.org/v2/projects/floodgate/versions/latest/builds/latest/downloads/spigot
```

### ufw設定

Server側でポートを開放します

フル開放してしまえば気にすることはないですが、怒られそうなので()

https://qiita.com/010Ri/items/f37f7f5fb35265823c7c

```
// 管理者権限でコンソールを弄っていることを前提にしてます（sudoつけてね）
// UFWが起動しているかチェック
ufw status

// 起動していなければ起動
ufw enable

// sshで使用するポート、サーバーの通信ポートを許可
ufw allow 22/tcp
ufw allow 25565/tcp
ufw allow 19132/udp

// 一応再起動
ufw reload

// 間違えたらこれで削除可能（何番目のルールか指定する）
ufw delete 1
```

![スクリーンショット 2024-02-22 1.19.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3504047/033e3c98-1f88-9a6e-e1c3-01c1caeeb39d.png)

最終的にこんな感じになりました

### 起動

https://github.com/Kento210/MinecraftServer

```
git clone https://github.com/[ユーザーID]/[作成したレポジトリ名]
```

まずサーバーでクローンします

以下起動手法（初回のみ）

```
// .env.sampleをコピーして編集
cp ./docker/.env.sample ./docker/.env
vi ./docker/.env

// ビルドと起動
docker-compose -f ./docker/docker-compose.yml up --build --remove-orphans

// 起動を確認したら一旦停止
docker-compose -f ./docker/docker-compose.yml stop
```
<br>

設定を更新1（Geyser-Spigot）

`auth-type: online` を `auth-type: floodgate` に変更

```
vi ./docker/data/plugins/Geyser-Spigot/config.yml
```

設定を更新2（floodgate）

`username-prefix: ".”` を `username-prefix: "【BE】”` に変更

```
vi ./docker/data/plugins/floodgate/config.yml
```
<br>

通常起動方法

```
// start
docker-compose -f ./docker/docker-compose.yml start

//stop
docker-compose -f ./docker/docker-compose.yml stop
```

以上で完了です。

お疲れ様でした。

# 3. メモ

### サーバーコマンドの実行方法

```
// ここでは"whitelist reload"コマンドを実行している
docker exec -i <コンテナ名またはID> rcon-cli whitelist reload
```

### ホワイトリストの使用方法

https://minecraft.server-memo.net/whitelist/

`whitelist.json`を開いて

```
vi ./docker/data/whitelist.json
```

以下のように`uuid`と`name`をjsonに登録することでワールドへ入ることが可能です

uuidは公式が提供するAPIで取得するか、サーバーログにて一度入ってみることで確認可能です

```
[
    {
      "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "name": "xxxxx"
    },
    {
      "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "name": "xxxxx"
    }
]
```

### ops.json（op権限の付与）について

https://mc.server-memo.net/add-op/

`ops.json`を開いて

```
vi ./docker/data/ops.json
```

以下のように`uuid`と`name`に加えて`level`、`bypassesPlayerLimit`をjsonに登録することで管理者権限を付与することが可能です

ここでのbypassesPlayerLimitとは、設定したサーバー人数の上限に達しているとき、そのサーバーに入ることが可能かを設定するものです

```
[
  {
    "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "name": "xxxxx",
    "level": 4,
    "bypassesPlayerLimit": false
  },
  {
    "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "name": "xxxxx",
    "level": 4,
    "bypassesPlayerLimit": false
  }
]
```

また何かあったら追記します。

それでは