Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

概要

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
sakura_internet
さくらレンタルサーバ、さくらのVPS、 さくらのクラウド、さくらの専用サーバなどのインターネットサービス・ITプラットフォームを提供しています。
https://www.sakura.ad.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away