Mastondon ARM64 Docker Deployment

Build Mastodon ARM64 Docker image yourself

Mastondon ARM64 Docker Deployment

1. Intro

Last post of Mastodon Installation on AMD64: <GHOST_URL/mastodon-installation/>

2. Background

Docker is not recommended by Mastodon Official.(dunno why) Till now (202204), Mastodon does not have official docker image on DockerHub, so let’s build it ourselves.
Environment: ARM64, Ubuntu 20.04 LTS

3. Deployment

3.1 Dependencies

Install the required packages

apt -y update
apt -y install curl git nginx python3-certbot-nginx

Install Docker

curl -sSL https://get.docker.com/ | sh
systemctl enable --now nginx docker

Install docker-compose of ARM64

pip3 install docker-compose

3.2 Download Mastodon and edit docker-compose file

Pull files

cd /home/ubuntu/
git clone https://github.com/tootsuite/mastodon.git
cd mastodon/

Copy a configuration file

cp .env.production.sample .env.production

Actually you can rename or delete the default docker-compose.yml that comes with the project. If you use this yml configuration directly, it will definitely not run. There are too many problems beyond explanation, so I won't go into details here.

mv docker-compose.yml docker-compose.yml.bak

3.3 Build Mastodon ARM64 Image

Since Mastodon does not officially release the arm64-based image on DockerHub, we have to build the image ourselves. Fortunately, the official dockerfile directly supports arm64.
Check version

cd /home/ubuntu/mastodon/
git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)

Build image (the duration varies, depending on your CPU & RAM)

docker build -t mastodon .

After building image, you can check it via

docker images

The self-built ARM64 image is named mastodon:latest

3.4 Edit docker-compose file

Create docker-compose file

nano docker-compose.yml

Here I put up an example configuration I am currently using, for your reference

version: '3.8'

services:
  mastodon-db:
    image: postgres:9.6-alpine
    shm_size: 256mb
    environment:
      POSTGRES_DB: mastodon
      POSTGRES_USER: username
      POSTGRES_PASSWORD: password
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "postgres"]
    volumes:
      - ./postgres:/var/lib/postgresql/data
    restart: unless-stopped

  mastodon-redis:
    image: redis:6.0-alpine
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
    volumes:
      - ./redis:/data
    restart: unless-stopped

  mastodon-es:
    image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.2
    environment:
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - "cluster.name=es-mastodon"
      - "discovery.type=single-node"
      - "bootstrap.memory_lock=true"
    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
    restart: unless-stopped

  mastodon-web:
    image: mastodon:latest
    env_file: .env.production
    command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000"
    depends_on:
      - mastodon-db
      - mastodon-redis
    healthcheck:
      test: ["CMD-SHELL", "wget -q --spider --proxy=off localhost:3000/health || exit 1"]
    ports:
      - "127.0.0.1:3000:3000"
    volumes:
      - ./public/system:/mastodon/public/system
    restart: unless-stopped

  mastodon-streaming:
    image: mastodon:latest
    env_file: .env.production
    command: node ./streaming
    depends_on:
      - mastodon-db
      - mastodon-redis
    healthcheck:
      test: ["CMD-SHELL", "wget -q --spider --proxy=off localhost:4000/api/v1/streaming/health || exit 1"]
    ports:
      - "127.0.0.1:4000:4000"
    restart: unless-stopped

  mastodon-sidekiq:
    image: mastodon:latest
    env_file: .env.production
    command: bundle exec sidekiq
    depends_on:
      - mastodon-db
      - mastodon-redis
    volumes:
      - ./public/system:/mastodon/public/system
    restart: unless-stopped

Note 1: substitute each tootsuite/mastodon with mastodon:latest
Note 2: ElasticSearch only supports ARM64 since version 7.8, so let’s modify the default version to a higher version (with your choice)

image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.2

3.5 Run configuration wizard

Next, run this command to enter the configuration wizard

docker-compose run --rm mastodon-web bundle exec rake mastodon:setup

Simply follow the instructions below:

Domain name: # fill in your domain
Do you want to enable single user mode? # Yes
Are you using Docker to run Mastodon? # Yes
PostgreSQL host: # mastodon-db
PostgreSQL port: # 5432
Name of PostgreSQL database: # mastodon
Name of PostgreSQL user: # username, match the database username in docker-compose.yml
Password of PostgreSQL user: # password, match the database username in docker-compose.yml
Redis host: # mastodon-redis
Redis port: # 6379
Redis password: # leave blank, press enter directly
Do you want to store uploaded files on the cloud? # No
Do you want to send e-mails from localhost? # Yes
Send a test e-mail with this configuration right now? # No
Save configuration? Yes

Note: This configuration is in single-user mode. that is, registration is not open by default. You can switch it to non-single-user mode as you wish. Secondly, SMTP is not configured because I’m the only user.

Next, it will print out the configuration you filled in, and now you need to copy the configuration you filled in before.

This is a very tricky place. You will see the following prompt:

Prepare the database now? (Y/n)

Important: Don't choose Y or N, just press the keyboard combination Ctrl^C to exit. Then clear the default configuration in the following configuration file:

echo > .env.production

Edit it

nano .env.production

Paste the configuration you copied through the wizard output earlier and save. Then run the wizard again:

docker-compose run --rm mastodon-web bundle exec rake mastodon:setup

The configuration this time must be the same as the last time. When you come to the following prompt again, you can choose Yes:

Prepare the database now? (Y/n) # Yes
Compile the assets now? (Y/n) # Yes

The next step is to create an administrator account. Continue to follow this guide and it will be OK. Don't forget to keep the default admin credential. You'll need to change it later

3.6 Build up the container

Up docker-compose

docker-compose up -d

Now you need to change the owner of the public directory to the one in the container, otherwise you cannot upload avatar later.

chown -R 991:991 public

3.7 Config Nginx

Now make a copy of the Nginx configuration file

cp /home/ubuntu/mastodon/dist/nginx.conf /etc/nginx/conf.d/mastodon.conf

Edit mastodon.conf

nano /etc/nginx/conf.d/mastodon.conf

In this configuration file, the official template has been all set. You only need to edit in the following two server blocks:

server {
  listen 80;
  listen [::]:80;
  server_name example.com; # your domain
  root /home/ubuntu/mastodon/public; # absolute path of public directory
...
server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name example.com; # your domain
  root /home/ubuntu/mastodon/public; # absolute path of public directory
...
}

Use certbot to issue SSL certificates

certbot --nginx

Restart Nginx

systemctl restart nginx

4. Post-Installation

If you want to move your site in the future, just pack the /home/ubuntu/mastodon directory directly, and upload it to another machine after decompression.

It is the same to change the configuration in .env.production. After changes, you can run docker-compose up -d.


Copyright statement: Unless otherwise stated, all articles on this blog adopt the CC BY-NC-SA 4.0 license agreement. For non-commercial reprints and citations, please indicate the author: Henry, and original article URL. For commercial reprints, please contact the author for authorization.