PowerMTA

PowerMTA Docker Container Setup: Step-by-Step Guide

Learn how to containerise PowerMTA with Docker: build an AlmaLinux-based image, mount licence and config volumes, allocate network interfaces, and troubleshoot common failures.

By Shane0 views
PowerMTA Docker Container Setup: Step-by-Step Guide

Deploying PowerMTA on bare metal ties the MTA to a specific operating system, package set, and kernel configuration. Moving to a PowerMTA Docker container setup gives you a repeatable image that deploys identically on any Docker host, from a developer laptop to a production VPS. By the end of this guide you will be able to build a PowerMTA image, mount licence and configuration volumes, allocate network interfaces, and troubleshoot common container-specific failures.

You still need a valid PowerMTA licence from Port25; containerising the MTA does not change licensing. This article assumes you already have the RPM or DEB package and a licence file. We will use AlmaLinux 8 as the base image and a Dockerfile that installs PowerMTA with a foreground process.

Why Run PowerMTA in Docker?

Consistency across deployments

A Docker image captures the exact PowerMTA version, base OS, and installation steps. When you deploy to a new VPS or migrate between cloud providers, the container starts with identical behaviour. This removes the drift that comes from manual package updates or server re-provisioning. If you later decide a non-Docker installation across a fleet of cloud servers is simpler, PMTAcore automates PowerMTA installation over SSH and generates DNS records from a Windows desktop app.

Isolation from host dependencies

PowerMTA on bare metal can conflict with other services that need port 25 or specific library versions. A container isolates those dependencies. The host only needs a Docker daemon. You can also run multiple PowerMTA containers on a single host with separate configurations, which is useful for testing different versions or customer environments. This does not replace the need for correct IP allocation, which we cover later.

Building a PowerMTA Docker Image

Base image and prerequisites

PowerMTA officially supports RPM-based distributions such as AlmaLinux 8/9 and Rocky Linux 8/9, as well as Ubuntu LTS. For this guide we use AlmaLinux 8 as the base image. You need the PowerMTA RPM package and a licence file. Store both outside the build context to prevent them from being baked into intermediate layers. If you prefer a step-by-step non-Docker installation, the PowerMTA Management documentation covers the manual process.

Dockerfile example

Create a file named Dockerfile with the following content. Adjust the ARG PMTA_RPM value to match the exact filename of your package.

# Base image
FROM almalinux:8

# PowerMTA RPM filename (adjust to your version)
ARG PMTA_RPM=PowerMTA-6.0r3.x86_64.rpm

# Copy the RPM into the image
COPY ${PMTA_RPM} /tmp/

# Install PowerMTA and clean up
RUN yum install -y /tmp/${PMTA_RPM} && \
    rm -f /tmp/${PMTA_RPM} && \
    yum clean all

# Expose SMTP and HTTP management port (if used)
EXPOSE 25 8080

# Run PowerMTA in foreground; check your version's flag for non-daemon mode
CMD ["sh", "-c", "exec /usr/sbin/pmtad --foreground"]

Build the image from the same directory that contains the Dockerfile and the RPM:

docker build -t my-powermta:6.0r3 .

Configuring Volumes and Licence Files

PowerMTA reads its configuration and licence from /etc/pmta and writes queue data to /var/spool/pmta. These must persist across container restarts and upgrades. Mount host directories rather than storing state inside the container layer.

Host pathContainer pathPurpose
/opt/pmta/licence/etc/pmta/licencePowerMTA licence file
/opt/pmta/config/etc/pmtaConfiguration directory (config, vmta files)
/opt/pmta/spool/var/spool/pmtaQueue and spool data
/opt/pmta/logs/var/log/pmtaOperational logs

Start a container with these volumes mounted. The --network host flag is used here because PowerMTA often needs to bind directly to host IP addresses; we discuss this in the next section.

docker run -d \
  --name powermta-prod \
  --restart unless-stopped \
  --network host \
  -v /opt/pmta/licence:/etc/pmta/licence:ro \
  -v /opt/pmta/config:/etc/pmta \
  -v /opt/pmta/spool:/var/spool/pmta \
  -v /opt/pmta/logs:/var/log/pmta \
  my-powermta:6.0r3

The licence file is mounted read-only to prevent accidental modification. Configuration files can be edited on the host and picked up after a container restart. Verify that the licence file exists inside the container with docker exec powermta-prod ls -l /etc/pmta/licence.

Networking and IP Allocation in Containers

Bridge networking vs host networking

Docker's default bridge network performs NAT, meaning the container's source IP becomes the Docker host's IP. For PowerMTA, this collapses all virtual MTA IP bindings into one address, breaking IP rotation. Use host networking (--network host) when the container must bind to multiple host IPs directly. In host mode, port mapping is not required because the container shares the host network stack.

Macvlan for per-container IPs

If you need each container to have its own IP address on the physical network, create a macvlan network. This is useful when scaling PowerMTA across containers or isolating customers. First create the network:

docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 \
  pmta_macvlan

Then run a container with a static IP:

docker run -d \
  --name powermta-customer1 \
  --network pmta_macvlan \
  --ip 192.168.1.50 \
  -v /opt/pmta/customer1/licence:/etc/pmta/licence:ro \
  -v /opt/pmta/customer1/config:/etc/pmta \
  -v /opt/pmta/customer1/spool:/var/spool/pmta \
  -v /opt/pmta/customer1/logs:/var/log/pmta \
  my-powermta:6.0r3

Macvlan bypasses the host network stack, so the container appears as a standalone device on the LAN. Make sure your upstream router and firewall permit forwarding for the allocated subnet. The same image runs on any Linux distribution with Docker Engine; on Windows 10 or 11 use Docker Desktop with the WSL2 backend and Linux containers.

Best Practices and Troubleshooting Dockerized PowerMTA

Best practices

  • Keep the Docker image immutable: rebuild instead of modifying containers.
  • Store licence, config, spool, and logs on persistent volumes, not inside the container layer.
  • Use --restart unless-stopped for automatic recovery after host reboots.
  • Run the container with host networking only if you need direct binding to multiple host IPs.
  • Monitor queue health with docker exec powermta-prod pmta show status.
  • Keep your PowerMTA RPM and licence outside the image build context to avoid leaking them in image layers.

Troubleshooting common issues

Start with the container logs. Most PowerMTA startup failures will appear there.

  1. Check logs: docker logs powermta-prod.
  2. Verify licence file presence and permissions: docker exec powermta-prod ls -l /etc/pmta/licence.
  3. Confirm port binding: docker exec powermta-prod netstat -tlnp | grep :25.
  4. Test SMTP from the host: telnet localhost 25.
  5. If using bridge networking, ensure published ports are mapped with -p 25:25 and that no other service on the host is using port 25.

For ongoing DNSBL monitoring of your sending IPs, PMTAcore's IP Blacklist Checker can stream results without needing to enter the container. If your goal is campaign-level bulk sending rather than MTA management, the separate Choco Mailer addon provides a self-hosted platform for multi-threaded sending.

Containerising PowerMTA gives you repeatable, isolated deployments that scale across hosts. When you are ready to manage PowerMTA across cloud servers without maintaining Dockerfiles, PMTAcore offers a Windows desktop workflow with automated installation over SSH and DNS generation. Start with the free trial or review the plans on the pricing page.

#powermta docker#powermta containerization#docker powermta#powermta docker setup#email infrastructure#smtp server docker