Skip to content

Instantly share code, notes, and snippets.

@troykelly
Created October 24, 2022 04:13
Show Gist options
  • Save troykelly/ee9044d8b6e078bd4954e15ce67e12ce to your computer and use it in GitHub Desktop.
Save troykelly/ee9044d8b6e078bd4954e15ce67e12ce to your computer and use it in GitHub Desktop.
Mastodon Docker Compose
version: '3.8'
x-default-opts:
&default-opts
logging:
driver: gelf
options:
gelf-address: udp://${GELF_SERVER}:12201
gelf-compression-type: none
tag: "{{.ImageName}}/{{.Name}}/{{.ID}}"
labels: sy3,traefik
services:
db:
<<: *default-opts
restart: always
image: postgres:alpine
shm_size: 256mb
deploy:
replicas: 1
endpoint_mode: vip
placement:
max_replicas_per_node: 1
constraints:
- node.role==worker
update_config:
parallelism: 2
delay: 10s
resources:
limits:
cpus: '2.00'
memory: 2G
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
networks:
- backend
healthcheck:
test: ['CMD', 'pg_isready', '--username=${DB_USER}', '--dbname=${DB_NAME}']
volumes:
- postgres:/var/lib/postgresql/data
environment:
POSTGRES_HOST_AUTH_METHOD: scram-sha-256
POSTGRES_PASSWORD: ${DB_PASS}
POSTGRES_USER: ${DB_USER}
POSTGRES_DB: ${DB_NAME}
PGDATA: /var/lib/postgresql/data/pgdata
redis:
<<: *default-opts
image: redis:alpine
command: redis-server --requirepass ${REDIS_PASSWORD}
# healthcheck:
# test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
# interval: 1s
# timeout: 3s
# retries: 5
# start_period: 20m0s
deploy:
replicas: 1
endpoint_mode: vip
placement:
max_replicas_per_node: 1
constraints:
- node.role==worker
update_config:
parallelism: 2
delay: 10s
resources:
limits:
cpus: '2.00'
memory: 2G
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
networks:
- backend
volumes:
- type: tmpfs
target: "/tmp"
tmpfs:
size: 262144000
- type: tmpfs
target: "/var/run/redis"
tmpfs:
size: 262144000
- redis:/data
- "/etc/timezone:/etc/timezone:ro"
read_only: true
es:
<<: *default-opts
restart: always
image: docker.elastic.co/elasticsearch/elasticsearch:8.4.3
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"
- http.host=0.0.0.0
- network.host=0.0.0.0
- ELASTIC_USERNAME=${ES_USER}
- ELASTIC_PASSWORD=${ES_PASS}
deploy:
replicas: 1
endpoint_mode: vip
placement:
max_replicas_per_node: 1
constraints:
- node.role==worker
update_config:
parallelism: 2
delay: 10s
resources:
limits:
cpus: '2.00'
memory: 2G
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
networks:
- backend
healthcheck:
test: ["CMD-SHELL", "curl --silent --fail localhost:9200/_cluster/health || exit 1"]
volumes:
- elasticsearch:/usr/share/elasticsearch/data
- "/etc/timezone:/etc/timezone:ro"
- "/etc/localtime:/etc/localtime:ro"
- type: tmpfs
target: "/tmp"
tmpfs:
size: 262144000
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
# cleanup-es:
# <<: *default-opts
# restart: always
# image: ubuntu:latest
# command: ["sleep", "60"]
# deploy:
# replicas: 1
# endpoint_mode: vip
# placement:
# max_replicas_per_node: 1
# constraints:
# - node.role==worker
# update_config:
# parallelism: 2
# delay: 10s
# resources:
# limits:
# cpus: '2.00'
# memory: 2G
# restart_policy:
# condition: on-failure
# delay: 5s
# max_attempts: 3
# window: 120s
# networks:
# - backend
# volumes:
# - elasticsearch:/usr/share/elasticsearch/data
# - "/etc/timezone:/etc/timezone:ro"
# - "/etc/localtime:/etc/localtime:ro"
# - type: tmpfs
# target: "/tmp"
# tmpfs:
# size: 262144000
# ulimits:
# memlock:
# soft: -1
# hard: -1
# nofile:
# soft: 65536
# hard: 65536
web:
<<: *default-opts
image: tootsuite/mastodon
restart: always
command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000"
environment:
LOCAL_DOMAIN: ${LOCAL_DOMAIN}
STREAMING_API_BASE_URL: streaming.${LOCAL_DOMAIN}
REDIS_HOST: ${REDIS_HOST}
REDIS_PORT: ${REDIS_PORT}
REDIS_PASSWORD: ${REDIS_PASSWORD}
DB_HOST: ${DB_HOST}
DB_USER: ${DB_USER}
DB_NAME: ${DB_NAME}
DB_PASS: ${DB_PASS}
DB_PORT: ${DB_PORT}
ES_ENABLED: ${ES_ENABLED}
ES_HOST: ${ES_HOST}
ES_PORT: ${ES_PORT}
ES_USER: ${ES_USER}
ES_PASS: ${ES_PASS}
SECRET_KEY_BASE: ${SECRET_KEY_BASE}
OTP_SECRET: ${OTP_SECRET}
VAPID_PRIVATE_KEY: ${VAPID_PRIVATE_KEY}
VAPID_PUBLIC_KEY: ${VAPID_PUBLIC_KEY}
SMTP_SERVER: ${SMTP_SERVER}
SMTP_PORT: ${SMTP_PORT}
SMTP_LOGIN: ${SMTP_LOGIN}
SMTP_PASSWORD: ${SMTP_PASSWORD}
SMTP_FROM_ADDRESS: ${SMTP_FROM_ADDRESS}
S3_ENABLED: ${S3_ENABLED}
S3_BUCKET: ${S3_BUCKET}
S3_ENDPOINT: ${S3_ENDPOINT}
S3_PROTOCOL: ${S3_PROTOCOL}
S3_HOSTNAME: ${S3_HOSTNAME}
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
S3_ALIAS_HOST: ${S3_ALIAS_HOST}
IP_RETENTION_PERIOD: ${IP_RETENTION_PERIOD}
SESSION_RETENTION_PERIOD: ${SESSION_RETENTION_PERIOD}
TRUSTED_PROXY_IP: ${TRUSTED_PROXY_IP}
RAILS_LOG_LEVEL: debug
LOCAL_HTTPS: 'false'
deploy:
replicas: 2
endpoint_mode: vip
placement:
max_replicas_per_node: 1
constraints:
- node.role==worker
update_config:
parallelism: 2
delay: 10s
resources:
limits:
cpus: '2.00'
memory: 4G
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
labels:
# Enable Traefik for this service, to make it available in the public network
- traefik.enable=true
- traefik.docker.network=proxy
- traefik.constraint-label=traefik-public
- traefik.http.routers.${SITE}-http.rule=Host(`${LOCAL_DOMAIN}`,`www.${LOCAL_DOMAIN}`)
- traefik.http.routers.${SITE}-http.entrypoints=http
- traefik.http.routers.${SITE}-http.middlewares=https-redirect
- traefik.http.routers.${SITE}-https.rule=Host(`${LOCAL_DOMAIN}`,`www.${LOCAL_DOMAIN}`)
- traefik.http.routers.${SITE}-https.middlewares=cloudflarewarp
- traefik.http.routers.${SITE}-https.entrypoints=http3
- traefik.http.routers.${SITE}-https.tls=true
- traefik.http.routers.${SITE}-https.tls.certresolver=${SITE_RESOLVER}
- traefik.http.services.${SITE}.loadbalancer.server.port=3000
networks:
- backend
- proxy
healthcheck:
# prettier-ignore
test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:3000/health || exit 1']
volumes:
- site:/mastodon/public/system
- type: tmpfs
target: "/tmp"
tmpfs:
size: 262144000
streaming:
<<: *default-opts
image: tootsuite/mastodon
restart: always
environment:
LOCAL_DOMAIN: ${LOCAL_DOMAIN}
STREAMING_API_BASE_URL: streaming.${LOCAL_DOMAIN}
REDIS_HOST: ${REDIS_HOST}
REDIS_PORT: ${REDIS_PORT}
REDIS_PASSWORD: ${REDIS_PASSWORD}
DB_HOST: ${DB_HOST}
DB_USER: ${DB_USER}
DB_NAME: ${DB_NAME}
DB_PASS: ${DB_PASS}
DB_PORT: ${DB_PORT}
ES_ENABLED: ${ES_ENABLED}
ES_HOST: ${ES_HOST}
ES_PORT: ${ES_PORT}
ES_USER: ${ES_USER}
ES_PASS: ${ES_PASS}
SECRET_KEY_BASE: ${SECRET_KEY_BASE}
OTP_SECRET: ${OTP_SECRET}
VAPID_PRIVATE_KEY: ${VAPID_PRIVATE_KEY}
VAPID_PUBLIC_KEY: ${VAPID_PUBLIC_KEY}
SMTP_SERVER: ${SMTP_SERVER}
SMTP_PORT: ${SMTP_PORT}
SMTP_LOGIN: ${SMTP_LOGIN}
SMTP_PASSWORD: ${SMTP_PASSWORD}
SMTP_FROM_ADDRESS: ${SMTP_FROM_ADDRESS}
S3_ENABLED: ${S3_ENABLED}
S3_BUCKET: ${S3_BUCKET}
S3_ENDPOINT: ${S3_ENDPOINT}
S3_PROTOCOL: ${S3_PROTOCOL}
S3_HOSTNAME: ${S3_HOSTNAME}
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
S3_ALIAS_HOST: ${S3_ALIAS_HOST}
IP_RETENTION_PERIOD: ${IP_RETENTION_PERIOD}
SESSION_RETENTION_PERIOD: ${SESSION_RETENTION_PERIOD}
TRUSTED_PROXY_IP: ${TRUSTED_PROXY_IP}
LOCAL_HTTPS: 'false'
PORT: 4000
command: node ./streaming
deploy:
replicas: 2
endpoint_mode: vip
placement:
max_replicas_per_node: 1
constraints:
- node.role==worker
update_config:
parallelism: 2
delay: 10s
resources:
limits:
cpus: '2.00'
memory: 4G
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
labels:
# Enable Traefik for this service, to make it available in the public network
- traefik.enable=true
- traefik.docker.network=proxy
- traefik.constraint-label=traefik-public
- traefik.http.routers.streaming-${SITE}-http.rule=Host(`streaming.${LOCAL_DOMAIN}`)
- traefik.http.routers.streaming-${SITE}-http.entrypoints=http
- traefik.http.routers.streaming-${SITE}-http.middlewares=https-redirect
- traefik.http.routers.streaming-${SITE}-https.rule=Host(`streaming.${LOCAL_DOMAIN}`)
- traefik.http.routers.streaming-${SITE}-https.middlewares=cloudflarewarp
- traefik.http.routers.streaming-${SITE}-https.entrypoints=http3
- traefik.http.routers.streaming-${SITE}-https.tls=true
- traefik.http.routers.streaming-${SITE}-https.tls.certresolver=${SITE_RESOLVER}
- traefik.http.services.streaming-${SITE}.loadbalancer.server.port=4000
volumes:
- site:/mastodon/public/system
- type: tmpfs
target: "/tmp"
tmpfs:
size: 262144000
networks:
- backend
- proxy
healthcheck:
# prettier-ignore
test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:4000/api/v1/streaming/health || exit 1']
sidekiq:
<<: *default-opts
image: tootsuite/mastodon
restart: always
environment:
LOCAL_DOMAIN: ${LOCAL_DOMAIN}
STREAMING_API_BASE_URL: streaming.${LOCAL_DOMAIN}
REDIS_HOST: ${REDIS_HOST}
REDIS_PORT: ${REDIS_PORT}
REDIS_PASSWORD: ${REDIS_PASSWORD}
DB_HOST: ${DB_HOST}
DB_USER: ${DB_USER}
DB_NAME: ${DB_NAME}
DB_PASS: ${DB_PASS}
DB_PORT: ${DB_PORT}
ES_ENABLED: ${ES_ENABLED}
ES_HOST: ${ES_HOST}
ES_PORT: ${ES_PORT}
ES_USER: ${ES_USER}
ES_PASS: ${ES_PASS}
SECRET_KEY_BASE: ${SECRET_KEY_BASE}
OTP_SECRET: ${OTP_SECRET}
VAPID_PRIVATE_KEY: ${VAPID_PRIVATE_KEY}
VAPID_PUBLIC_KEY: ${VAPID_PUBLIC_KEY}
SMTP_SERVER: ${SMTP_SERVER}
SMTP_PORT: ${SMTP_PORT}
SMTP_LOGIN: ${SMTP_LOGIN}
SMTP_PASSWORD: ${SMTP_PASSWORD}
SMTP_FROM_ADDRESS: ${SMTP_FROM_ADDRESS}
S3_ENABLED: ${S3_ENABLED}
S3_BUCKET: ${S3_BUCKET}
S3_ENDPOINT: ${S3_ENDPOINT}
S3_PROTOCOL: ${S3_PROTOCOL}
S3_HOSTNAME: ${S3_HOSTNAME}
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
S3_ALIAS_HOST: ${S3_ALIAS_HOST}
IP_RETENTION_PERIOD: ${IP_RETENTION_PERIOD}
SESSION_RETENTION_PERIOD: ${SESSION_RETENTION_PERIOD}
TRUSTED_PROXY_IP: ${TRUSTED_PROXY_IP}
LOCAL_HTTPS: 'false'
command: bundle exec sidekiq
deploy:
replicas: 1
endpoint_mode: vip
placement:
max_replicas_per_node: 1
constraints:
- node.role==worker
update_config:
parallelism: 2
delay: 10s
resources:
limits:
cpus: '2.00'
memory: 2G
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
networks:
- backend
volumes:
- site:/mastodon/public/system
- type: tmpfs
target: "/tmp"
tmpfs:
size: 262144000
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:
proxy:
name: proxy
driver: overlay
external: true
backend:
driver: overlay
volumes:
redis:
driver: glusterfs
name: ${GLUSTERFS_REDIS}
postgres:
driver: glusterfs
name: ${GLUSTERFS_POSTGRES}
elasticsearch:
driver: glusterfs
name: ${GLUSTERFS_ELASTICSEARCH}
sidekiq:
driver: glusterfs
name: ${GLUSTERFS_SIDEKIQ}
site:
driver: glusterfs
name: ${GLUSTERFS_SITE}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment