anorithのブログ

主にGIS系の記事を書く。

WSL2のDockerでmastodonを起動してみる(HTTP)

概要

  • WSL上でDockerを使用してmastodonを起動
  • インターネットには公開しないローカルでのお試し用。
  • localhostへのアクセスとし、http通信のみで行う(SSLの設定はしない)。

手順

ソースコードのDL

作業用に適当なディレクトリを作成して作業します。

まずはGitHubからソースのダウンロードを行います。 この時点の最新の安定版である「stable-4.1」を使用します。

wget https://github.com/mastodon/mastodon/archive/refs/heads/stable-4.1.zip
unzip stable-4.1.zip
cd mastodon-stable-4.1

リポジトリごとDLしていますが、実際に使用するのは「.env.production.sample」ファイルと「docker-compose.yml」くらいです。

docker-compose.ymlの編集

dbの環境変数を「POSTGRES_USER: mastodon」「POSTGRES_DB: mastodon」「POSTGRES_PASSWORD: password」としてユーザーを設定します(ついでに「POSTGRES_HOST_AUTH_METHOD」も書き方を統一&「healthcheck」もちょっと修正)。

  db:
    restart: always
    image: postgres:14-alpine
    shm_size: 256mb
    networks:
      - internal_network
    healthcheck:
      # test: ['CMD', 'pg_isready', '-U', 'postgres']
      test: ['CMD', 'pg_isready', '-U', 'mastodon']
    volumes:
      - ./postgres14:/var/lib/postgresql/data
    environment:
      POSTGRES_HOST_AUTH_METHOD: trust
      POSTGRES_USER: mastodon
      POSTGRES_DB: mastodon
      POSTGRES_PASSWORD: password

HTTP通信をするためにコンテナ内部の設定ファイルを変更したいので「web」の実行時のコマンドに以下の内容を追加します。

sed 's/config.force_ssl = true/config.force_ssl = false/' /opt/mastodon/config/environments/production.rb > /opt/mastodon/config/environments/production.rb

また、環境変数にもHTTP通信用の設定を追加します。

    environment:
      HTTPS_LOCAL: 'false'

また、Dockerイメージのビルドを省略するために「build .」をコメントアウトします。「web」「streaming」「sidekiq」の3か所あります。

最終的に以下のようなdocker-composeファイルになります。

docker-compose.yml

version: '3'
services:
  db:
    restart: always
    image: postgres:14-alpine
    shm_size: 256mb
    networks:
      - internal_network
    healthcheck:
      # test: ['CMD', 'pg_isready', '-U', 'postgres']
      test: ['CMD', 'pg_isready', '-U', 'mastodon']
    volumes:
      - ./postgres14:/var/lib/postgresql/data
    environment:
      POSTGRES_HOST_AUTH_METHOD: trust
      POSTGRES_USER: mastodon
      POSTGRES_DB: mastodon
      POSTGRES_PASSWORD: password
  redis:
    restart: always
    image: redis:7-alpine
    networks:
      - internal_network
    healthcheck:
      test: ['CMD', 'redis-cli', 'ping']
    volumes:
      - ./redis:/data

  # es:
  #   restart: always
  #   image: docker.elastic.co/elasticsearch/elasticsearch:7.17.4
  #   environment:
  #     - "ES_JAVA_OPTS=-Xms512m -Xmx512m -Des.enforce.bootstrap.checks=true"
  #     - "xpack.license.self_generated.type=basic"
  #     - "xpack.security.enabled=false"
  #     - "xpack.watcher.enabled=false"
  #     - "xpack.graph.enabled=false"
  #     - "xpack.ml.enabled=false"
  #     - "bootstrap.memory_lock=true"
  #     - "cluster.name=es-mastodon"
  #     - "discovery.type=single-node"
  #     - "thread_pool.write.queue_size=1000"
  #   networks:
  #      - external_network
  #      - internal_network
  #   healthcheck:
  #      test: ["CMD-SHELL", "curl --silent --fail localhost:9200/_cluster/health || exit 1"]
  #   volumes:
  #      - ./elasticsearch:/usr/share/elasticsearch/data
  #   ulimits:
  #     memlock:
  #       soft: -1
  #       hard: -1
  #     nofile:
  #       soft: 65536
  #       hard: 65536
  #   ports:
  #     - '127.0.0.1:9200:9200'

  web:
    # build: .
    image: ghcr.io/mastodon/mastodon:v4.1.6
    restart: always
    env_file: .env.production
    command: bash -c "rm -f /mastodon/tmp/pids/server.pid; sed 's/config.force_ssl = true/config.force_ssl = false/' /opt/mastodon/config/environments/production.rb > /opt/mastodon/config/environments/production.rb; bundle exec rails s -p 3000"
    networks:
      - external_network
      - internal_network
    healthcheck:
      # prettier-ignore
      test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:3000/health || exit 1']
    ports:
      - '127.0.0.1:3000:3000'
    depends_on:
      - db
      - redis
      # - es
    volumes:
      - ./public/system:/mastodon/public/system
    environment:
      HTTPS_LOCAL: 'false'

  streaming:
    # build: .
    image: ghcr.io/mastodon/mastodon:v4.1.6
    restart: always
    env_file: .env.production
    command: node ./streaming
    networks:
      - external_network
      - internal_network
    healthcheck:
      # prettier-ignore
      test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:4000/api/v1/streaming/health || exit 1']
    ports:
      - '127.0.0.1:4000:4000'
    depends_on:
      - db
      - redis

  sidekiq:
    # build: .
    image: ghcr.io/mastodon/mastodon:v4.1.6
    restart: always
    env_file: .env.production
    command: bundle exec sidekiq
    depends_on:
      - db
      - redis
    networks:
      - external_network
      - internal_network
    volumes:
      - ./public/system:/mastodon/public/system
    healthcheck:
      test: ['CMD-SHELL', "ps aux | grep '[s]idekiq\ 6' || false"]

  ## 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:
  #   image: sirboops/tor
  #   networks:
  #      - external_network
  #      - internal_network
  #
  # privoxy:
  #   image: sirboops/privoxy
  #   volumes:
  #     - ./priv-config:/opt/config
  #   networks:
  #     - external_network
  #     - internal_network

networks:
  external_network:
  internal_network:
    internal: true

.env.productionの作成、設定

「.env.production.sample」をコピーして「.env.production」を作成します。

cp .env.production.sample .env.production

このファイルの設定に鍵の生成が必要なのですが、今回は公式とは別のlinuxserverが作成しているコンテナを使用します(生成さえできれば手段はなんでもよいので)。

「SECRET_KEY_BASE」「OTP_SECRET」に設定する値を生成するために以下のDockerイメージとコマンドを使用します。2回実行し表示された値をそれぞれ「SECRET_KEY_BASE」「OTP_SECRET」に設定します。

docker run --rm -it --entrypoint /bin/bash lscr.io/linuxserver/mastodon generate-secret

「VAPID_PRIVATE_KEY」「VAPID_PUBLIC_KEY」に設定する値を生成するために以下のコマンドを使用します。こちらはそのままコピペできる形で出力されます。

docker run --rm -it --entrypoint /bin/bash lscr.io/linuxserver/mastodon generate-vapid

その他以下のように設定します。

LOCAL_DOMAIN=localhost
REDIS_HOST=redis

DB_HOST=db
DB_USER=mastodon
DB_NAME=mastodon
DB_PASS=password

ES_ENABLED=false

S3_ENABLED=false

最終的には以下のようなファイルになります。

.env.production

# This is a sample configuration file. You can generate your configuration
# with the `rake mastodon:setup` interactive setup wizard, but to customize
# your setup even further, you'll need to edit it manually. This sample does
# not demonstrate all available configuration options. Please look at
# https://docs.joinmastodon.org/admin/config/ for the full documentation.

# Note that this file accepts slightly different syntax depending on whether
# you are using `docker-compose` or not. In particular, if you use
# `docker-compose`, the value of each declared variable will be taken verbatim,
# including surrounding quotes.
# See: https://github.com/mastodon/mastodon/issues/16895

# Federation
# ----------
# This identifies your server and cannot be changed safely later
# ----------
LOCAL_DOMAIN=localhost

# Redis
# -----
REDIS_HOST=redis
REDIS_PORT=6379

# PostgreSQL
# ----------
DB_HOST=db
DB_USER=mastodon
DB_NAME=mastodon
DB_PASS=password
DB_PORT=5432

# Elasticsearch (optional)
# ------------------------
ES_ENABLED=false
ES_HOST=localhost
ES_PORT=9200
# Authentication for ES (optional)
ES_USER=elastic
ES_PASS=password

# Secrets
# -------
# Make sure to use `rake secret` to generate secrets
# -------
SECRET_KEY_BASE=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
OTP_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

# Web Push
# --------
# Generate with `rake mastodon:webpush:generate_vapid_key`
# --------
VAPID_PRIVATE_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
VAPID_PUBLIC_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

# Sending mail
# ------------
SMTP_SERVER=
SMTP_PORT=587
SMTP_LOGIN=
SMTP_PASSWORD=
SMTP_FROM_ADDRESS=notifications@example.com

# File storage (optional)
# -----------------------
S3_ENABLED=false
S3_BUCKET=files.example.com
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
S3_ALIAS_HOST=files.example.com

# IP and session retention
# -----------------------
# Make sure to modify the scheduling of ip_cleanup_scheduler in config/sidekiq.yml
# to be less than daily if you lower IP_RETENTION_PERIOD below two days (172800).
# -----------------------
IP_RETENTION_PERIOD=31556952
SESSION_RETENTION_PERIOD=31556952

DBの設定とアセットのコンパイル

以下のコマンドでDBのマイグレーションを行います。大量のログが出力されるので少し待ちます。

docker-compose run --rm web rails db:migrate

次にアセットのコンパイルを行います(作成済みのDockerイメージを使用する場合は不要という情報もありましたが念のため・・・)。

docker-compose run --rm web rails assets:precompile

コンテナの起動

以下コマンドでコンテナを起動します。

docker-compose  up -d

以下のようなログが出ます。

mastodon-stable-41_db_1 is up-to-date
mastodon-stable-41_redis_1 is up-to-date
Creating mastodon-stable-41_web_1       ... done
Creating mastodon-stable-41_streaming_1 ... done
Creating mastodon-stable-41_sidekiq_1   ... done

「docker ps」でコンテナを確認すると以下のようになっています(直後なのでまだhealth: startingですが・・・)。

c7f09f791613   ghcr.io/mastodon/mastodon:v4.1.6   "/usr/bin/tini -- no…"   24 seconds ago       Up 21 seconds (health: starting)   3000/tcp, 127.0.0.1:4000->4000/tcp   mastodon-stable-41_streaming_1
abfb7420b861   ghcr.io/mastodon/mastodon:v4.1.6   "/usr/bin/tini -- bu…"   24 seconds ago       Up 20 seconds (health: starting)   3000/tcp, 4000/tcp                   mastodon-stable-41_sidekiq_1
911368ee133a   ghcr.io/mastodon/mastodon:v4.1.6   "/usr/bin/tini -- ba…"   24 seconds ago       Up 20 seconds (health: starting)   127.0.0.1:3000->3000/tcp, 4000/tcp   mastodon-stable-41_web_1
ee657ada8db7   postgres:14-alpine                 "docker-entrypoint.s…"   About a minute ago   Up About a minute (healthy)                                             mastodon-stable-41_db_1
d982b142e1a4   redis:7-alpine                     "docker-entrypoint.s…"   About a minute ago   Up About a minute (healthy)                                             mastodon-stable-41_redis_1

ここで「http://localhost:3000/」にアクセスするとmastodonの画面が表示されます。

※普通に表示されることもありますが、chromeの設定やキャッシュによってHTTPSにリダイレクトされ「ERR_SSL_PROTOCOL_ERROR」が出ることもあります。その場合はシークレットモードだとアクセスできます。

ユーザーの作成とログイン

このままだとログインできないのでユーザーを作成します。メールサーバーを設定しておらず通常のようにユーザーの新規作成ができないのでコンテナに入って無理やり作成します。

以下のコマンドでコンテナに入ります。

docker exec -it mastodon-stable-41_web_1 /bin/bash

コンテナ内で以下のコマンドでユーザーを作成します。「confirmed 」はメール認証を省略するためのオプションです。

bundle exec bin/tootctl accounts create admin_user --email admin@localhost --confirmed --role Admin

※メアドは適当です。example.comだとはじかれたのでlocalhostにしています。ついでにAdmin権限を与えていますが、あまり意味はないです。

パスワードが表示されるので上のメアドと表示されたパスワードを使用してログインします。

ログインすると以下のような画面になります。

投稿もできます。

ただしアイコン画像などはリンクがhttpsで設定されているためか表示されません。 httpで確認できるのはこの程度っぽいですね。

その他コメント

特にHTTPS通信を回避するところでめちゃくちゃ詰まりました。最初はオレオレ証明書でやろうとしたりもしてましたが、ごちゃごちゃしてきたので一旦http通信で起動する方針にしました。最終的には比較的するっといけましたが、途中無駄にDockerのネットワークの仕様など調べて疲れました・・・。https版の設定もできたら記事にしようと思います。

参考