Docker builds (#231)
ci/woodpecker/push/woodpecker Pipeline was successful Details

Co-authored-by: FloatingGhost <>
Reviewed-on: #231
floatingghost 5 months ago
parent 60b3c8d17b
commit 66f913355a

@ -6,12 +6,12 @@ COPYING
*file *file
elixir_buildpack.config elixir_buildpack.config
test/ test/
test test
benchmarks benchmarks
docs/site docs/site
# Required to get version # Required to get version
!.git !.git

.gitignore vendored

@ -17,6 +17,13 @@ secret
/instance /instance
/priv/ssh_keys /priv/ssh_keys
vm.args vm.args
# Prevent committing custom emojis # Prevent committing custom emojis
/priv/static/emoji/custom/* /priv/static/emoji/custom/*
@ -65,3 +72,6 @@ pleroma.iml
# Generated documentation # Generated documentation
docs/site docs/site
# docker stuff

@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](
## Unreleased ## Unreleased
## Added
- Officially supported docker release
## Changes ## Changes
- Follows no longer override domain blocks, a domain block is final - Follows no longer override domain blocks, a domain block is final
- Deletes are now the lowest priority to publish and will be handled after creates - Deletes are now the lowest priority to publish and will be handled after creates

@ -1,21 +1,9 @@
FROM elixir:1.13.4-alpine as build FROM hexpm/elixir:1.13.4-erlang-
COPY . .
RUN apk add git gcc g++ musl-dev make cmake file-dev &&\ ARG HOME=/opt/akkoma
echo "import Config" > config/prod.secret.exs &&\ ARG DATA=/var/lib/akkoma
mix local.hex --force &&\
mix local.rebar --force &&\
mix deps.get --only prod &&\
mkdir release &&\
mix release --path release
FROM alpine:3.16
LABEL org.opencontainers.image.title="akkoma" \ LABEL org.opencontainers.image.title="akkoma" \
org.opencontainers.image.description="Akkoma for Docker" \ org.opencontainers.image.description="Akkoma for Docker" \
@ -26,25 +14,21 @@ LABEL org.opencontainers.image.title="akkoma" \
org.opencontainers.image.revision=$VCS_REF \ org.opencontainers.image.revision=$VCS_REF \
org.opencontainers.image.created=$BUILD_DATE org.opencontainers.image.created=$BUILD_DATE
ARG HOME=/opt/akkoma RUN apk add git gcc g++ musl-dev make cmake file-dev exiftool ffmpeg imagemagick libmagic ncurses postgresql-client
ARG DATA=/var/lib/akkoma
RUN apk update &&\ EXPOSE 4000
apk add exiftool ffmpeg imagemagick libmagic ncurses postgresql-client &&\
adduser --system --shell /bin/false --home ${HOME} akkoma &&\
mkdir -p ${DATA}/uploads &&\
mkdir -p ${DATA}/static &&\
chown -R akkoma ${DATA} &&\
mkdir -p /etc/akkoma &&\
chown -R akkoma /etc/akkoma
USER akkoma ARG UID=1000
ARG GID=1000
ARG UNAME=akkoma
COPY --from=build --chown=akkoma:0 /release ${HOME} RUN addgroup -g $GID $UNAME
RUN adduser -u $UID -G $UNAME -D -h $HOME $UNAME
COPY ./config/docker.exs /etc/akkoma/config.exs WORKDIR /opt/akkoma
RUN mix local.hex --force &&\
mix local.rebar --force
ENTRYPOINT ["/opt/akkoma/"] CMD ["/opt/akkoma/"]

@ -24,11 +24,11 @@ config :pleroma, Pleroma.Repo,
config :web_push_encryption, :vapid_details, subject: "mailto:#{System.get_env("NOTIFY_EMAIL")}" config :web_push_encryption, :vapid_details, subject: "mailto:#{System.get_env("NOTIFY_EMAIL")}"
config :pleroma, :database, rum_enabled: false config :pleroma, :database, rum_enabled: false
config :pleroma, :instance, static_dir: "/var/lib/pleroma/static" config :pleroma, :instance, static_dir: "/var/lib/akkoma/static"
config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/pleroma/uploads" config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/akkoma/uploads"
# We can't store the secrets in this file, since this is baked into the docker image # We can't store the secrets in this file, since this is baked into the docker image
if not File.exists?("/var/lib/pleroma/secret.exs") do if not File.exists?("/var/lib/akkoma/secret.exs") do
secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64) secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64)
signing_salt = :crypto.strong_rand_bytes(8) |> Base.encode64() |> binary_part(0, 8) signing_salt = :crypto.strong_rand_bytes(8) |> Base.encode64() |> binary_part(0, 8)
{web_push_public_key, web_push_private_key} = :crypto.generate_key(:ecdh, :prime256v1) {web_push_public_key, web_push_private_key} = :crypto.generate_key(:ecdh, :prime256v1)
@ -52,16 +52,16 @@ if not File.exists?("/var/lib/pleroma/secret.exs") do
web_push_private_key: Base.url_encode64(web_push_private_key, padding: false) web_push_private_key: Base.url_encode64(web_push_private_key, padding: false)
) )
File.write("/var/lib/pleroma/secret.exs", secret_file) File.write("/var/lib/akkoma/secret.exs", secret_file)
end end
import_config("/var/lib/pleroma/secret.exs") import_config("/var/lib/akkoma/secret.exs")
# For additional user config # For additional user config
if File.exists?("/var/lib/pleroma/config.exs"), if File.exists?("/var/lib/akkoma/config.exs"),
do: import_config("/var/lib/pleroma/config.exs"), do: import_config("/var/lib/akkoma/config.exs"),
else: else:
File.write("/var/lib/pleroma/config.exs", """ File.write("/var/lib/akkoma/config.exs", """
import Config import Config
# For additional configuration outside of environmental variables # For additional configuration outside of environmental variables

@ -0,0 +1,61 @@
version: "3.7"
image: akkoma-db:latest
build: ./docker-resources/database
restart: unless-stopped
user: ${DOCKER_USER}
environment: {
# This might seem insecure but is usually not a problem.
# You should leave this at the "akkoma" default.
# The DB is only reachable by containers in the same docker network,
# and is not exposed to the open internet.
# If you do change this, remember to update "config.exs".
POSTGRES_DB: akkoma,
- .env
- type: bind
source: ./pgdata
target: /var/lib/postgresql/data
image: akkoma:latest
build: .
restart: unless-stopped
- .env
- db
ports: [
# Uncomment/Change port mappings below as needed.
# The left side is your host machine, the right one is the akkoma container.
# You can prefix the left side with an ip.
# Webserver (for reverse-proxies outside of docker)
# If you use a dockerized proxy, you can leave this commented
# and use a container link instead.
- .:/opt/akkoma
# Uncomment the following if you want to use a reverse proxy
# image: caddy:2-alpine
# restart: unless-stopped
# links:
# - akkoma
# ports: [
# "443:443",
# "80:80"
# ]
# volumes:
# - ./docker-resources/Caddyfile:/etc/caddy/Caddyfile
# - ./caddy-data:/data
# - ./caddy-config:/config

@ -8,7 +8,7 @@ while ! pg_isready -U ${DB_USER:-pleroma} -d postgres://${DB_HOST:-db}:5432/${DB
done done
echo "-- Running migrations..." echo "-- Running migrations..."
$HOME/bin/pleroma_ctl migrate mix ecto.migrate
echo "-- Starting!" echo "-- Starting!"
exec $HOME/bin/pleroma start mix phx.server

@ -0,0 +1,14 @@
# default docker Caddyfile config for Akkoma
# Simple installation instructions:
# 1. Replace 'example.tld' with your instance's domain wherever it appears.
example.tld {
log {
output file /var/log/caddy/akkoma.log
encode gzip
reverse_proxy akkoma:4000

@ -0,0 +1,4 @@
docker-compose build --build-arg UID=$(id -u) --build-arg GID=$(id -g) akkoma
docker-compose build --build-arg UID=$(id -u) --build-arg GID=$(id -g) db

@ -0,0 +1,10 @@
FROM postgres:14-alpine
ARG UID=1000
ARG GID=1000
ARG UNAME=akkoma
RUN addgroup -g $GID $UNAME
RUN adduser -u $UID -G $UNAME -D -h $HOME $UNAME
USER akkoma

@ -0,0 +1,4 @@

@ -0,0 +1,3 @@
docker-compose run --rm akkoma $@

@ -0,0 +1,160 @@
# Installing in Docker
## Installation
This guide will show you how to get akkoma working in a docker container,
if you want isolation, or if you run a distribution not supported by the OTP
### Prepare the system
* Install docker and docker-compose
* [Docker](
* [Docker-compose](
* This will usually just be a repository installation and a package manager invocation.
* Clone the akkoma repository
* `git clone -b stable`
* `cd akkoma`
### Set up basic configuration
cp docker-resources/env.example .env
echo "DOCKER_USER=$(id -u):$(id -g)" >> .env
This probably won't need to be changed, it's only there to set basic environment
variables for the docker-compose file.
### Building the container
The container provided is a thin wrapper around akkoma's dependencies,
it does not contain the code itself. This is to allow for easy updates
and debugging if required.
This will generate a container called `akkoma` which we can use
in our compose environment.
### Generating your instance
mkdir pgdata
# if you want to use caddy
mkdir caddy-data
mkdir caddy-config
./docker-resources/ mix deps.get
./docker-resources/ mix compile
./docker-resources/ mix pleroma.instance gen
This will ask you a few questions - the defaults are fine for most things,
the database hostname is `db`, and you will want to set the ip to ``.
Now we'll want to copy over the config it just created
cp config/generated_config.exs config/prod.secret.exs
### Setting up the database
We need to run a few commands on the database container, this isn't too bad
docker-compose run --rm --user akkoma -d db
# Note down the name it gives here, it will be something like akkoma_db_run
docker-compose run --rm akkoma psql -h db -U akkoma -f config/setup_db.psql
docker stop akkoma_db_run # Replace with the name you noted down
Now we can actually run our migrations
./docker-resources/ mix ecto.migrate
# this will recompile your files at the same time, since we changed the config
### Start the server
We're going to run it in the foreground on the first run, just to make sure
everything start up.
docker-compose up
If everything went well, you should be able to access your instance at http://localhost:4000
You can `ctrl-c` out of the docker-compose now to shutdown the server.
### Running in the background
docker-compose up -d
### Create your first user
If your instance is up and running, you can create your first user with administrative rights with the following task:
./docker-resources/ mix pleroma.user new MY_USERNAME MY_EMAIL@SOMEWHERE --admin
And follow the prompts
### Reverse proxies
This is a tad more complex in docker than on the host itself. It
You've got two options.
#### Running caddy in a container
This is by far the easiest option. It'll handle HTTPS and all that for you.
cp docker-resources/Caddyfile.example docker-resources/Caddyfile
Then edit the TLD in your caddyfile to the domain you're serving on.
Uncomment the `caddy` section in the docker-compose file,
then run `docker-compose up -d` again.
#### Running a reverse proxy on the host
If you want, you can also run the reverse proxy on the host. This is a bit more complex, but it's also more flexible.
Follow the guides for source install for your distribution of choice, or adapt
as needed. Your standard setup can be found in the [Debian Guide](../debian_based_en/#nginx)
### You're done!
All that's left is to set up your frontends.
The standard from-source commands will apply to you, just make sure you
prefix them with `./docker-resources/`!
{! installation/frontends.include !}
### Updating Docker Installs
git pull
./docker-resources/ mix deps.get
./docker-resources/ mix compile
./docker-resources/ mix ecto.migrate
docker-compose restart akkoma
#### Further reading
{! installation/further_reading.include !}
{! support.include !}

@ -21,5 +21,11 @@ For most installations, the following will suffice:
mix pleroma.frontend install admin-fe --ref stable mix pleroma.frontend install admin-fe --ref stable
``` ```
=== "Docker"
./docker-resources/ mix pleroma.frontend install pleroma-fe --ref stable
./docker-resources/ mix pleroma.frontend install admin-fe --ref stable
For more customised installations, refer to [Frontend Management](../../configuration/frontend_management) For more customised installations, refer to [Frontend Management](../../configuration/frontend_management)