We’ll use nginx-proxy and its acme companion to setup a reverse proxy that handles mutliple web services.
First, create the nginx-proxy network:
docker create network nginx-proxy
Then setup the docker-compose.yml in a nginx-proxy folder.
services:
nginx-proxy:
image: nginxproxy/nginx-proxy
container_name: nginx-proxy
labels:
- com.github.nginx-proxy.nginx_proxy=true
ports:
- "80:80"
- "443:443"
volumes:
- ./volumes/certs:/etc/nginx/certs
- ./volumes/conf.d:/etc/nginx/conf.d
- ./volumes/vhost:/etc/nginx/vhost.d
- ./volumes/html:/usr/share/nginx/html
- /var/run/docker.sock:/tmp/docker.sock:ro
dns:
- 8.8.8.8
- 8.8.4.4
restart: always
nginx-proxy-acme:
image: nginxproxy/acme-companion
container_name: nginx-proxy-acme
depends_on:
- nginx-proxy
volumes_from:
- nginx-proxy
volumes:
- ./volumes/certs:/etc/nginx/certs:rw
- ./volumes/acme:/etc/acme.sh
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- DEFAULT_EMAIL=YOUR_EMAIL_HERE_FOR_LETSENCRYPT_CERTS
- NGINX_PROXY_CONTAINER=nginx-proxy
restart: always
networks:
default:
name: nginx-proxy
external: true
This a graphical tool that provides a handy webUI and an embedded certificate manager. It may be a better investment if you plan to have multiple services.
---
services:
nginx-proxy-manager:
image: 'docker.io/jc21/nginx-proxy-manager:latest'
container_name: nginx-proxy-manager
restart: unless-stopped
ports:
- '80:80'
- '443:443'
- '8081:81'
volumes:
- ./volumes/npm/npm_data:/data
- ./volumes/npm/letsencrypt:/etc/letsencrypt
networks:
default:
name: nginx-proxy
external: true
In a dedicated mastodon folder, prepare the following docker-compose.yml (see also official instructions). You will want to use elasticsearch for full site search. Make sure your resources allow it.
# Adapted from <https://github.com/mastodon/mastodon/blob/main/docker-compose.yml>
---
services:
db:
restart: always
image: postgres:14-alpine
shm_size: 256mb
networks:
- internal_network
healthcheck:
test: ['CMD', 'pg_isready', '-U', 'postgres']
volumes:
- ./postgres14:/var/lib/postgresql/data
environment:
- 'POSTGRES_HOST_AUTH_METHOD=trust'
redis:
restart: always
image: redis:7-alpine
networks:
- internal_network
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
volumes:
- ./redis:/data
es:
restart: always
image: elasticsearch:7.17.24
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: tootsuite/mastodon:${MASTODON_VERSION}
#image: ghcr.io/mastodon/mastodon:v4.3.0 this would be the reccomended image on the github docker-compose file
restart: always
env_file: .env.production
#command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000"
command: bundle exec puma -C config/puma.rb
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
expose:
- 3000
environment:
VIRTUAL_HOST: "${MASTODON_DOMAIN}"
LETSENCRYPT_HOST: "${MASTODON_DOMAIN}"
VIRTUAL_PATH: "/"
VIRTUAL_PORT: 3000
RAILS_LOG_LEVEL: warn
streaming:
#build: .
image: tootsuite/mastodon-streaming:${MASTODON_VERSION}
restart: always
env_file: .env.production
# command: node ./streaming
command: node ./streaming/index.js
networks:
- external_network
- internal_network
healthcheck:
# prettier-ignore
test: ['CMD-SHELL', "curl -s --noproxy localhost localhost:4000/api/v1/streaming/health | grep -q 'OK' || exit 1"]
ports:
- '127.0.0.1:4000:4000'
depends_on:
- db
- redis
expose:
- 4000
environment:
VIRTUAL_HOST: "${MASTODON_DOMAIN}"
VIRTUAL_PATH: "/api/v1/streaming"
VIRTUAL_PORT: 4000
sidekiq:
#build: .
image: tootsuite/mastodon:${MASTODON_VERSION}
restart: always
env_file: .env.production
command: bundle exec sidekiq
environment:
- RAILS_LOG_LEVEL=error
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_hidden_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:
name: nginx-proxy
external: true
internal_network:
internal: true
Then add some custom info regarding your instance.
.env
#.env
[email protected]
MASTODON_DOMAIN=mymastodon.com
MASTODON_VERSION=v4.3.3
Launch the docker machinery and autocreate the env.production file.
# first time: setup mastodon
touch .env.production
sudo docker-compose run --rm -u root -v $(pwd)/.env.production:/opt/mastodon/.env.production -e RUBYOPT=-W0 web bundle exec rake mastodon:setup
# launch mastodon
docker-compose up -d
A new autocreated file from /opt/mastodon/.env.production and mapped locally contains all the important configurations settings. It can be modified if needed, and the server can be restarted at anytime with docker compose up -d