Docker応用チュートリアル:Mastodon

  • 21
    いいね
  • 0
    コメント

概要

Docker および Docker Compose を使い、Mastodon および関連サービス(Nginx)、SSL 証明書(certbot + Let's Encrypt)動作環境をセットアップします。LinuxやDockerに慣れている方であれば、所要時間は10分程度です。

作成するサービス(コンテナ)、ボリューム、ネットワークの関係は、下図の通りです。

docker-compose-mastdon-stack.png

前提知識

Docker Compose の基本操作(応用チュートリアル:WordPress)の理解が望ましいです(必須ではありません)。

6/28(水)ハンズオン用の補足情報

  • 希望者に「 任意の名称.sakuradon.jp 」の DNS 設定を発行します(当日のみ)
    • サーバの IP アドレスを講師までお知らせください

環境構築(CentOS 7.3)

Docker のセットアップ

# curl -sSL https://get.docker.com/ | sh
# systemctl enable docker
# systemctl start docker

Docker Compose のセットアップ

# curl -L https://github.com/docker/compose/releases/download/1.14.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
# chmod +x /usr/local/bin/docker-compose

チュートリアル内容について

GitHub の Mastodon リポジトリで docker-compose.yml が提供されています。しかし、こちらは Mastodon 単体であり、Nginx フロントエンドやメールサーバ等の設定は含まれていません。また最新版(latest)ではイメージをビルドできなかったり、Docker Hub上のlatestタグのイメージに不具合があったりします。

そのため、公式ドキュメントの手順に準じながら、一通り Mastodon を動かすために必要なサービスを、Docker を通して管理できるようにします。

本チュートリアル(ハンズオン)では、Docker Hub 上から最新安定版(今日現在v1.4.6)のDockerイメージを取得し、実行します。

1. 作業用アカウントの作成

root 権限で mastodon アカウントを作成します。また、このアカウントは docker グループにも所属します(docker グループに所属しているユーザは root 権限としてコンテナを実行可能です。つまり、サーバ上で事実上の root 権限を持っているのと同じ状態のため、セキュリティ上の取り扱いにご注意ください)。

# /usr/sbin/groupadd -g 991 mastodon
# /usr/sbin/adduser -g mastodon -u 991 mastodon
# usermod -aG docker mastodon

ユーザを作成した mastodon 切り替えます。

# su - mastodon

それから docker version コマンドを実行し、バージョン情報を確認します。「Server:」 のバージョン情報が表示されていれば正常です。表示されない場合は Docker Engine が起動しているかどうかや、mastodon アカウントが docker グループに所属しているかどうか、確認します。

$ docker version
Client:
 Version:      17.05.0-ce
 API version:  1.29
 Go version:   go1.7.5
 Git commit:   89658be
 Built:        Thu May  4 22:06:25 2017
 OS/Arch:      linux/amd64

Server:
 Version:      17.05.0-ce
 API version:  1.29 (minimum version 1.12)
 Go version:   go1.7.5
 Git commit:   89658be
 Built:        Thu May  4 22:06:25 2017
 OS/Arch:      linux/amd64
 Experimental: false

2. Let's Encrypt 証明書の作成

Mastodon のフロントエンドには SSL 通信に対応した Nginx を設定します。そこで使うための SSL 証明書を作成します。作成には certbot と呼ばれるツールを作成します。

ここでは certbot プロジェクトの公式 Docker イメージを使います。また certbot という名称の Docker ボリュームを作成し、そのボリューム内の /etc/letsencrypt ディレクトリ内に証明書を保存します。

まずはじめに証明書を作成するためのテスト(ドライ・ラン)を実行します。次のコマンドの実行にあたり、 <ホスト名> には Mastdon にアクセスする URL で使いたいホスト名(例:social.example.jp)を、<メールアドレス> には Let's Encrypt の通知用に使う自分のメールアドレスを入力します。

$ docker container run -it --rm -v certbot:/etc/letsencrypt \
    -v /var/log/letsencrypt:/var/log/letsencrypt \
    -p 443:443 \
    certbot/certbot \
     certonly --standalone --agree-tos --dry-run -n \
    -d <ホスト名> --email <メールアドレス>

実行後、次のように The dry run was successful. (ドライ・ランの成功)と表示されれば正常です。

IMPORTANT NOTES:
 - The dry run was successful.
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.

つぎは、先ほどのコマンドから ---dry-run を削除して実行します。

$ docker container run -it --rm -v certbot:/etc/letsencrypt \
    -v /var/log/letsencrypt:/var/log/letsencrypt \
    -p 443:443 \
    certbot/certbot \
     certonly --standalone --agree-tos -n \
    -d <ホスト名> --email <メールアドレス>

実行すると、次のようにメールアドレスを EFF で共有するかどうか訊ねてくる場合があります。その場合は Yes または No を入力します。

-------------------------------------------------------------------------------
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about EFF and
our work to encrypt the web, protect its users and defend digital rights.
-------------------------------------------------------------------------------
(Y)es/(N)o:

最終的に、次のように表示されていれば、作成完了です。

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/social.zem.jp/fullchain.pem. Your cert will
   expire on 2017-08-21. To obtain a new or tweaked version of this
   certificate in the future, simply run certbot again. To
   non-interactively renew *all* of your certificates, run "certbot
   renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

これでボリューム certbot の中に証明書が格納されました。

docker volume ls コマンドで確認しましょう。

$ docker volume ls
DRIVER              VOLUME NAME
local               certbot

また、次のコマンドを実行することで、証明書関連ファイルを確認できます。

実行例
$ docker run -it -v certbot:/cert/  --rm  alpine ls -al /cert/archive/ここにホスト名/
total 24
drwxr-xr-x    2 root     root          4096 Jun 28 01:30 .
drwx------    3 root     root          4096 Jun 28 01:30 ..
-rw-r--r--    1 root     root          1805 Jun 28 01:30 cert1.pem
-rw-r--r--    1 root     root          1647 Jun 28 01:30 chain1.pem
-rw-r--r--    1 root     root          3452 Jun 28 01:30 fullchain1.pem
-rw-r--r--    1 root     root          1708 Jun 28 01:30 privkey1.pem

3. SSL 用設定ファイルの作成

SSL通信で使う鍵交換用パラメータ・ファイルを作成するために、openssl コマンドを実行可能なイメージを作成します。

$ cd
$ git clone https://github.com/zembutsu/mastodon-docker.git
$ cd ~/mastodon-docker/myopenssl
$ docker image build -t myopenssl - < ./Dockerfile

次に、鍵交換用パラメータ・ファイルを作成します。コマンドの実行後、1~2分ほど待ちます。

$ docker container run -it --rm -v certbot:/certbot myopenssl openssl dhparam -out  /certbot/dhparam.pem 2048

4. Mastodon GitHub リポジトリの取得と設定ファイルの設置

GitHub リポジトリから、Mastodon 関連ファイルを取得します。

$ cd
$ git clone https://github.com/tootsuite/mastodon.git live
$ cd live

それから、設定ファイルを複製、または Docker 関連設定ファイルを上書きします。

$ cp .env.production.sample .env.production
$ cp ~/mastodon-docker/docker-compose.yml .
$ cp ~/mastodon-docker/Dockerfile .
$ cp -r ~/mastodon-docker/frontend .
$ cp ~/mastodon-docker/.env.smtp .

次に、設定ファイルを開きます。

$ vi .env.production

ファイルを開き、15行目付近の LOCAL_DOMAIN を編集し、今回使う「ホスト名」にします。これは Mastodon のアクセスに使うための URL です。また、50行目付近のメールサーバ設定も次のように書き換えます。

.env.production
# Federation
LOCAL_DOMAIN=<ホスト名 mastodon.example.jp など>
LOCAL_HTTPS=true
(省略)
SMTP_SERVER=mta
SMTP_PORT=25
SMTP_LOGIN=
SMTP_PASSWORD=
SMTP_FROM_ADDRESS=who@example.com ←※要編集(メールの From: アドレスです)
SMTP_DOMAIN=example.com ←※要編集(メールサーバ自身のホスト名、ここでは Mastodon を動かすホスト名を指定)

なお、この .env ファイルでは、 # (コメント)の位置に注意が必要です。値の後に # を使うと、 # 込みの値として処理されますので、値の後には書かないようにします。

望ましい書き方
# 作業用アドレスを使用
SMTP_FROM_ADDRESS=hoe@example.com
誤った書き方
SMTP_FROM_ADDRESS=hoe@example.com # 作業用アドレスを使用

次に、メールサーバ用(exim4)設定ファイルを編集します。

$ vi .env.smtp

ファイル内容を編集します。

.env.smtp
MAILNAME=example.com    ←ここのホスト名を変更します
RELAY_NETWORKS=192.168.0.0/24
PORT=25

Nginx 用設定ファイルを編集します。

$ vi frontend/nginx-default.conf

ファイルを開いたら example.com の箇所を、今回使うホスト名に変更します(5箇所)。vim の場合は一括置換(ESC -> %s /example.com/自分のホスト名/g)が便利です。

5. イメージの構築と取得

関連イメージの構築と取得を行います。build には数秒、pull はファイル容量が大きいため約1分半程かかります。

$ docker-compose build
$ docker-compose pull

docker-compose pull 実行時、最後に mastodon_frontend イメージが pull できないというエラーが表示されますが、問題ありません(Docker Hub上に mastodon_frontend イメージは存在しないからです)。

6. 内部通信用ネットワーク作成

docker network create コマンドで、Mastodon 内部通信用のネットワークを作成します。これは内部での名前解決を行うためと、データのやりとりや SMTP サーバを外部のパブリックなネットワークから切り離し、安全性を高めるためです。

$ docker network create --subnet=192.168.0.0/16 mastodon

ネットワーク mastodon が作成されているか docker network ls コマンドで確認します。

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
7d9b04de513f        bridge              bridge              local
babeb8b623d2        host                host                local
949a22119e80        mastodon            bridge              local
e49989f1bbd0        none                null                local

7. シークレットの作成と設定反映

シークレット(APIで言う所のトークンに相当)を3つ必要なため、次のコマンドを3回実行します。

$ docker-compose run --rm web rake secret

実行後、文字列が表示されますので、エディタ等に控えておきます。

そして .env.production ファイルを開き、以下の行の = のあとに追加します。

.env.production
PAPERCLIP_SECRET=8979dee487...
SECRET_KEY_BASE=74a137afd0b0...
OTP_SECRET=aae3d46591fb057...

8. データベースの初期化とアセットのプリコンパイル

初期設定用のコマンドを実行します。

$ docker-compose run --rm web rails db:migrate
$ docker-compose run --rm web rails assets:precompile

これで特にエラーが出ていなければ、準備完了です。

9. Mastodon 起動と管理用設定

$ docker-compose up -d

実行後は docker-compose ps で各サービスが起動しているかどうか、確認できます。各サービス(コンテナ)の状態(State)が起動中(Up)なのを確認します。

$ docker-compose ps
      Name                    Command               State                    Ports
----------------------------------------------------------------------------------------------------
live_db_1          docker-entrypoint.sh postgres    Up      5432/tcp
live_frontend_1    nginx -g daemon off;             Up      0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp
live_mta_1         /bin/entrypoint.sh exim -b ...   Up      25/tcp
live_redis_1       docker-entrypoint.sh redis ...   Up      6379/tcp
live_sidekiq_1     bundle exec sidekiq -q def ...   Up      3000/tcp, 4000/tcp
live_streaming_1   npm run start                    Up      3000/tcp, 0.0.0.0:4000->4000/tcp
live_web_1         bundle exec rails s -p 300 ...   Up      3000/tcp, 4000/tcp

また、起動まで時間がかかるので、ログを取得し、画面のスクロールが止まるまで待ちます。

$ docker-compose logs -f

次のようなログが出れば問題ありません。

Attaching to live_web_1
web_1        | => Booting Puma
web_1        | => Rails 5.0.2 application starting in production on http://0.0.0.0:3000
web_1        | => Run `rails server -h` for more startup options
web_1        | Creating scope :cache_ids. Overwriting existing method Notification.cache_ids.
web_1        | [1] Puma starting in cluster mode...
web_1        | [1] * Version 3.8.2 (ruby 2.4.1-p111), codename: Sassy Salamander
web_1        | [1] * Min threads: 5, max threads: 5
web_1        | [1] * Environment: production
web_1        | [1] * Process workers: 2
web_1        | [1] * Preloading application
web_1        | [1] * Listening on tcp://0.0.0.0:3000
web_1        | [1] Use Ctrl-C to stop
web_1        | [1] - Worker 0 (pid: 14) booted, phase: 0
web_1        | [1] - Worker 1 (pid: 16) booted, phase: 0

ログの表示は Ctrl+C で中断できます。

あとは、ブラウザから https://<ホスト名/ にアクセスし、アカウント登録を済ませます。

アカウント登録を済ませたら、対象アカウントを管理者として設定します。

$ docker-compose run --rm web rails mastodon:make_admin USERNAME=<ここにアカウント名>

コマンド実行後の URL から、サイトに関する管理情報を編集できるようになります。

最後に cron の設定を済ませます。crontab -e を実行し、次の内容を追加します。

@daily cd /home/mastodon/live && /usr/local/bin/docker-compose run --rm web rake mastodon:daily > /dev/null
@weekly cd /home/mastodon/live && docker container run -it --rm -v certbot:/etc/letsencrypt -v /var/log/letsencrypt:/var/log/letsencrypt certbot/certbot renew  && /usr/local/bin/docker-compose restart frontend > /dev/null

以上で設定完了です。

補足:手動でメールアドレスの許可

何らかの理由によりメールが送信できない場合、次のコマンドで手動許可できます(送信先メールの本文に含まれるURLをクリックした状態にします)。

docker-compose run --rm web rake mastodon:confirm_email USER_EMAIL=<ここにメールアドレス>

後片付け

次のコマンドを実行すると、Mastodon に限らず システム上の全てのockerコンテナ・イメージ・ネットワーク・ボリューム領域を 強制破棄 します。

$ cd ~/live/
$ docker-compose down
$ docker system prune