🐳

Outline Wiki をホスティングする(Docker版)

2024/01/07に公開

以前投稿した、「Outline Wiki をホスティングする」の Docker 版になります。

成果物

今回作成した Docker Compose と 設定ファイル を最初に置いておきます。
アプリケーションのURLやバージョン、 %MINIO_ROOT_USER% などの % で囲まれた文字列は適宜修正してご利用ください。

compose.yml
compose.yml
version: "3.2"
services:

  outline:
    image: docker.getoutline.com/outlinewiki/outline:latest
    env_file: ./docker.env
    ports:
      - "3000:3000"
    volumes:
      - storage-data:/var/lib/outline/data
    depends_on:
      - postgres
      - redis
      - minio

  redis:
    image: redis
    env_file: ./docker.env
    ports:
      - "6379:6379"
    volumes:
      - ./redis.conf:/redis.conf
    command: ["redis-server", "/redis.conf"]
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 30s
      retries: 3

  postgres:
    image: postgres
    env_file: ./docker.env
    ports:
      - "5432:5432"
    volumes:
      - database-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD", "pg_isready"]
      interval: 30s
      timeout: 20s
      retries: 3
    environment:
      POSTGRES_USER: 'user'
      POSTGRES_PASSWORD: 'pass'
      POSTGRES_DB: 'outline'

  https-portal:
    image: steveltn/https-portal
    env_file: ./docker.env
    ports:
      - '80:80'
      - '443:443'
    links:
      - outline
    restart: always
    volumes:
      - https-portal-data:/var/lib/https-portal
    healthcheck:
      test: ["CMD", "service", "nginx", "status"]
      interval: 30s
      timeout: 20s
      retries: 3
    environment:
      DOMAINS: 'outline.domain -> http://outline:3000, minio.domain -> http://minio:9000, minio-console.domain -> http://minio:9001'
#      DOMAINS: 'minio.domain -> http://minio:9000, minio-console.domain -> http://minio:9001'
      STAGE: 'production'
      WEBSOCKET: 'true'
      CLIENT_MAX_BODY_SIZE: '0'


  minio:
    image: minio/minio:latest
    ports:
      - '9000:9000'
      - '9001:9001'
    environment:
      - MINIO_ROOT_USER=%MINIO_ROOT_USER%
      - MINIO_ROOT_PASSWORD=%MINIO_ROOT_PASSWORD%
    command: server /export --console-address ":9001"
    volumes:
      - ./minio/data:/export

volumes:
  https-portal-data:
  storage-data:
  database-data:
docker.env
docker.env
# –––––––––––––––– REQUIRED ––––––––––––––––

NODE_ENV=production

# Generate a hex-encoded 32-byte random key. You should use `openssl rand -hex 32`
# in your terminal to generate a random value.
SECRET_KEY=

# Generate a unique random key. The format is not important but you could still use
# `openssl rand -hex 32` in your terminal to produce this.
UTILS_SECRET=

# For production point these at your databases, in development the default
# should work out of the box.
DATABASE_URL=postgres://user:pass@postgres:5432/outline
DATABASE_URL_TEST=postgres://user:pass@postgres:5432/outline-test
DATABASE_CONNECTION_POOL_MIN=
DATABASE_CONNECTION_POOL_MAX=
# Uncomment this to disable SSL for connecting to Postgres
PGSSLMODE=disable

# For redis you can either specify an ioredis compatible url like this
REDIS_URL=redis://redis:6379
# or alternatively, if you would like to provide additional connection options,
# use a base64 encoded JSON connection option object. Refer to the ioredis documentation
# for a list of available options.
# Example: Use Redis Sentinel for high availability
# {"sentinels":[{"host":"sentinel-0","port":26379},{"host":"sentinel-1","port":26379}],"name":"mymaster"}
# REDIS_URL=ioredis://eyJzZW50aW5lbHMiOlt7Imhvc3QiOiJzZW50aW5lbC0wIiwicG9ydCI6MjYzNzl9LHsiaG9zdCI6InNlbnRpbmVsLTEiLCJwb3J0IjoyNjM3OX1dLCJuYW1lIjoibXltYXN0ZXIifQ==

# URL should point to the fully qualified, publicly accessible URL. If using a
# proxy the port in URL and PORT may be different.
URL=%OUTLINE_APP_URL%
PORT=3000

# See [documentation](docs/SERVICES.md) on running a separate collaboration
# server, for normal operation this does not need to be set.
COLLABORATION_URL=

# To support uploading of images for avatars and document attachments an
# s3-compatible storage must be provided. AWS S3 is recommended for redundancy
# however if you want to keep all file storage local an alternative such as
# minio (https://github.com/minio/minio) can be used.

# A more detailed guide on setting up S3 is available here:
# => https://wiki.generaloutline.com/share/125de1cc-9ff6-424b-8415-0d58c809a40f
#
AWS_ACCESS_KEY_ID=%MINIO_ACCESS_ID%
AWS_SECRET_ACCESS_KEY=%MINIO_ACCESS_KEY%
AWS_REGION=local
AWS_S3_ACCELERATE_URL=
AWS_S3_UPLOAD_BUCKET_URL=%MINIO_URL%
AWS_S3_UPLOAD_BUCKET_NAME=%MINIO_BUCKET_NANE%
AWS_S3_FORCE_PATH_STYLE=true
AWS_S3_ACL=private

# Specify what storage system to use. Possible value is one of "s3" or "local".
# For "local", the avatar images and document attachments will be saved on local disk. 
FILE_STORAGE=s3

# If "local" is configured for FILE_STORAGE above, then this sets the parent directory under
# which all attachments/images go. Make sure that the process has permissions to create
# this path and also to write files to it.
FILE_STORAGE_LOCAL_ROOT_DIR=/var/lib/outline/data

# Maximum allowed size for the uploaded attachment.
FILE_STORAGE_UPLOAD_MAX_SIZE=26214400

# –––––––––––––– AUTHENTICATION ––––––––––––––

# Third party signin credentials, at least ONE OF EITHER Google, Slack,
# or Microsoft is required for a working installation or you'll have no sign-in
# options.

# To configure Slack auth, you'll need to create an Application at
# => https://api.slack.com/apps
#
# When configuring the Client ID, add a redirect URL under "OAuth & Permissions":
# https://<URL>/auth/slack.callback
SLACK_CLIENT_ID=get_a_key_from_slack
SLACK_CLIENT_SECRET=get_the_secret_of_above_key

# To configure Google auth, you'll need to create an OAuth Client ID at
# => https://console.cloud.google.com/apis/credentials
#
# When configuring the Client ID, add an Authorized redirect URI:
# https://<URL>/auth/google.callback
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=

# To configure Microsoft/Azure auth, you'll need to create an OAuth Client. See
# the guide for details on setting up your Azure App:
# => https://wiki.generaloutline.com/share/dfa77e56-d4d2-4b51-8ff8-84ea6608faa4
AZURE_CLIENT_ID=
AZURE_CLIENT_SECRET=
AZURE_RESOURCE_APP_ID=

# To configure generic OIDC auth, you'll need some kind of identity provider.
# See documentation for whichever IdP you use to acquire the following info:
# Redirect URI is https://<URL>/auth/oidc.callback
OIDC_CLIENT_ID=
OIDC_CLIENT_SECRET=
OIDC_AUTH_URI=
OIDC_TOKEN_URI=
OIDC_USERINFO_URI=

# Specify which claims to derive user information from
# Supports any valid JSON path with the JWT payload
OIDC_USERNAME_CLAIM=preferred_username

# Display name for OIDC authentication
OIDC_DISPLAY_NAME=OpenID Connect

# Space separated auth scopes.
OIDC_SCOPES=openid profile email


# –––––––––––––––– OPTIONAL ––––––––––––––––

# Base64 encoded private key and certificate for HTTPS termination. This is only
# required if you do not use an external reverse proxy. See documentation:
# https://wiki.generaloutline.com/share/1c922644-40d8-41fe-98f9-df2b67239d45
SSL_KEY=
SSL_CERT=

# If using a Cloudfront/Cloudflare distribution or similar it can be set below.
# This will cause paths to javascript, stylesheets, and images to be updated to
# the hostname defined in CDN_URL. In your CDN configuration the origin server
# should be set to the same as URL.
CDN_URL=

# Auto-redirect to https in production. The default is true but you may set to
# false if you can be sure that SSL is terminated at an external loadbalancer.
FORCE_HTTPS=true

# Have the installation check for updates by sending anonymized statistics to
# the maintainers
ENABLE_UPDATES=true

# How many processes should be spawned. As a reasonable rule divide your servers
# available memory by 512 for a rough estimate
WEB_CONCURRENCY=1

# Override the maximum size of document imports, could be required if you have
# especially large Word documents with embedded imagery
MAXIMUM_IMPORT_SIZE=5120000

# You can remove this line if your reverse proxy already logs incoming http
# requests and this ends up being duplicative
DEBUG=http

# Configure lowest severity level for server logs. Should be one of
# error, warn, info, http, verbose, debug and silly
LOG_LEVEL=info

# For a complete Slack integration with search and posting to channels the
# following configs are also needed, some more details
# => https://wiki.generaloutline.com/share/be25efd1-b3ef-4450-b8e5-c4a4fc11e02a
#
SLACK_VERIFICATION_TOKEN=your_token
SLACK_APP_ID=A0XXXXXXX
SLACK_MESSAGE_ACTIONS=true

# Optionally enable google analytics to track pageviews in the knowledge base
GOOGLE_ANALYTICS_ID=

# Optionally enable Sentry (sentry.io) to track errors and performance,
# and optionally add a Sentry proxy tunnel for bypassing ad blockers in the UI:
# https://docs.sentry.io/platforms/javascript/troubleshooting/#using-the-tunnel-option)
SENTRY_DSN=
SENTRY_TUNNEL=

# To support sending outgoing transactional emails such as "document updated" or
# "you've been invited" you'll need to provide authentication for an SMTP server
SMTP_HOST=
SMTP_PORT=
SMTP_USERNAME=
SMTP_PASSWORD=
SMTP_FROM_EMAIL=hello@example.com
SMTP_REPLY_EMAIL=hello@example.com
SMTP_TLS_CIPHERS=
SMTP_SECURE=true

# The default interface language. See translate.getoutline.com for a list of
# available language codes and their rough percentage translated.
DEFAULT_LANGUAGE=en_US

# Optionally enable rate limiter at application web server
RATE_LIMITER_ENABLED=true

# Configure default throttling parameters for rate limiter
RATE_LIMITER_REQUESTS=1000
RATE_LIMITER_DURATION_WINDOW=60

# Iframely API config
# IFRAMELY_URL=
# IFRAMELY_API_KEY=

# Enable unsafe-inline in script-src CSP directive
# Setting it to true allows React dev tools add-on in
# Firefox to successfully detect the project
DEVELOPMENT_UNSAFE_INLINE_CSP=false

ここからは設定についての詳細や各種コマンドなどの実行順序について記述します。

起動手順

0. 準備

  • Dockerがインストールされたマシン
    • 私は Oracle Cloud Infrastructure の VM を使用しました
  • ドメイン
    • アプリ用
    • minio 用
    • minio コンソール用(Zero Trust Tunnel などで別途認証を設けるか、作業終了後はアクセス不可にすることをおすすめします)
  • 公式テンプレート もしくは 成果物 の2ファイル

1. DB のマイグレーション

ドキュメント にも記載の通り、下記コマンドを実行すれば完了です。

$ docker compose run --rm outline yarn db:create --env=production-ssl-disabled
# ↑ Docker Compose でスキーマが作成されるため
# すでに存在すると言われるかもしれません
$ docker compose run --rm outline yarn db:migrate --env=production-ssl-disabled

2. Docker で minio が起動するようにする

minio を起動させるために、下記を追加しました。

compose.yml
  minio:
    image: minio/minio:latest
    ports:
      - '9000:9000'
      - '9001:9001'
    environment:
      - MINIO_ROOT_USER=%MINIO_ROOT_USER%
      - MINIO_ROOT_PASSWORD=%MINIO_ROOT_PASSWORD%
    command: server /export --console-address ":9001"
    volumes:
      - ./minio/data:/export # Docker Volume を使用してもOK

minio に外部からもアクセス可能なように、https-portal の設定も変更します。

compose.yml
  https-portal:
    image: steveltn/https-portal
    # ~~~ 省略 ~~~
    environment:
      # DOMAINS に minio 用のドメインを追加 
      DOMAINS: 'outline.domain -> http://outline:3000, minio.domain -> http://minio:9000, minio-console.domain -> http://minio:9001'
      STAGE: 'production'
      WEBSOCKET: 'true'
      CLIENT_MAX_BODY_SIZE: '0'

3. minio を設定

まずはアプリケーションを起動します。

$ docker compose up -d

次に設定した minio コンソール用のドメインにアクセスして、%MINIO_ROOT_USER%%MINIO_ROOT_PASSWORD% を使用してログインします。
アクセスできない方は、docker compose ps で立ち上がっていることを確認してみてください。

Bucket 作成

サイドメニューの Buckets へ進み、右上の「Create Bucket」から作成します。
名前は適当で大丈夫です。(outline とか outline-wiki とかなんでもOK)

ユーザー作成

Root ユーザーでアクセスキーを発行するのは少し怖かったため、ユーザーを作成しました。
サイドメニューの Identity > Users へ進み、右上の「Create User」から作成します。
ユーザー名、パスワードを入力し、readwite のみチェックを入れて作成します。

アクセスキーの発行

今作成したユーザーが Identity > Users の中に表示されていると思うのでそちらをクリックし、Service Accounts という項目へ進みます。

Create Access Key というボタンを押し、新しいアクセスキーを作成します。
この際、Access KeySecret Key をメモしておいてください。

docker.env に設定を追加

docker.env
# ↓ 先ほどメモした Access Key
AWS_ACCESS_KEY_ID=%MINIO_ACCESS_ID%
# ↓ 先ほどメモした Secret Key
AWS_SECRET_ACCESS_KEY=%MINIO_ACCESS_KEY%
# ↓ なんでもOK
AWS_REGION=local
AWS_S3_ACCELERATE_URL=
# ↓ minio のURL
AWS_S3_UPLOAD_BUCKET_URL=%MINIO_URL%
# ↓ 先ほど作成した Bucket の名前
AWS_S3_UPLOAD_BUCKET_NAME=%MINIO_BUCKET_NANE%
AWS_S3_FORCE_PATH_STYLE=true
AWS_S3_ACL=private

設定が完了したら、Docker Compose でアプリを落とします。

$ docker compose down

4. 認証関係の設定

こちらについては、公式ドキュメントでの設定をお願いします。

私は、無料版 Google Workspace で独自ドメインのアカウントのみログインできるようにしました。

5. 動作確認

設定が完了したら、Docker compose でアプリを起動します。

$ docker compose up -d
  • Outline に割り当てた URL でアクセスできる
  • ログインできる(最初にログインしたユーザーが Admin になります)
  • 画像やファイルのアップロード/ダウンロードができる
    以上の内容が確認できれば動確完了です。

アップデート手順

1. DBなどのバックアップを作成する

必要に応じて DB や Bucket のバックアップを作成してください。

2. Outline バージョンを変更する

アプリを終了し、Docker compose 記載の Outline のバージョンを上げます。(latest の場合はそのまま)

$ docker compose down
compose.yml
  outline:
    # ↓ ここのバージョンを変更する
    image: docker.getoutline.com/outlinewiki/outline:latest
    env_file: ./docker.env
    ports:
      - "3000:3000"
    volumes:
      - storage-data:/var/lib/outline/data
    depends_on:
      - postgres
      - redis
      - minio

3. Outline アップデート用のコマンドを実行する

# 1. 最新版をプル
$ docker compose pull

# 2. DBのマイグレーションを行う
$ docker compose run --rm outline yarn db:migrate --env=production-ssl-disabled

# 3. アプリを起動する
$ docker compose up -d

上記コマンドのみでアップデートが行えます。


おわりに

今回の記事で Outline Wiki に関する投稿が2つ目になってしまいました。
今後は Docker でホストした Outline を使っていこうと思います。

Discussion