Rspamd is a powerful and free spam filtering system. Unfortunately, there is no official Docker image available so let’s build one for ourselves.

If you only want rspamd to run in a container the Dockerfile is very simple: Just install the rspamd packages and set the command to /usr/sbin/rspamd -f. But rspamd can also expose a minimal web interface with statistics, logs and the ability to manually submit ham and spam. Of course we want that, too.
We use nginx to serve the necessary style sheets and icons for the rspamd web interface. These are included in the rspamd package. To make things easier we run both rspamd and nginx in the same docker container. We start them both at the same time using supervisord, one of the methods recommended by the Docker docs.

So this is our Dockerfile: it installs the necessary packages, copies the supervisord config and nginx config and starts supervisord.

Dockerfile
FROM alpine:3.17

RUN apk update && \
apk add rspamd rspamd-proxy rspamd-utils rspamd-controller supervisor nginx && \
rm -rf /var/cache/apk/*

COPY supervisord/supervisord.conf /etc/supervisord/supervisord.conf
COPY nginx/nginx.conf /etc/nginx/nginx.conf
COPY rspamd/local.d/logging.inc /etc/rspamd/local.d/logging.inc

EXPOSE 11332/tcp
EXPOSE 80/tcp

CMD exec /usr/bin/supervisord -c /etc/supervisord/supervisord.conf

We let nginx pick the static files from the rspamd package location and proxy the http requests to rspamd itself. Output goes to /dev/stdout to populate the Docker logs.

nginx/nginx.conf
worker_processes  2;
user nginx nginx;

pid /var/run/nginx.pid;

error_log /dev/stdout info;

events {
worker_connections 8192;
use epoll;
}

http {
include mime.types;
default_type text/plain;

sendfile on;
tcp_nopush on;
tcp_nodelay on;

gzip on;

server {
access_log /dev/stdout;

location / {
alias /usr/share/rspamd/www/;
try_files $uri @proxy;
}
location @proxy {
proxy_pass http://127.0.0.1:11334;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}
server_tokens off;
}
}

We let rspamd also log to the console.

rspamd/local.d/logging.inc
type = console
level = "notice";

Supervisord has the ability to start multiple processes but stay in foreground itself which is very convenient in docker containers as the main command stays alive. We use it to start rspamd and nginx, again, in foreground. Rspamd has a switch for that, nginx needs an additional option string.

supervisord/supervisord.conf
[supervisord]
nodaemon=true
user=root

[program:rspamd]
command=/usr/sbin/rspamd -f -u rspamd -g rspamd
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

[program:nginx]
command=/usr/sbin/nginx -g 'daemon off;'
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

Build your image like this:

docker build -t dovecot:2.3.19.1-r0-2 .

And that’s it. Build your image from the recipe above or just take my prebuilt Rspamd Docker image.