ccruiの博客

ccruiの博客

Outline docker-compose 部署

1107
2024-03-01

Outline docker-compose 部署

1709254373478.png

前言

前段时间想要搭建一个自己的 outline 服务用作wiki使用,但是在搜索引擎上搜索了一圈,发现现有的教程就那么几篇,并且没有一个是完整的。

研究了一段时间,并且查看了官方的文档,终于搞定了 outline 的部署。

准备工作

  • 一台服务器
  • docker
  • docker-compose
  • 一个域名
  • 一个 SSL 证书

包含服务

  • outline - outline 项目本体
  • redis - 缓存数据库
  • postgres - 数据库
  • minio - 用于构建兼容 S3 的对象存储服务
  • sso-server - 单点登录服务

部署

我将部署分为了两个部分,第一部分为 minio 部署,用于存储 outline 的数据,第二部分为其他依赖项目部署。

因为 minio 是一个通用的对象存储服务,可能有其他的项目也会用到,所以我将 minio 部署单独拿出来。

部署过程中,我将会使用到 docker-compose,所以需要提前安装好 docker 和 docker-compose。

并且需要在 docker-compose.yml 文件所在的目录下创建.env 文件,用于存放一些敏感信息。

minio 部署

docker-compose.yml

version: "3"
services:
  minio:
    image: ${DOCKER_MINIO_IMAGE_NAME}
    env_file: ./.env # 指定环境变量文件
    container_name: minio
    ports:
      - 9502:9000
      - 9503:9001
    restart: always
    command: server /data --console-address :9000 --address :9001
    environment:
      MINIO_ROOT_USER: ${MINIO_ROOT_USER}
      MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
    logging:
      options:
        max-size: "5M"
        max-file: "10"
      driver: json-file
    volumes:
      - ./minio_data:/data
    labels:
      createdBy: "Apps"

.env

DOCKER_MINIO_IMAGE_NAME=minio/minio:RELEASE.2024-01-05T22-17-24Z
DOCKER_MINIO_ROOT_USER=admin
DOCKER_MINIO_ROOT_PASSWORD=admin

后续操作

使用 Nginx 反向代理 minio 服务,其中 9502 端口为 minio 服务的 http 端口,9503 端口为 minio 服务的 API 端口。

示例:
localhost:9502 -> https://minio.example.com
localhost:9503 -> https://api-minio.example.com

部署完成后,请访问https://minio.example.com,使用设定的用户名和密码登录。
登录后,在设置中将Region设置为cn-1,并且在Bucket中增加一个 bucket,命名为outline用于存储 outline 的数据,访问权限设置为私有

可选操作

Bucket->outline->Access->User中增加一个用户,用于 outline 服务访问 minio 服务。

outline 部署

docker-compose.yml

version: "3.8"
services:
  outline:
    image: ${DOCKER_OUTLINE_IMAGE_NAME}
    env_file: ./.env
    ports:
      - "9303:3000"
    container_name: outline
    restart: always
    networks:
      - outline
    extra_hosts:
      - "${DOCKER_OUTLINE_HOSTNAME}:0.0.0.0"
    depends_on:
      - postgres
      - redis
      - sso-server

  redis:
    image: ${DOCKER_REDIS_IMAGE_NAME}
    env_file: ./.env
    volumes:
      - ./redis/redis.conf:/redis.conf # 配置文件持久化
    container_name: ${DOCKER_REDIS_HOST}
    restart: always
    networks:
      - outline
    command: ["redis-server", "/redis.conf"] # 启动命令

  postgres:
    image: ${DOCKER_POSTGRES_IMAGE_NAME}
    env_file: ./.env
    environment:
      POSTGRES_DB: ${DOCKER_POSTGRES_DB}
      POSTGRES_USER: ${DOCKER_POSTGRES_USER}
      POSTGRES_PASSWORD: ${DOCKER_POSTGRES_PASSWORD}
    volumes:
      - ./database-data:/var/lib/postgresql/data # 数据持久化
    container_name: ${DOCKER_POSTGRES_HOST}
    restart: always
    networks:
      - outline

  sso-server:
    image: ${DOCKER_SSO_IMAGE_NAME}
    env_file: ./.env
    ports:
      - "9304:80"
    environment:
      CLIENT_NAME: ${DOCKER_SSO_CLIENT_NAME}
      CLIENT_ID: ${DOCKER_SSO_CLIENT_ID}
      CLIENT_SECRET: ${DOCKER_SSO_CLIENT_SECRET}
      USER_PASS: ${DOCKER_SSO_USER_PASS}
      LICENSE: ${DOCKER_SSO_LICENSE}
      PORT: 80
    container_name: ${DOCKER_SSO_HOST}
    restart: always
    networks:
      - outline

networks:
  outline:

.env

请根据实际情况修改以下配置

注意!下面配置请逐行详细阅读,并根据实际情况修改

# 镜像设置
DOCKER_OUTLINE_IMAGE_NAME=docker.getoutline.com/outlinewiki/outline:latest
DOCKER_POSTGRES_IMAGE_NAME=postgres
DOCKER_REDIS_IMAGE_NAME=redis
DOCKER_SSO_IMAGE_NAME=soulteary/sso-server:1.1.5

# 容器名称
DOCKER_REDIS_HOST=outline_redis
DOCKER_POSTGRES_HOST=outline_postgres
DOCKER_SSO_HOST=outline_sso-server

# postgres设置
DOCKER_POSTGRES_USER=outline
DOCKER_POSTGRES_PASSWORD=outline
DOCKER_POSTGRES_DB=outline

# sso-server设置
DOCKER_SSO_CLIENT_NAME=My SSO Service # 用于显示在登录页面
DOCKER_SSO_CLIENT_ID=ca63edca-6773-4f55-8a7f-bf7b45a8b493 # https://www.uuidgenerator.net/ 随机生成
DOCKER_SSO_CLIENT_SECRET=85c11838-7ac9-416c-9362-669c1c488238 # https://www.uuidgenerator.net/ 随机生成
DOCKER_SSO_USER_PASS=S4q6WhThqH5Y8Hh # SSO登录密码
SSO_HOSTNAME=auth.example.com # sso-server域名(需要自己使用Nginx反向代理)
# 默认用户账号为 `username`,如果你希望使用自己的用户名进行登陆,则需要修改DOCKER_SSO_LICENSE的值
# DOCKER_SSO_LICENSE的值可使用 https://readers-lic-gift.suyang.wiki/ 生成
# DOCKER_SSO_LICENSE=

# outline设置
DOCKER_OUTLINE_HOSTNAME=docs.example.com # outline域名(需要自己使用Nginx反向代理)

# –––––––––––––––– outline必需 –––––––––––––––-

NODE_ENV=production

# 生成一个十六进制编码的32字节随机密钥。你应该在终端使用 `openssl rand -hex 32`
# 来生成一个随机值。
SECRET_KEY=d8e45ea2e5d298d976464888dea86c92b72dfa73a48cb8903454205c02c732b3

# 生成一个唯一的随机密钥。格式不重要,但你仍然可以使用
# `openssl rand -hex 32` 在你的终端来产生这个。
UTILS_SECRET=cf561a25ab8bd24c58e6d74edd726f60de11fd5c3fb88289c725a48ab3b7b759

# 对于生产环境,请将这些指向你的数据库,在开发中默认
# 应该是开箱即用的。
DATABASE_URL=postgres://${DOCKER_POSTGRES_USER}:${DOCKER_POSTGRES_PASSWORD}@${DOCKER_POSTGRES_HOST}:5432/${DOCKER_POSTGRES_DB}
DATABASE_CONNECTION_POOL_MIN=
DATABASE_CONNECTION_POOL_MAX=
# 取消注释此项以禁用连接到Postgres的SSL
PGSSLMODE=disable

# 对于redis,你可以指定一个与ioredis兼容的url,像这样
REDIS_URL=redis://${DOCKER_REDIS_HOST}:6379
# 或者,如果你想提供额外的连接选项,
# 使用一个base64编码的JSON连接选项对象。参考ioredis文档
# 了解可用选项的列表。
# 示例:使用Redis Sentinel来实现高可用性
# {"sentinels":[{"host":"sentinel-0","port":26379},{"host":"sentinel-1","port":26379}],"name":"mymaster"}
# REDIS_URL=ioredis://eyJzZW50aW5lbHMiOlt7Imhvc3QiOiJzZW50aW5lbC0wIiwicG9ydCI6MjYzNzl9LHsiaG9zdCI6InNlbnRpbmVsLTEiLCJwb3J0IjoyNjM3OX1dLCJuYW1lIjoibXltYXN0ZXIifQ==

# URL应该指向完全合格的、公开可访问的URL。如果使用代理,
# URL中的端口和PORT可能不同。
URL=https://${DOCKER_OUTLINE_HOSTNAME}
PORT=3000

# 查看在运行一个独立的协作
# 服务器的[文档](docs/SERVICES.md),在正常操作中不需要设置这个。
# COLLABORATION_URL=

# 为了支持上传头像和文档附件的图片,必须提供
# 一个兼容s3的存储。推荐使用AWS S3来实现冗余
# 但如果你想保持所有文件存储在本地,可以使用
# 例如minio (https://github.com/minio/minio) 的替代方案。

# 设置S3的更详细指南可以在这里找到:
# => https://wiki.generaloutline.com/share/125de1cc-9ff6-424b-8415-0d58c809a40f
# 这里使用在minio部署时使用的用户名和密码,或者使用在上一节中可选操作中创建的用户
AWS_ACCESS_KEY_ID=admin
AWS_SECRET_ACCESS_KEY=admin
AWS_REGION=cn-1
# AWS_S3_ACCELERATE_URL=
AWS_S3_UPLOAD_BUCKET_URL=https://api-minio.example.com
AWS_S3_UPLOAD_BUCKET_NAME=outline
AWS_S3_FORCE_PATH_STYLE=true
AWS_S3_ACL=private

# 指定要使用的存储系统。可能的值是"s3"或"local"之一。
# 对于"local",头像图片和文档附件将被保存在本地磁盘上。
FILE_STORAGE=s3

# 如果上面为FILE_STORAGE配置了"local",则这设置了所有附件/图片的父目录
# 确保该进程有权限创建
# 这个路径,并且也有权限向其写入文件。
FILE_STORAGE_LOCAL_ROOT_DIR=/var/lib/outline/data

# 上传附件允许的最大大小。
FILE_STORAGE_UPLOAD_MAX_SIZE=262144000

# 覆盖文档导入的最大大小,通常这应该比文档附件的最大大小要低。
# FILE_STORAGE_IMPORT_MAX_SIZE=

# 覆盖工作区导入的最大大小,这些可能特别大
# 并且文件是临时的,会在一段时间后自动删除。
# FILE_STORAGE_WORKSPACE_IMPORT_MAX_SIZE=

# –––––––––––––– 认证 ––––––––––––––

# 第三方登录凭证,至少需要配置Google、Slack、
# 或Microsoft中的一个才能进行工作安装,否则你将没有登录
# 选项。

# 要配置Slack认证,你需要在
# => https://api.slack.com/apps
# 创建一个应用程序
#
# 在配置Client ID时,添加一个重定向URL到"OAuth & Permissions":
# https://<URL>/auth/slack.callback
# SLACK_CLIENT_ID=从slack获取一个密钥
# SLACK_CLIENT_SECRET=获取上面密钥的密钥

# 要配置Google认证,你需要在
# => https://console.cloud.google.com/apis/credentials
# 创建一个OAuth客户端ID
#
# 在配置客户端ID时,添加一个已授权的重定向URI:
# https://<URL>/auth/google.callback
# GOOGLE_CLIENT_ID=
# GOOGLE_CLIENT_SECRET=

# 要配置Microsoft/Azure认证,你需要创建一个OAuth客户端。见
# 指南了解如何设置你的Azure应用:
# => https://wiki.generaloutline.com/share/dfa77e56-d4d2-4b51-8ff8-84ea6608faa4
# AZURE_CLIENT_ID=
# AZURE_CLIENT_SECRET=
# AZURE_RESOURCE_APP_ID=

# 要配置通用OIDC认证,你需要某种身份提供者。
# 见你使用的IdP的文档来获取以下信息:
# 重定向URI是 https://<URL>/auth/oidc.callback
OIDC_CLIENT_ID=${DOCKER_SSO_CLIENT_ID}
OIDC_CLIENT_SECRET=${DOCKER_SSO_CLIENT_SECRET}
OIDC_AUTH_URI=https://${SSO_HOSTNAME}/dialog/authorize
OIDC_TOKEN_URI=https://${SSO_HOSTNAME}/oauth/token
OIDC_USERINFO_URI=https://${SSO_HOSTNAME}/api/outline/oidc
OIDC_LOGOUT_URI=https://${SSO_HOSTNAME}/logout

# 指定从哪些声明中派生用户信息
# 支持JWT负载中任何有效的JSON路径
OIDC_USERNAME_CLAIM=preferred_username

# OIDC认证的显示名称
OIDC_DISPLAY_NAME=My SSO Service

# 空格分隔的认证范围。
OIDC_SCOPES=openid profile email


# –––––––––––––––– 可选 ––––––––––––––––

# 为HTTPS终止提供Base64编码的私钥和证书。仅当你不使用外部反向代理时才需要此项。见文档:
# https://wiki.generaloutline.com/share/1c922644-40d8-41fe-98f9-df2b67239d45
# SSL_KEY=
# SSL_CERT=

# 如果使用Cloudfront/Cloudflare分发或类似的服务,可以在下面设置。
# 这将导致javascript、样式表和图像的路径被更新为
# 在CDN_URL中定义的主机名。在CDN配置中,原始服务器
# 应设置为与URL相同。
# CDN_URL=

# 在生产环境中自动重定向到https。默认值为true,但如果你能确保
# SSL在外部负载均衡器处终止,可以设置为false。
FORCE_HTTPS=false

# 让安装通过发送匿名统计数据到
# 维护者来检查更新
ENABLE_UPDATES=false

# 应该启动多少个进程。作为一个合理的规则,将你服务器
# 可用内存除以512来大致估算
WEB_CONCURRENCY=1

# 如果你的反向代理已经记录了传入的http
# 请求,而这变得重复,你可以删除这一行
# DEBUG=http

# 配置服务器日志的最低严重性级别。应该是
# error, warn, info, http, verbose, debug 和 silly 之一
LOG_LEVEL=info

# 为了完整的Slack集成,包括搜索和发布到频道,还需要
# 以下配置,更多细节
# => https://wiki.generaloutline.com/share/be25efd1-b3ef-4450-b8e5-c4a4fc11e02a
#
# SLACK_VERIFICATION_TOKEN=你的令牌
# SLACK_APP_ID=A0XXXXXXX
# SLACK_MESSAGE_ACTIONS=true

# 可选地启用Sentry (sentry.io) 来跟踪错误和性能,
# 并可选地在UI中添加一个Sentry代理隧道以绕过广告拦截器:
# https://docs.sentry.io/platforms/javascript/troubleshooting/#using-the-tunnel-option)
# SENTRY_DSN=
# SENTRY_TUNNEL=

# 为了支持发送出站的事务性电子邮件,如"文档已更新"或
# "你被邀请了",你需要提供SMTP服务器的认证
# SMTP_HOST=smtp.office365.com
# SMTP_PORT=587
# SMTP_USERNAME=
# SMTP_PASSWORD=
# SMTP_FROM_EMAIL=
# SMTP_REPLY_EMAIL=
# SMTP_TLS_CIPHERS=
# SMTP_SECURE=false

# 默认界面语言。见translate.getoutline.com查看
# 可用的语言代码及其大致翻译的百分比。
DEFAULT_LANGUAGE=zh_CN

# 可选地启用应用程序Web服务器的速率限制器
RATE_LIMITER_ENABLED=true

# 为速率限制器配置默认的限流参数
RATE_LIMITER_REQUESTS=1000
RATE_LIMITER_DURATION_WINDOW=60

# Iframely API配置
# IFRAMELY_URL=
# IFRAMELY_API_KEY=

后续操作

使用 Nginx 反向代理 outline 服务,其中 9303 端口为 outline 服务的 http 端口。

示例:
localhost:9303 -> https://docs.example.com

使用 Nginx 反向代理 sso-server 服务,其中 9304 端口为 sso-server 服务的 http 端口。

示例:
localhost:9304 -> https://auth.example.com

浏览器访问https://auth.example.com/login,使用设定的用户名和密码登录(默认用户名为username)。
登录完成后,需绑定两步验证器,绑定完成后,即可使用https://docs.example.com访问 outline 服务。