This guide provides instructions for running Exim in a Docker container with security best practices and proper configuration. Note that running mail servers in containers requires special considerations for networking and persistence.
Running mail servers in containers presents unique challenges:
Several community-maintained Exim Docker images are available:
# Pull the image
docker pull disaster/exim-smtp
# Run with basic configuration
docker run -d \
--name exim \
--restart unless-stopped \
-p 25:25 \
-p 587:587 \
-v exim-config:/etc/exim4 \
-v exim-spools:/var/spool/exim4 \
disaster/exim-smtp
# Lightweight relay image
docker pull anominous/exim-relay
# Run as a mail relay
docker run -d \
--name exim-relay \
--restart unless-stopped \
-p 25:25 \
-e RELAY_NETWORKS="172.16.0.0/12 192.168.0.0/16" \
anominous/exim-relay
For maximum control, create a custom Dockerfile:
FROM debian:12-slim
# Install Exim
RUN apt-get update && \
apt-get install -y exim4-daemon-heavy && \
rm -rf /var/lib/apt/lists/*
# Copy configuration
COPY ./config/ /etc/exim4/
# Create non-root user
RUN useradd -r -s /bin/false exim && \
chown -R exim:exim /var/spool/exim4 /var/log/exim4
# Update configuration
RUN update-exim4.conf
# Expose ports
EXPOSE 25 587 465
# Run as non-root user
USER exim
# Start Exim
CMD ["exim", "-bd", "-oX", "25:587:465"]
Build and run:
# Build the image
docker build -t custom-exim .
# Run with volume mounts
docker run -d \
--name exim-container \
--restart unless-stopped \
-p 25:25 \
-p 587:587 \
-p 465:465 \
-v exim-config:/etc/exim4 \
-v exim-spools:/var/spool/exim4 \
-v exim-logs:/var/log/exim4 \
custom-exim
Create a docker-compose.yml for easier management:
version: '3.8'
services:
exim:
image: disaster/exim-smtp
container_name: exim
restart: unless-stopped
ports:
- "25:25" # SMTP
- "587:587" # Submission
- "465:465" # SMTPS (if supported by image)
volumes:
- exim-config:/etc/exim4
- exim-spools:/var/spool/exim4
- exim-logs:/var/log/exim4
environment:
- TZ=Etc/UTC
- RELAY_NETWORKS=172.16.0.0/12 192.168.0.0/16
networks:
- mailnet
networks:
mailnet:
driver: bridge
volumes:
exim-config:
exim-spools:
exim-logs:
Deploy with:
# Deploy the stack
docker compose up -d
# Check logs
docker compose logs -f exim
For custom configurations, mount your config files:
docker run -d \
--name exim-custom \
-p 25:25 \
-v $(pwd)/config:/etc/exim4/conf.d:ro \
-v exim-spools:/var/spool/exim4 \
disaster/exim-smtp
Common environment variables for Exim containers:
RELAY_NETWORKS: Networks allowed to relay mailMAIN_HOSTNAME: Primary hostname for the mail serverLOCAL_DOMAINS: Domains to accept mail forTLS_CERT_PATH: Path to TLS certificateTLS_KEY_PATH: Path to TLS private key# docker-compose.yml
services:
exim:
# ...
networks:
- internal
# Don't expose unnecessary ports
ports:
- "25:25" # Only expose required ports
- "587:587"
# Limit resources
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
# Mount TLS certificates
docker run -d \
--name exim-tls \
-v /path/to/certs:/etc/ssl/certs:ro \
-e TLS_CERT_PATH=/etc/ssl/certs/mail.crt \
-e TLS_KEY_PATH=/etc/ssl/private/mail.key \
disaster/exim-smtp
# Check if container is running
docker ps | grep exim
# Check logs
docker logs exim
# Connect to container
docker exec -it exim bash
# Test Exim configuration
docker exec exim exim -bV
# Test mail routing
docker exec exim exim -bt test@example.com
Always use named volumes for:
/etc/exim4/)/var/spool/exim4/)/var/log/exim4/)# Monitor queue size
docker exec exim exim -bp | wc -l
# Monitor logs
docker logs exim --tail 50 -f
# Backup configuration
docker cp exim:/etc/exim4 ./backup/config
# Backup spools (when service is stopped)
docker stop exim
docker cp exim:/var/spool/exim4 ./backup/spools
docker start exim
Ensure your containerized Exim version is 4.99.1 or later to address security vulnerabilities:
docker exec exim exim -bV# Check if ports are accessible
docker exec exim netstat -tlnp | grep -E "(25|587|465)"
# Verify configuration
docker exec exim update-exim4.conf --dry-run
# Test connectivity
docker run --rm -it --network container:exim mwendler/netcat -zv localhost 25