1.nginx-proxy + letsencrypt-nginx-proxy-companion
すでに同じサーバー上で他のアプリを動かしていたので、nginx-proxyを使った。ついでにletsencrypt-nginx-proxy-companionも使い、https化も自動化した。まずこの2つでdocker-compose.ymlを書いておく。
nginx-proxyはデフォルトであるサイズ(1MB?)以上のファイルのアップロードを受け付けない。これを超えるサイズの動画の投稿などを可能にしたいので自前のカスタム設定用のファイルを作り、マウントしている。
dockerネットワークを作る
dockerのコンテナ間の通信はdocker networkで行う。
- common_linkはmastodonを動かすnginxサーバーとnginx-proxyの通信を行う
- back-mastodonはmastodonを構成する各コンテナ間での通信を行う
$ docker network create --driver bridge common_link
$ docker network create --driver bridge back-mastodon
なおdocker networkの管理に有用なコマンドを書いておく
# ネットワークの一覧を表示する
$ docker network ls
# ネットワークの詳細を表示する
$ docker network inspect <network名>
# 使用されていないネットワークを削除する
$ docker network prune
動作確認(必要なら)
mastodon以外にすでにdockerで動かしているアプリがある場合、ネットワークの設定を修正する。私はwordpressを動かしていたのでその例を示す。変更点は2つ。
- nginx-proxyと通信するコンテナには環境変数としてVIRTUAL_HOST, LETSENCRYPT_HOST, LETSENCRYPT_EMAILを与える。
- VIRTUAL_HOSTにはサブドメイン名(ここでは違うが)を設定する。のちのちmastodonにはanimedon.chao.tokyoというサブドメイン名を設定するので、chao.tokyoとanimedon.chao.tokyoのどちらにアクセスされたかによって違うコンテナを呼び出せるようになる。なおサブドメイン名はお名前ドットコムで設定した。
- LETSENCRYPT_HOSTとLETSENCRYPT_EMAILはletsencrypt-nginx-proxy-companionのための環境変数。前者にはVIRTUAL_HOSTと同じ値を、後者にはletsencryptの通知メールを受け取るメールアドレスを設定する。
- 先ほど設定したネットワークを使用する
- トップレベルにnetworksを作り、先ほど作ったcommon_linkというネットワークを利用することを明示する
- 各コンテナでcommon_linkを利用することを明示する
version: "2"
services:
wordpress:
image: wordpress:latest
container_name: "wp-main"
volumes:
- .:/var/www/html
- ./log:/tmp/log
depends_on:
- db
environment:
WORDPRESS_DB_HOST: "db:3306"
VIRTUAL_HOST: chao.tokyo
LETSENCRYPT_HOST: chao.tokyo
LETSENCRYPT_EMAIL: 見せられないよ
env_file: .env
networks:
- common_link
db:
image: mysql:5.7
container_name: "wp-db"
volumes:
- "./db-data:/var/lib/mysql"
env_file: .env
networks:
- common_link
networks:
common_link:
external: true
nginx-proxyのdocker-composeとアプリのdocker-composeを任意の順序で起動すると、アプリがアクセス可能になるはずだ。この段階でアプリ(例:chao.tokyo)にアクセスできない場合はどこかでエラーが出ているので頑張ってなんとかする。letsencrypt-nginx-proxy-companionは起動に時間がかかるし、初回起動時は特に長い。証明書の取得、あるいはその必要がないことの確認が済むと3600秒のスリープに入るというようなメッセージが出るので、それまではエラーが出ても焦らないで。
2.Mastodonの設定
ではMastodonをデプロイしていく。まず適当な作業ディレクトリにcloneする。
git clone https://github.com/tootsuite/mastodon.git
docker-compose.ymlの編集
公式のインストラクションによると
If you're not making any local code changes or customizations on your instance, you can use a prebuilt Docker image to avoid the time and resource consumption of a build
もしローカルでコードを変更しないのであれば、ビルド済みのDockerイメージを利用することで時間と資源を節約することができます。
とのことなので、そうすることにした。この場合docker-compose.ymlに若干の変更が必要になる。他にもいろいろな変更が必要になるがとりあえず載せる。
version: '2'
services:
nginx:
image: nginx:1.11.10-alpine
container_name: mstdn-nginx
expose:
- "9090"
restart: always
tty: false
env_file: .env.production
links:
- web
- streaming
volumes:
- ./setting/nginx/conf.d:/etc/nginx/conf.d:ro
- ./setting/nginx/conf:/etc/nginx/conf/:ro
volumes_from:
- container:nginx-proxy_nginx-proxy_1
networks:
- common_link
- back-mastodon
db:
restart: always
image: postgres:9.6-alpine
networks:
- back-mastodon
### Uncomment to enable DB persistance
volumes:
- ./postgres:/var/lib/postgresql/data
redis:
restart: always
image: redis:4.0-alpine
networks:
- back-mastodon
### Uncomment to enable REDIS persistance
volumes:
- ./redis:/data
# es:
# restart: always
# image: docker.elastic.co/elasticsearch/elasticsearch-oss:6.1.3
# environment:
# - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
# networks:
# - back-mastodon
#### Uncomment to enable ES persistance
## volumes:
## - ./elasticsearch:/usr/share/elasticsearch/data
web:
# build: .
image: tootsuite/mastodon:v2.4.3
restart: always
env_file: .env.production
command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000 -b '0.0.0.0'"
networks:
- back-mastodon
ports:
- "127.0.0.1:3000:3000"
depends_on:
- db
- redis
# - es
volumes:
- ./public/system:/mastodon/public/system
- ./public/assets:/mastodon/public/assets
- ./public/packs:/mastodon/public/packs
streaming:
# build: .
image: tootsuite/mastodon:v2.4.3
restart: always
env_file: .env.production
command: yarn start
networks:
- back-mastodon
ports:
- "127.0.0.1:4000:4000"
depends_on:
- db
- redis
sidekiq:
# build: .
image: tootsuite/mastodon:v2.4.3
restart: always
env_file: .env.production
command: bundle exec sidekiq -q default -q mailers -q pull -q push
depends_on:
- db
- redis
networks:
- back-mastodon
volumes:
- ./public/system:/mastodon/public/system
- ./public/packs:/mastodon/public/packs
## Uncomment to enable federation with tor instances along with adding the following ENV variables
## http_proxy=http://privoxy:8118
## ALLOW_ACCESS_TO_HIDDEN_SERVICE=true
# tor:
# build: https://github.com/usbsnowcrash/docker-tor.git
# networks:
# - external_network
# - back-mastodon
#
# privoxy:
# build: https://github.com/usbsnowcrash/docker-privoxy.git
# command: /opt/sbin/privoxy --no-daemon --user privoxy.privoxy /opt/config
# volumes:
# - ./priv-config:/opt/config
# networks:
# - external_network
# - back-mastodon
networks:
common_link:
external: true
back-mastodon:
external: true
変更点を1つずつ説明する。
nginxコンテナの追加
mastodon専用のサーバーのコンテナ。nginx-proxyと各コンテナを中継する。volumesでコンテナの外から設定ファイルを編集できるようにしている。volumes_fromに関する解説はここを参照のこと。networksでcommon_linkと先ほど使用したmastodonの内部用ネットワークの両方に接続する。
なおvolumes_fromはdocker-compose version 3では使えない。解決策を調べたがよくわからなかったのでversionを2にした。
dbコンテナ, redisコンテナ
データベースの永続化のためにvolumesをコメントアウトした。先ほど使用したmastodon内部用ネットワークを利用するためにネットワーク名を変えた。
webコンテナ
ローカルで変更を加えないことにしたのでbuildをコメントアウト。imageでバージョンを指定。サーバー外部との通信はnginxコンテナが一括して担うのでnetworksはback-mastodonのみでよい。
volumesコンテナにアセットが保存されるディレクトリを追加。ここはエラーメッセージを頼りに手探りでやったことなのでよく理解できていないのだが、ビルドをしない場合はこうしないと動かないっぽい(参考)?。
streamingコンテナ
buildをコメントアウト。networksをback-mastodonに。
sidekiqコンテナ
これも手探りでやったのでよくわからないが、volumesに/public/packsを追加した。もしかしたら要らないかも。
networks
先ほど作ったcommon_linkとback-mastodonを利用することを明示する。
mastodon用nginxの設定ファイルの編集
mastodon/settings/nginx/conf.d/default.confを編集する。参考をコピペしてドメイン名等を埋めていけばいいが、add_header Content-Security-Policyの行はそのままだと画像アップロードができないので、意味がわかる人なら画像アップロードを許可するようにここを編集する。僕はわからなかったので丸ごと消した。
.env.productionの編集
まずcp .env.production.sample .env.production
し、このファイルを編集していく。
# 冒頭に追加
VIRTUAL_HOST=animedon.chao.tokyo
VIRTUAL_PORT=9090
VIRTUAL_PROTO=https
LETSENCRYPT_HOST=animedon.chao.tokyo
LETSENCRYPT_EMAIL=見せられないよ
LETSENCRYPT_TEST=false
# 探して編集
LOCAL_DOMAIN=animedon.chao.tokyo
# それぞれdocker-compose run --rm web rake secretを実行し出力された文字列を入れる
SECRET_KEY_BASE=
OTP_SECRET=
# 探して編集
SMTP_SERVER=smtp.gmail.com
SMTP_PORT=587
SMTP_LOGIN=見せられないよ
SMTP_PASSWORD=見せられないよ
SMTP_FROM_ADDRESS=見せられないよ
SMTP_DOMAIN=gmail.com
SMTP_OPENSSL_VERIFY_MODE=none
冒頭はnginx-proxyとmastodon用nginxが通信するための環境変数。
メールはgmailを利用するのでこうなった。なおgmail側で事前に設定してmastodon用のアプリパスワードを発行するのが望ましい。
起動
docker-compose build
chown -R 991:991 public
docker-compose run --rm web bundle exec rake mastodon:setup
chownは以外なタイミングでトラブった記憶があるので(忘れた)、それっぽいエラーが出たら思い出したかのようにもう一度実行しよう。
最後のコマンドで対話型のセットアップが始まる。内容はここにある。
- ドメイン名→animedon.chao.tokyo
- シングルユーザー?→No
- Docker?→Yes
- DB設定→Enter連打
- Redis設定→Enter連打
- クラウドストレージ→No
- メール設定→NoとEnter連打。さっき設定したのでたぶん上書きはされてない。
- DBマイグレーション→永続化してあるので既にやってあるならスキップしないとエラーになる
- アセットのプリコンパイル→同上。ただしこれはやり直してもよい。とても時間がかかる。
- 管理者アカウント作成→しましょう
docker-compose up -d
起動します。
終わりに
参考にしたサイトはどれも素晴らしかったが、mastodonの進化が非常に早いのでそのままでは動かないところがいくつもあった。基本的な構築の流れは参考サイトを見てもらったほうがよくて、私のこの記事はどこにどういうエラーが起こりうるのか、それをどう考えて対処したのかというような記録として残しておきたいと思う。
参考