DockerでMinecraft Serverを立てる

Dockerはいろんな使い方ができるので、マイクラサーバーとかを立てることもできる。
そういう使い方もされるみたい？なので自分なりにDockerを使ってバニラのマイクラサーバーを立ててみる。
今回はDockerfileの編集手順もまとめていきたい。

# 目次
* Javaの実行環境を入れる
* マイクラサーバーの入手
* ディレクトリの場所を整理
* データをマウントしてローカルへ保存する
* CMDコマンドの設定

# 環境
* Docker version 20.10.6
* Ubuntu（ベースイメージ） version latest
* エディタ：VScode

# Dockerfileの作成
まず、ubuntuのイメージを起動してコマンドを手打ちして確認作業をしつつ書いていきます。

```terminal
$ docker run -it ubuntu bash
```

## Javaの実行環境を入れる
まずはいつものapt関連の更新をしておく。

```terminal
$ apt update && apt upgrade -y
```
次にJavaを入れるために

```terminal
$ apt search openjdk-\(\.\)\+-jre$
```
これを実行してJavaのJRE（実行環境）で有効なバージョン一覧を表示する。
自分のやったタイミングでは11, 13, 14, 16, 8が表示される。
~~そこで自分も扱ったことの多い8を選択（他のバージョンで何か問題が起きるのが嫌なので）。~~
<font color='red'>2021/6/9現在、マイクラの最新バージョン1.17でJavaのバージョンが16でないと起動できないことを確認したので、バージョン16に訂正しておきます(&記事内のマイクラバージョンも1.17にします)。
<font>

```terminal
$ apt install openjdk-16-jre
```
でインストールする。
と、タイムゾーン選択の処理が入る。

タイムゾーンはtzdataのパッケージを入れて対処をする。
ここまでをDockerfileに書いていく。

```docker
FROM ubuntu:latest
RUN apt update && apt upgrade -y && apt install -y tzdata
ENV TZ Asia/Tokyo
RUN apt install -y openjdk-16-jre
```
ここで一旦ビルドして、エラーがでないかを確認しておくのもよき。

```terminal
$ docker build .
$ docker run -it <docker-image-id>
```

## マイクラサーバーの入手
マイクラサーバーのクライアントをインターネットから入手する必要がある。
そこで、wgetのパッケージが必要なのでこれをインストールする。

```terminal
$ apt install wget
```
そしたらバージョン毎にダウンロード可能なArchiveが保存されてるサイトを参照する。
[ここ](https://mcversions.net/)⇦から今回は1.16.5のクライアントをダウンロードします。
Downloadを押して、Download　Server　Jarのリンクをコピーして、wgetでダウンロードします。

```terminal
$ wget https://launcher.mojang.com/v1/objects/0a269b5f2c5b93b1712d0f5dc43b6182b9ab254e/server.jar
```
これでクライアントの準備はできました。
ここまでをDockerfileに書きましょう。

```docker
FROM ubuntu:latest
RUN apt update && apt upgrade -y && apt install -y tzdata wget
ENV TZ Asia/Tokyo
RUN apt install -y openjdk-8-jre && \
    wget https://launcher.mojang.com/v1/objects/0a269b5f2c5b93b1712d0f5dc43b6182b9ab254e/server.jar

```
レイヤーをできるだけ減らすため、&&を使って記述していきます。

## ディレクトリの場所を整理
ここでディレクトリの整理をします。もうすでに必要最低限のパッケージなどはインストール済みです。
まず、サーバークライアントはoptディレクトリに入れます。通常はソフトウェアなどを入れるフォルダです。
サーバーの主要ファイル群はrootディレクトリに入れます。
なので、ダウンロード場所をoptにして、コマンド実行をrootディレクトリで行うようにします。

```docker
FROM ubuntu:latest
RUN apt update && apt upgrade -y && apt install -y tzdata wget
ENV TZ Asia/Tokyo
WORKDIR /opt
RUN apt install -y openjdk-8-jre && \
    wget https://launcher.mojang.com/v1/objects/0a269b5f2c5b93b1712d0f5dc43b6182b9ab254e/server.jar
WORKDIR /root
```
optに移動して、サーバークライアントをダウンロード後、ルートディレクトリに移動しておきます。

## データをマウントしてローカルへ保存する
ここはかなり重要な部分です。
コンテナ内にサーバーデータを置いたままだとコンテナを閉じた時にデータが全部なくなってしまいます。
そこで、以下の図のようなディレクトリ構成でマウントを行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456646/1f6e9d64-393a-1ad2-c0fe-1c33ae09fb26.png)
まず、コンテナ内とローカルPCでマウントするディレクトリは、/mnt/varと、./varです。
その後、/mnt/varのデータを/rootに移動させる。それでサーバークライアントを起動させ、ストップしたら/rootのデータを/mnt/varに移動させる。
これでデータを保存することができます。
これをシェルスクリプトに書いておきます。

```shell
mv /mnt/var/* /root
java -Xmx1024M -Xms1024M -jar /opt/server.jar
mv /root/* /mnt/var
```
ここまでをDockerfileに書きます。

```docker
FROM ubuntu:latest
RUN apt update && apt upgrade -y && apt install -y tzdata wget
ENV TZ Asia/Tokyo
WORKDIR /opt
RUN apt install -y openjdk-8-jre && \
    wget https://launcher.mojang.com/v1/objects/0a269b5f2c5b93b1712d0f5dc43b6182b9ab254e/server.jar
WORKDIR /root
RUN echo "mv /mnt/var/* /root" > run.sh && \
    echo "java -Xmx1024M -Xms1024M -jar /opt/server.jar" >> run.sh && \
    echo "mv /root/* /mnt/var" >> run.sh
```
## CMDコマンドの設定
CMDコマンドは、先程のシェルスクリプトを指定します。
これに加えて、CMDで実行するために実行権限を持たせるコマンド、マウント先のディレクトリ作成、eula=ture(これがないとサーバーが起動できない)のファイルを作成、というコマンドを追加して、Dockerfile完成です。

```docker
FROM ubuntu:latest
RUN apt update && apt upgrade -y && apt install -y tzdata wget
ENV TZ Asia/Tokyo
WORKDIR /opt
RUN apt install -y openjdk-8-jre && \
    wget https://launcher.mojang.com/v1/objects/0a269b5f2c5b93b1712d0f5dc43b6182b9ab254e/server.jar
WORKDIR /root
RUN echo eula=true > eula.txt && echo "mv /mnt/var/* /root" > run.sh && \
    echo "java -Xmx1024M -Xms1024M -jar /opt/server.jar" >> run.sh && \
    echo "mv /root/* /mnt/var" >> run.sh && chmod 777 run.sh && mkdir /mnt/var
CMD ["sh", "run.sh"]
```

# docker-compose.ymlを作成
上のDockerfileをビルドすればできますが、立ち上げるときのマウントやポート指定を楽にするためにymlファイルを作成します。

```yaml
version: '3'

services:
  mcserver:
    image: sugimochi/mcserver
    volumes:
      - './var:/mnt/var'
    ports:
      - '25565:25565'
    tty: true
    stdin_open: true
```

# まとめ
これにて完成です。
一つ一つ確認しながらDockerfileを書いていくという流れをよく理解することができました。
また環境を作ったりするときにこういう練習はしていきたいですね。

# 参考文献
* [Linuxディレクトリ構造](https://qiita.com/nys9302/items/a8ddeedd3cd9d0deb332)
* [OpenJDK（Java）を最新のUbuntuにインストール](https://qiita.com/terappy/items/537c069923144a9d9755)
* [MCVERSIONS.NET](https://mcversions.net/)
* [Dockerfile で cd が効かない](https://christina04.hatenablog.com/entry/2014/10/31/101510)
* [【最新版対応】マイクラサーバーの立て方【公式サーバー bat編】](https://mcpoteton.com/mcserver/official-bat)
* [Dockerで複数CMDを実行する方法](https://sleepless-se.net/2018/05/26/docker%E3%81%A7%E8%A4%87%E6%95%B0cmd%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/)
* [Linuxの権限確認と変更(chmod)（超初心者向け）](https://qiita.com/shisama/items/5f4c4fa768642aad9e06)

# Git Hub
[https://github.com/sugimochi97/docker_mcserver](https://github.com/sugimochi97/docker_mcserver)