sumisoクラフト

sumisoクラフトはてなブログ拠点

Dockerでマイクラのサーバーを立てる【Java版マイクラ】

Java版マイクラのデータパックの動作検証用に
dockerでマイクラサーバーを構築し
ワールドデータを使い捨てにできる開発環境を作成しました

目次

環境

wsl2にdockerはインストール済みです

構成図

wsl2上のdockerにマイクラサーバーのコンテナを作成し
windowsのマイクラからアクセスします

システム構成図

wsl2でのホスト側最終的なディレクトリ構成図

minecraft/                  適当な作業用フォルダ
 ├ sample/                 マイクラサーバー起動して生成されるファイル格納用
 ├ datapacks/              開発中のデータパックを入れるフォルダ
 │ └ dark_sabanna/        データパック本体
 ├ data/                   コンテナにCOPYするファイル
 │ ├ eula.txt             利用規約に同意
 │ ├ ops.json             op権限設定
 │ ├ server.jar           マイクラサーバー.jar
 │ └ server.properties    ワールドの設定
 ├ docker-compose.yml      ポートやボリュームの設定
 └ Dockerfile              コンテナイメージの設定

Ubuntuでマイクラサーバー構築

Dockerfile用のコマンド確認も含めて
1度マイクラのサーバーを起動して
設定ファイルなどを生成させます

とりあえずUbuntuのイメージからコンテナを起動します
ホスト側minecraftフォルダから実行します

docker container run \
    --name mitest \
    --interactive      \
    --tty              \
    --rm \
    --publish 25565:25565 \
    --mount type=bind,src=$(pwd)/sample,dst=/minecraft \
    --mount type=bind,src=$(pwd)/datapacks,dst=/minecraft/world/datapacks \
    --mount type=bind,src=/etc/passwd,dst=/etc/passwd,readonly \
    --mount type=bind,src=/etc/group,dst=/etc/group,readonly \
    --user 1000:1000 \
    ubuntu:22.04

コンテナ内部で生成したファイルをホスト側で利用したいため
コンテナで使用するユーザーをホスト側のユーザーと合わせています

参考
Dockerコンテナの実行ユーザーと権限の関係
https://qiita.com/yitakura731/items/36a2ba117ccbc8792aa7

普通にJava版マイクラサーバーを構築します
各種インストールのため、rootでアタッチしなおします

# デタッチ
# [control-P] [control-Q]

# rootでアタッチ
docker exec -u 0 -it mitest bash

VScodeのターミナルからデタッチ操作する場合は
ショートカットが他の設定と被ってるので注意
ショートカットの設定を解除すれば使えます

とりあえず更新します

apt update

ファイル一覧確認

ls

マウントで生成されているはずのminecraftフォルダの存在確認します
minecraftに移動します

cd minecraft

Javaのインストールを確認します
入ってません

java --version

Javaのインストールできるバージョン一覧を取得します

apt-cache search openjdk

適当に新しそうなものをインストールします

apt-get install -y openjdk-21-jre-headless

他にweget, screen, vimをインストールしました

apt-get -y install wget
apt-get -y install screen
apt-get -y install vim

root権限が必要な使いそうなアプリのインストールは終わったので
作業用ユーザーに切り替えます

# デタッチ
# [control-P] [control-Q]

# userで入る
docker attach -it mitest

Java版のマイクラサーバーをダウンロードします
下記サイトにjarのダウンロードリンクがあるのでコピーして

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

ダウンロードします

wget https://piston-data.mojang.com/v1/objects/8dd1a28015f51b1803213892b50b7b4fc76e594d/server.jar

イクラサーバーを起動します

java -Xmx1024M -Xms1024M -jar server.jar nogui

この段階では、利用規約に同意していないので
すぐにサーバーが終了します

ファイルが生成されるので
利用規約に同意します
vimeula.txtを編集します

vi eula.txt

i で入力
falseをtrueに書き換え
escで入力終了
:wqで上書き保存 ミスってやり直したいときは
:q!

vim極めるとファイル編集が爆速になるらしい
vim使いたくない場合は、eula.txt自体を生成する方法もあります

echo "eula=true" > eula.txt

これでマイクラのサーバーが起動できます

java -Xmx1024M -Xms1024M -jar server.jar nogui

ワールドが生成されます
ここで、マイクラの作業用ユーザーにop権限を付けておきます
データパックの動作確認に、各種コマンドが使えるようにしておきます

# op [ユーザー名]
op sumiso_c0db8c

ワールドに入ってみます
イクラを起動し、マルチプレイを選択します

サーバーを追加
アドレスに

localhost

と入力して接続します
ワールドに入れることを確認して終了します

dockerのコンソールに戻るとプレイヤーが出入りしたログが確認できます

イクラのサーバーを停止します

stop

screenでマイクラサーバーを起動する場合は

# サーバー起動
screen -dmS minecraft java -Xmx1024M -Xms1024M -jar server.jar nogui

# 一覧表示
screen -ls
# マイクラサーバーにコマンド送信
screen -S minecraft -X stuff 'say hello'`echo -ne '\015'`
# マイクラサーバー終了
screen -S minecraft -X stuff 'stop'`echo -ne '\015'`

結局screenは利用しませんでした   

イクラサーバーの設定ファイルが生成できたので
コンテナを終了させます

Ubuntuのイメージをベースにしているため
bashを終了するとコンテナも終了します

exit

ホスト側Ubuntuに戻り
sampleフォルダにサーバーの設定ファイルが生成されています

sampleディレクトリから
eula.txt, ops.json, server.jar, server.properties
の4ファイルをdataディレクトリに移動させます

wsl2でのホスト側最終的なディレクトリ構成図

minecraft/                  適当な作業用フォルダ
 ├ sample/                 マイクラサーバー起動して生成されるファイル格納用
 ├ datapacks/              開発中のデータパックを入れるフォルダ
 │ └ dark_sabanna/        データパック本体
 ├ data/                   コンテナにCOPYするファイル
 │ ├ eula.txt             利用規約に同意
 │ ├ ops.json             op権限設定
 │ ├ server.jar           マイクラサーバー.jar
 │ └ server.properties    ワールドの設定
 ├ docker-compose.yml      ポートやボリュームの設定
 └ Dockerfile              コンテナイメージの設定

server.properties

イクラのワールドの設定を調整します

データパックの動作確認を目的としているため
クリエイティブモードになるようにしておきます

server.properties

allow-flight=false
allow-nether=true
broadcast-console-to-ops=true
broadcast-rcon-to-ops=true
# 難易度ハード
difficulty=hard
enable-command-block=false
enable-jmx-monitoring=false
enable-query=false
enable-rcon=false
enable-status=true
enforce-secure-profile=true
enforce-whitelist=false
entity-broadcast-range-percentage=100
force-gamemode=false
function-permission-level=2
# クリエイティブモード
gamemode=creative
generate-structures=true
generator-settings={}
hardcore=false
hide-online-players=false
initial-disabled-packs=
initial-enabled-packs=vanilla
level-name=world
# シード値 空欄でランダム生成
level-seed=141
level-type=minecraft\:normal
log-ips=true
max-chained-neighbor-updates=1000000
# 最大接続人数 マルチしないので1人でいい
max-players=10
max-tick-time=60000
max-world-size=29999984
# ワールドの説明 マルチプレイのワールド選択画面に表示される
motd=Datapacks Test Server
network-compression-threshold=256
online-mode=true
op-permission-level=4
player-idle-timeout=0
prevent-proxy-connections=false
pvp=true
query.port=25565
rate-limit=0
rcon.password=
rcon.port=25575
require-resource-pack=false
resource-pack=
resource-pack-id=
resource-pack-prompt=
resource-pack-sha1=
server-ip=
server-port=25565
simulation-distance=10
spawn-animals=true
spawn-monsters=true
spawn-npcs=true
spawn-protection=16
sync-chunk-writes=true
text-filtering-config=
use-native-transport=true
view-distance=10
white-list=false

変更した部分にコメント入れています

Dockerfile

Ubuntuでマイクラサーバー構築で確認したコマンドなどをもとに
Dockerfileを作成します

javaのイメージに変更しました

FROM openjdk:23-jdk

# server.propertiesなどをコピー
COPY  ./data/ /minecraft/
WORKDIR /minecraft

CMD java -Xmx1024M -Xms1024M -jar server.jar nogui

イクラのサーバー設定などはDockerfileに含めているので
変更したときはimageをビルドしてください

docker image build  \
    --tag midocker:minecraft    \
    --file Dockerfile    \
    .

Dockerfileからマイクラサーバー起動

docker container run        \
    --name mitest           \
    --interactive           \
    --tty                   \
    --rm                    \
    --mount type=bind,src=$(pwd)/datapacks,dst=/minecraft/world/datapacks \
    --publish 25565:25565   \
    midocker:minecraft      \

コンテナ停止

docker container stop mitest

イメージが蓄積してきたら適当に削除しておきます

# 使ってないimageの削除
docker image prune -a

docker-compose

docker-compose.ymlにまとめておきます

datapacksフォルダをマウントするように設定し
ワールド生成時にデータパック適用されるようにしています

version: '3.9'

services:
  minecraft:
    container_name: docker-minecraft
    build: 
      dockerfile: Dockerfile
      context: .
    volumes:
      - type : bind
        source: ./datapacks
        target: /minecraft/world/datapacks
    ports:
      - '25565:25565'

これで下記コマンドでいつでもマイクラのサーバーを構築して
ワールドデータを使い捨てにできます

# 起動
docker compose up --detach
# imageのビルドしなおす場合
docker compose up --build
# 終了
docker compose down

データパック

Dockerでマイクラサーバーが起動できるようになったので
データパックを適用してみます

サバンナバイオームを闇落ちさせるデータパックを作成します

ディレクトリ構成図

minecraft/                  適当な作業用フォルダ
 ├ sample/                 マイクラサーバー起動して生成されるファイル格納用
 ├ datapacks/              開発中のデータパックを入れるフォルダ
 │ └ dark_sabanna/        データパック本体
 ├ data/                   コンテナにCOPYするファイル
 │ ├ eula.txt             利用規約に同意
 │ ├ ops.json             op権限設定
 │ ├ server.jar           マイクラサーバー.jar
 │ └ server.properties    ワールドの設定
 ├ docker-compose.yml      ポートやボリュームの設定
 └ Dockerfile              コンテナイメージの設定

dark_sabannaがデータパック本体です

dark_savanna/
 ├ data/
 │ └ minecraft/
 │   └ worldgen/
 │     └ biome/
 │       └ savanna.json
 └ pack.mcmeta

pack.mcmeta
Java版マイクラ 1.20.4だと26のようです

{
  "pack": {
    "pack_format": 26,
    "description": {
      "text": "サバンナ闇落ちデータパック"
    }
  }
}

参考
https://minecraft.wiki/w/Pack_format

savanna.json
バイオームジェネレーターで適当にサバンナを魔改造します
https://misode.github.io/worldgen/biome/

{
  "temperature": 2,
  "downfall": 0,
  "has_precipitation": false,
  "effects": {
    "sky_color": 15279446,
    "fog_color": 8546241,
    "water_color": 7512092,
    "water_fog_color": 6997592,
    "grass_color": 8593860,
    "foliage_color": 4143022,
    "mood_sound": {
      "sound": "minecraft:ambient.cave",
      "tick_delay": 6000,
      "block_search_extent": 8,
      "offset": 2
    }
  },
  "spawners": {
    "ambient": [
      {
        "type": "minecraft:bat",
        "weight": 10,
        "minCount": 8,
        "maxCount": 8
      }
    ],
    "axolotls": [],
    "creature": [
      {
        "type": "minecraft:sheep",
        "weight": 12,
        "minCount": 4,
        "maxCount": 4
      },
      {
        "type": "minecraft:pig",
        "weight": 10,
        "minCount": 4,
        "maxCount": 4
      },
      {
        "type": "minecraft:chicken",
        "weight": 10,
        "minCount": 4,
        "maxCount": 4
      },
      {
        "type": "minecraft:cow",
        "weight": 8,
        "minCount": 4,
        "maxCount": 4
      },
      {
        "type": "minecraft:horse",
        "weight": 1,
        "minCount": 2,
        "maxCount": 6
      },
      {
        "type": "minecraft:donkey",
        "weight": 1,
        "minCount": 1,
        "maxCount": 1
      }
    ],
    "misc": [],
    "monster": [
      {
        "type": "minecraft:spider",
        "weight": 100,
        "minCount": 4,
        "maxCount": 4
      },
      {
        "type": "minecraft:zombie",
        "weight": 95,
        "minCount": 4,
        "maxCount": 4
      },
      {
        "type": "minecraft:zombie_villager",
        "weight": 5,
        "minCount": 1,
        "maxCount": 1
      },
      {
        "type": "minecraft:skeleton",
        "weight": 100,
        "minCount": 4,
        "maxCount": 4
      },
      {
        "type": "minecraft:creeper",
        "weight": 100,
        "minCount": 4,
        "maxCount": 4
      },
      {
        "type": "minecraft:slime",
        "weight": 100,
        "minCount": 4,
        "maxCount": 4
      },
      {
        "type": "minecraft:enderman",
        "weight": 10,
        "minCount": 1,
        "maxCount": 4
      },
      {
        "type": "minecraft:witch",
        "weight": 5,
        "minCount": 1,
        "maxCount": 1
      }
    ],
    "underground_water_creature": [
      {
        "type": "minecraft:glow_squid",
        "weight": 10,
        "minCount": 4,
        "maxCount": 6
      }
    ],
    "water_ambient": [],
    "water_creature": []
  },
  "spawn_costs": {},
  "carvers": {
    "air": [
      "minecraft:cave",
      "minecraft:cave_extra_underground",
      "minecraft:canyon"
    ]
  },
  "features": [
    [],
    [
      "minecraft:lake_lava_underground",
      "minecraft:lake_lava_surface"
    ],
    [
      "minecraft:amethyst_geode"
    ],
    [
      "minecraft:monster_room",
      "minecraft:monster_room_deep"
    ],
    [],
    [],
    [
      "minecraft:ore_dirt",
      "minecraft:ore_gravel",
      "minecraft:ore_granite_upper",
      "minecraft:ore_granite_lower",
      "minecraft:ore_diorite_upper",
      "minecraft:ore_diorite_lower",
      "minecraft:ore_andesite_upper",
      "minecraft:ore_andesite_lower",
      "minecraft:ore_tuff",
      "minecraft:ore_coal_upper",
      "minecraft:ore_coal_lower",
      "minecraft:ore_iron_upper",
      "minecraft:ore_iron_middle",
      "minecraft:ore_iron_small",
      "minecraft:ore_gold",
      "minecraft:ore_gold_lower",
      "minecraft:ore_redstone",
      "minecraft:ore_redstone_lower",
      "minecraft:ore_diamond",
      "minecraft:ore_diamond_medium",
      "minecraft:ore_diamond_large",
      "minecraft:ore_diamond_buried",
      "minecraft:ore_lapis",
      "minecraft:ore_lapis_buried",
      "minecraft:ore_copper",
      "minecraft:underwater_magma",
      "minecraft:disk_sand",
      "minecraft:disk_clay",
      "minecraft:disk_gravel"
    ],
    [],
    [
      "minecraft:spring_water",
      "minecraft:spring_lava"
    ],
    [
      "minecraft:glow_lichen",
      "minecraft:patch_tall_grass",
      "minecraft:trees_savanna",
      "minecraft:patch_grass_savanna",
      "minecraft:brown_mushroom_normal",
      "minecraft:red_mushroom_normal",
      "minecraft:patch_sugar_cane",
      "minecraft:patch_taiga_grass",
      "minecraft:patch_melon"
    ],
    [
      "minecraft:freeze_top_layer"
    ]
  ]
}

動作確認

イクラサーバーを起動します

# 起動
docker compose up --detach

イクラからワールドに接続します

シード値141を指定しているので
初期リスはサバンナバイオーム

闇落ちサバンナ

無事闇落ちサバンナが生成されています

闇落ちサバンナにはカボチャの代わりにスイカが生成されます

草の生えたスイカ

イカから草が生えてて草

動作を確認したらサーバー停止しワールドごと削除します

# 終了
docker compose down

まとめ

Dockerで使い捨てのJava版マイクラサーバーを起動できるようにしました

イクラのimageはDocker Hubに存在していますが
使わずに構築してみました

ワールドデータを保存するようにすれば、マルチプレイにも使えそうです

参考
実践 Docker - ソフトウェアエンジニアの「Docker よくわからない」を終わりにする本
https://zenn.dev/suzuki_hoge/books/2022-03-docker-practice-8ae36c33424b59