Docker desktop (Windows10) でローカルにMastodonサーバを立ててみる

## 前提

この記事で紹介するやり方はあくまで仮の環境であり、実際に稼働させるには問題が多いので本番として運用したい方には役に立たない。
「Mastodonサーバを立ててみたい」という好奇心を満たすためだけに推奨される方法である。

## 環境
```
OS: Windows 10 Home 64bit バージョン 20H2
Docker:  Docker desktop for Windows バージョン v20.10.5
WSL2用ディストリビューション: Ubuntu 18.04 LTS
ngrok: バージョン 2.3.38
Mastodon: バージョン v3.2.2
```

## docker-compose.yml の編集

1. [Mastodonのリポジトリ](https://github.com/tootsuite/mastodon)から`docker-compose.yml`、`.env.production.sample`をコピーしてくる。 
2. 環境変数設定ファイルである`.env.production.sample`を`.env.production`にリネームする。
3. ローカルビルドはしないので、web、streaming、sidekiqから`build: .`の行をコメントアウトする。 また、`image: tootsuite/mastodon:v3.2.2`のようにバージョンを固定しておく（実運用する場合は定期的に書き換えてバージョンアップ）。
4. DB、Redis、Mastodon各サービスのDockerイメージを取得する。  

    ```
    docker-compose pull
    ```
5. `db`セクションの`volumes`以下に次の行を追加する。既存の`healthcheck`項目はコメントアウトする。`YOUR_PASSWD`は任意のパスワードに変更すること。また、インデントを`volumes`と`healthcheck`をそろえるようにすること。

    ```yml:docker-compose.yml
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "mastodon", "-D", "mastodon_production"]
    environment:
      POSTGRES_USER: mastodon
      POSTGRES_DB: mastodon_production
      POSTGRES_PASSWORD: YOUR_PASSWORD
    ```

## .env.production の編集

1. `LOCAL_DOMAIN=mstdn.example.com`などの適当な値に変更する。
2. `REDIS_HOST=redis`に変更する。
3. `DB_HOST`と`DB_PASS`の値を`docker-compose.yml`に合わせる。

    ```.env:.env.production
    DB_HOST=db
    DB_PASS=YOUR_PASSWORD
    ```
4. 全文検索エンジンをOFFにする。`ES_ENABLED=false`
5. セッション用と二要素認証用の2つのシークレット（文字列）を生成する。 標準出力にランダム文字列が吐き出されるのでコピーして各変数の値として張り付ける。
   2つのコマンドは同じもので、出力だけが毎回異なる。

    ```bash:シークレットの生成
    # SECRET_KEY_BASE 用
    docker run --rm tootsuite/mastodon:v3.2.2 bundle exec rake secret

    # OTP_SECRET 用
    docker run --rm tootsuite/mastodon:v3.2.2 bundle exec rake secret
    ```
6. Web Pushの公開鍵・秘密鍵を生成する。標準出力に.envの形式で吐き出されるのでコピーする。

    ```bash:公開鍵・秘密鍵の生成
    docker run --rm --env-file ./.env.production tootsuite/mastodon:v3.2.2 bundle exec rake mastodon:webpush:generate_vapid_key

    # 出力例
    VAPID_PRIVATE_KEY=MxV1BSLJIAI2d4rJDGAOev-f18VpUrneQn0zCT_AEAI=
    VAPID_PUBLIC_KEY=BEbArD8WnodlZRpq0jCW_FWuz8gPXMnSmK2U5FjBEuLU4pLMcm-BBM-L8W0qGQIcvIU9ZsNrHOVSkPbAmVHqRCk=
    ```
7. メールアドレス検証・通知などに使うメールサーバ（SMTPサーバ）を設定する。 
   今回は自分のGoogleアカウントを使用する。 Googleアカウントの二段階認証が有効になっていることを確認し、 Googleアカウント設定からメールに使用するアプリパスワードを生成しておく。

    ```.env:.env.production
    SMTP_SERVER=smtp.gmail.com
    SMTP_PORT=587
    SMTP_LOGIN=YOUR_NAME@gmail.com
    SMTP_PASSWORD=YOUR_APP_PASSWORD
    SMTP_FROM_ADDRESS=YOUR_NAME@gmail.com
    ```
8. オブジェクトストレージ接続機能はひとまず無効化しておく。`S3_ENABLED=false`

## コマンド実行
### DBの初期化と静的ファイル生成
```bash:初期化
docker-compose run --rm web rails db:migrate
docker-compose run --rm web rails assets:precompile

# いったん終了
docker-compose down   

# 永続化指定して起動
docker-compose up -d  
```

`db:migrate`でエラーが出て失敗するときは、一度`docker-compose pull`コマンドを実行してから`db:migrate`しなおすとうまくいくことがある。
### アカウントの作成

以下のコマンドで管理者アカウントを登録する。
この例では`hoge`ユーザを管理者として作成し、ログインメールアドレスは`hoge@example.com`、パスワードはこのコマンドの出力結果となる。

```bash:アカウントの作成
docker-compose run --rm web bundle exec bin/tootctl accounts create hoge --email hoge@example.com --confirmed --role admin
```
### ローカルのインスタンス（Mastodonサーバ）にアクセスできるようにする

このままではhttpsの暗号化設定ができておらず、しかもデフォルトで`http`でのアクセスは`https`にリダイレクトされてしまい、アクセスしてもエラー画面が表示されログインできない。
そこで`ngrok`コマンドを使う。Windows10の場合は[ここ](https://ngrok.com/download)からダウンロードする。
以下のコマンドを実行し、起動しているローカルのMastodonへのURLを表示させる。このURLはngrokを停止するまで有効で、ngrokを起動しなおしたらURLが変わるようだ。

```bash:ngrokの実行
# 今dockerで起動しているMastodonの待ち受けポートが3000なので「http 3000」とする
ngrok http 3000   
```

ngrokが表示している`https://`で始まるURLにアクセスするとローカルのDockerで立てたMastodonにログインできる。__ただし、ログイン後数分はサーバとの通信が多すぎて429エラーが出てしまい、投稿に失敗する。__（ngrokによる制限？）
初投稿はログイン後数分経ってからでないとできなかった。

## 参考

[Mastodonをdocker-composeで立てる（Ubuntu 18.04） - えやみぐさ](https://blog.aoirint.com/entry/2020/mastodon_docker/)