Zurück zum Blog

Zentrales SMTP-Relay für Docker Container

Zentrales SMTP-Relay für Docker Container: Sichere E-Mail-Zustellung in isolierten Netzwerken

Zentrales SMTP-Relay für Docker Container: Sichere E-Mail-Zustellung in isolierten Netzwerken

Veröffentlicht 11. Januar 2026
Kategorie Infrastructure & E-Mail
Technologien Docker, Postfix, SMTP
Lesezeit 12 Minuten

1. Das Problem: E-Mail aus Docker Containern

In einer modernen Docker-basierten Infrastruktur laufen zahlreiche Services, die E-Mail-Benachrichtigungen versenden müssen: Authentifizierungs-Systeme für Passwort-Resets, CMS-Plattformen für Workflow-Notifications, Backup-Systeme für Status-Reports, und Monitoring-Tools für Alerts.

Doch was in einer klassischen Server-Umgebung trivial erscheint – eine E-Mail über einen SMTP-Server zu versenden – wird in containerisierten Umgebungen schnell zur Herausforderung.

Die Herausforderungen

Typische Probleme bei Docker E-Mail:
  • Netzwerk-Isolation: Container in internen Docker Networks haben keinen direkten Zugang zu externen Mail-Servern
  • DNS-Auflösung: Interne Container können oft externe Hostnamen nicht auflösen
  • Cross-Network-Kommunikation: Services in verschiedenen Docker Networks können nicht direkt kommunizieren
  • Dezentrale Konfiguration: Jeder Service hat eigene SMTP-Einstellungen – Wartungsalptraum
  • Security: Credentials müssen in jedem Container konfiguriert werden

Konkrete Symptome

In der Praxis manifestieren sich diese Probleme durch:

  • E-Mails, die nie ankommen
  • Timeout-Fehler beim Verbindungsaufbau
  • "Connection refused" oder "Host not found" Meldungen
  • Inkonsistente E-Mail-Zustellung (manchmal funktioniert es, manchmal nicht)
# Typischer Fehler in Container-Logs
SMTP Error: Could not connect to mail.example.com:587
Connection timed out (110)

# Oder
sendmail: fatal: Host not found: mail.example.com

2. Die Lösung: Zentrales SMTP-Relay

Die elegante Lösung für dieses Problem ist ein zentrales SMTP-Relay – ein spezialisierter Container, der als Gateway zwischen internen Services und dem externen Mail-Server fungiert.

Konzept

┌─────────────────────────────────────────────────────────────┐
│                 Internes Docker Network                      │
│                                                              │
│    ┌─────────┐    ┌─────────┐    ┌─────────┐               │
│    │Service A│    │Service B│    │Service C│               │
│    │  (Auth) │    │  (CMS)  │    │ (Backup)│               │
│    └────┬────┘    └────┬────┘    └────┬────┘               │
│         │              │              │                      │
│         └──────────────┼──────────────┘                      │
│                        │                                     │
│                        ▼                                     │
│              ┌──────────────────┐                           │
│              │   SMTP-Relay     │◄──── Einziger Ausgangspunkt
│              │   (Postfix)      │                           │
│              └────────┬─────────┘                           │
│                       │                                      │
└───────────────────────┼──────────────────────────────────────┘
                        │
                        │ SMTP Relay
                        ▼
              ┌──────────────────┐
              │   Mail-Server    │
              │   (Postfix/      │
              │    Mailcow)      │
              └──────────────────┘

Vorteile dieser Architektur

Warum ein zentrales SMTP-Relay?
  • Zentrale Konfiguration: Ein Punkt für alle SMTP-Einstellungen
  • Netzwerk-Brücke: Verbindet isolierte Networks mit dem Mail-Server
  • Security-Gateway: Zentrale Kontrolle über ausgehende E-Mails
  • Einfache Integration: Services senden an localhost-ähnlichen Host
  • Debugging: Ein Ort für Logs und Fehlersuche
  • Rate-Limiting: Schutz vor E-Mail-Flooding

3. Architektur & Design

Komponenten-Übersicht

Komponente Funktion Details
SMTP-Relay Container Gateway für E-Mail-Versand Postfix-basiert, leichtgewichtig
Internes Network Isoliertes Netzwerk für Services Eigenes Subnet, keine externe Erreichbarkeit
Mail-Server Network Verbindung zum Mail-Server Externes oder Mail-spezifisches Network
Client Services E-Mail sendende Anwendungen Auth, CMS, Backup, Monitoring, etc.

Netzwerk-Design

Der SMTP-Relay Container ist das einzige Element, das in beiden Netzwerken gleichzeitig existiert – dem internen Service-Network und dem Mail-Server-Network.

# Docker Network Topologie

smtp-internal (Bridge, isolated)
├── smtp-relay        ──┐
├── authentik         ──┤
├── directus          ──┼── Alle senden an smtp-relay:25
├── nextcloud         ──┤
├── n8n               ──┤
├── gitea             ──┤
└── backup            ──┘

mail-network (Bridge)
├── smtp-relay        ◄── Einzige Verbindung nach außen
├── postfix
├── dovecot
└── ...
Dual-Network Membership: Der SMTP-Relay Container ist Mitglied beider Networks und kann daher als Brücke fungieren, ohne dass andere Container direkten Zugriff auf das Mail-Network benötigen.

Message Flow

  1. Service (z.B. Authentik) generiert E-Mail
  2. Service sendet an smtp-relay:25 (internes Network)
  3. SMTP-Relay empfängt, validiert, loggt
  4. SMTP-Relay leitet an Mail-Server weiter (Mail-Network)
  5. Mail-Server versendet an Internet

4. Security-Konzept

Ein SMTP-Relay ohne angemessene Sicherheitsmaßnahmen kann schnell zum Open Relay werden – ein Albtraum für jeden Administrator. Die folgende Security-Architektur verhindert Missbrauch.

Defense in Depth: Mehrschichtige Sicherheit

┌─────────────────────────────────────────────────────────────┐
│  Schicht 1: Netzwerk-Isolation                              │
│  └── Nur Container im internen Network können verbinden     │
├─────────────────────────────────────────────────────────────┤
│  Schicht 2: IP-basierte Zugriffskontrolle                   │
│  └── Nur definiertes Subnet darf senden                     │
├─────────────────────────────────────────────────────────────┤
│  Schicht 3: Domain-Whitelist                                │
│  └── Nur eigene Domain als Absender erlaubt                 │
├─────────────────────────────────────────────────────────────┤
│  Schicht 4: Sender-Validierung                              │
│  └── FQDN-Prüfung, Domain-Existenz                          │
├─────────────────────────────────────────────────────────────┤
│  Schicht 5: Rate-Limiting                                   │
│  └── Maximale E-Mails pro Zeiteinheit                       │
└─────────────────────────────────────────────────────────────┘

Schicht 1: Netzwerk-Isolation

Das SMTP-Relay ist nur im internen Network erreichbar. Container außerhalb dieses Networks können keine Verbindung aufbauen.

# Docker Compose Network Definition
networks:
  smtp-internal:
    driver: bridge
    internal: false  # Bridge für Relay-Funktion
    ipam:
      config:
        - subnet: 172.30.0.0/24  # Dediziertes Subnet

Schicht 2: IP-basierte Zugriffskontrolle

Postfix akzeptiert nur Verbindungen aus dem definierten Subnet:

# Postfix MYNETWORKS Konfiguration
MYNETWORKS: "127.0.0.0/8 [INTERNES_SUBNET]"

# Nur localhost und das interne Subnet dürfen senden
# Alle anderen werden abgelehnt

Schicht 3: Domain-Whitelist

Nur E-Mails mit der eigenen Domain als Absender werden akzeptiert:

# Erlaubte Sender-Domains
ALLOWED_SENDER_DOMAINS: example.com

# Schützt vor:
# - Spoofing fremder Domains
# - Verwendung als Open Relay
# - Reputation-Schäden

Schicht 4: Sender-Validierung

# Postfix Sender Restrictions
smtpd_sender_restrictions:
  - permit_mynetworks        # Erlaube interne Clients
  - reject_unknown_sender_domain   # Lehne unbekannte Domains ab
  - reject_non_fqdn_sender   # Erfordere vollqualifizierte Adressen

Schicht 5: Rate-Limiting

Schutz vor Flooding, kompromittierten Containern und fehlerhaften Workflows:

# Postfix Rate-Limiting
smtpd_client_message_rate_limit: [MAX_MESSAGES_PER_HOUR]
smtpd_client_connection_rate_limit: [MAX_CONNECTIONS_PER_HOUR]
anvil_rate_time_unit: 3600s  # Zeitfenster: 1 Stunde
Keine Authentifizierung?

Da das SMTP-Relay nur im internen Network erreichbar ist (Schicht 1 & 2), ist keine zusätzliche Authentifizierung erforderlich. Die Netzwerk-Isolation ist der primäre Security-Mechanismus.

Dies vereinfacht die Konfiguration der Client-Services erheblich – sie benötigen keine Credentials, nur Host und Port.

5. Implementierung

Docker Compose Setup

Die Implementierung basiert auf dem boky/postfix Image – einem schlanken, produktionsreifen Postfix-Container:

version: '3.9'

services:
  smtp-relay:
    image: boky/postfix:latest
    container_name: smtp-relay
    hostname: smtp-relay
    restart: unless-stopped
    networks:
      - smtp-internal      # Internes Service-Network
      - mail-network       # Verbindung zum Mail-Server
    environment:
      # Relay-Ziel
      RELAYHOST: [MAIL_SERVER_HOST]:25

      # Security: Nur eigene Domain
      ALLOWED_SENDER_DOMAINS: example.com

      # Security: Nur internes Subnet
      MYNETWORKS: "127.0.0.0/8 [INTERNES_SUBNET]"

      # Rate-Limiting
      POSTFIX_smtpd_client_message_rate_limit: "[LIMIT]"
      POSTFIX_smtpd_client_connection_rate_limit: "[LIMIT]"
      POSTFIX_anvil_rate_time_unit: "3600s"

      # Sender-Validierung
      POSTFIX_smtpd_sender_restrictions: >-
        permit_mynetworks,
        reject_unknown_sender_domain,
        reject_non_fqdn_sender
    healthcheck:
      test: ["CMD", "postfix", "status"]
      interval: 30s
      timeout: 10s
      retries: 3
    deploy:
      resources:
        limits:
          memory: 128m
          cpus: '0.25'

networks:
  smtp-internal:
    driver: bridge
    ipam:
      config:
        - subnet: 172.30.0.0/24

  mail-network:
    external: true

Warum boky/postfix?

Eigenschaft Vorteil
Minimal Nur Postfix, keine unnötigen Komponenten
Environment-basiert Konfiguration via ENV-Variablen
Relay-optimiert Speziell für Relay-Szenarien designed
Aktiv maintained Regelmäßige Security-Updates
Klein ~50MB Image-Größe

6. Service-Integration

Die Integration in bestehende Services ist denkbar einfach: Anstatt externe SMTP-Server mit Credentials zu konfigurieren, verweisen alle Services auf den internen Relay.

Allgemeines Muster

# Vorher (externe SMTP-Konfiguration)
SMTP_HOST: mail.example.com
SMTP_PORT: 587
SMTP_USER: service@example.com
SMTP_PASSWORD: [GEHEIM]
SMTP_TLS: true

# Nachher (internes Relay)
SMTP_HOST: smtp-relay
SMTP_PORT: 25
SMTP_USER: (nicht benötigt)
SMTP_PASSWORD: (nicht benötigt)
SMTP_TLS: false

Beispiel: Authentik (SSO)

authentik-server:
  networks:
    - frontend
    - authentik-backend
    - smtp-internal         # Hinzufügen
  environment:
    AUTHENTIK_EMAIL__HOST: smtp-relay
    AUTHENTIK_EMAIL__PORT: 25
    AUTHENTIK_EMAIL__USE_TLS: "false"
    AUTHENTIK_EMAIL__USE_SSL: "false"
    AUTHENTIK_EMAIL__FROM: auth@example.com

Beispiel: Directus (CMS)

directus:
  networks:
    - frontend
    - webapp-backend
    - smtp-internal         # Hinzufügen
  environment:
    EMAIL_TRANSPORT: smtp
    EMAIL_SMTP_HOST: smtp-relay
    EMAIL_SMTP_PORT: 25
    EMAIL_FROM: cms@example.com

Beispiel: n8n (Workflow Automation)

n8n:
  networks:
    - frontend
    - n8n-backend
    - smtp-internal         # Hinzufügen
  environment:
    N8N_EMAIL_MODE: smtp
    N8N_SMTP_HOST: smtp-relay
    N8N_SMTP_PORT: 25
    N8N_SMTP_SENDER: workflow@example.com
    N8N_SMTP_SSL: "false"

Beispiel: Nextcloud (File Sharing)

Nextcloud benötigt zusätzliche Konfiguration via OCC-Kommando:

# Docker Compose: Network hinzufügen
nextcloud:
  networks:
    - frontend
    - cloud
    - smtp-internal         # Hinzufügen

# OCC-Konfiguration
docker exec -u www-data nextcloud php occ config:system:set \
  mail_smtpmode --value="smtp"
docker exec -u www-data nextcloud php occ config:system:set \
  mail_smtphost --value="smtp-relay"
docker exec -u www-data nextcloud php occ config:system:set \
  mail_smtpport --value="25"
docker exec -u www-data nextcloud php occ config:system:set \
  mail_from_address --value="cloud"
docker exec -u www-data nextcloud php occ config:system:set \
  mail_domain --value="example.com"

Beispiel: Gitea (Git Service)

gitea:
  networks:
    - frontend
    - gitea-backend
    - smtp-internal         # Hinzufügen
  environment:
    GITEA__mailer__ENABLED: "true"
    GITEA__mailer__FROM: git@example.com
    GITEA__mailer__PROTOCOL: smtp
    GITEA__mailer__SMTP_ADDR: smtp-relay
    GITEA__mailer__SMTP_PORT: 25

Beispiel: Backup-Script (Shell)

#!/bin/sh
# backup-notify.sh

SMTP_HOST="smtp-relay"
SMTP_PORT="25"
FROM_EMAIL="backup@example.com"
TO_EMAIL="admin@example.com"

# E-Mail senden mit sendmail oder msmtp
echo "Subject: Backup Status
From: $FROM_EMAIL
To: $TO_EMAIL

Backup completed successfully at $(date)" | \
  nc $SMTP_HOST $SMTP_PORT

7. Monitoring & Troubleshooting

Health Checks

# Container-Status prüfen
docker ps | grep smtp-relay

# Postfix-Status
docker exec smtp-relay postfix status

# Mail-Queue prüfen
docker exec smtp-relay mailq

Logging

# Live-Logs anzeigen
docker logs -f smtp-relay

# Letzte 50 Zeilen
docker logs --tail 50 smtp-relay

# Nur Fehler
docker logs smtp-relay 2>&1 | grep -E "(error|reject|warning)"

Häufige Probleme & Lösungen

Problem Ursache Lösung
Connection refused Service nicht im smtp-internal Network docker network connect smtp-internal [container]
Sender address rejected Falsche Sender-Domain Sender auf @example.com ändern
Rate limit exceeded Zu viele E-Mails Queue prüfen, Rate-Limit anpassen
Relay access denied IP nicht in MYNETWORKS Subnet-Konfiguration prüfen
Messages stuck in queue Mail-Server nicht erreichbar Relay-Verbindung prüfen

Test-E-Mail senden

# Aus einem verbundenen Container
docker exec [service-container] sh -c '
  echo "Subject: Test
From: test@example.com
To: admin@example.com

Test email from SMTP relay" | nc smtp-relay 25
'

# Oder mit msmtp/sendmail
docker exec [service-container] sh -c '
  echo "Test message" | \
  mail -s "Test" -S smtp=smtp-relay:25 admin@example.com
'

Queue-Management

# Queue anzeigen
docker exec smtp-relay mailq

# Alle E-Mails erneut versuchen
docker exec smtp-relay postqueue -f

# Spezifische E-Mail löschen
docker exec smtp-relay postsuper -d [QUEUE_ID]

# Alle E-Mails löschen (Vorsicht!)
docker exec smtp-relay postsuper -d ALL

8. Fazit & Best Practices

Zusammenfassung

Ein zentrales SMTP-Relay löst das fundamentale Problem der E-Mail-Zustellung aus Docker-Containern elegant und sicher. Durch die Kombination aus Netzwerk-Isolation, Domain-Whitelisting und Rate-Limiting entsteht eine robuste Lösung für produktive Umgebungen.

Vorteile im Überblick:
  • Zentrale Verwaltung: Ein Konfigurationspunkt statt dutzender
  • Erhöhte Sicherheit: Mehrschichtiges Security-Konzept
  • Vereinfachte Integration: Keine Credentials in Services nötig
  • Besseres Debugging: Ein Ort für alle E-Mail-Logs
  • Skalierbarkeit: Einfach neue Services hinzufügen
  • Ressourcen-effizient: ~128MB RAM, minimal CPU

Best Practices

Empfehlungen für den Produktivbetrieb:
  1. Eigenes Subnet: Verwenden Sie ein dediziertes Subnet für das SMTP-Network
  2. Rate-Limiting anpassen: Starten Sie konservativ und erhöhen Sie bei Bedarf
  3. Monitoring einrichten: Überwachen Sie Queue-Länge und Zustellungszeiten
  4. Log-Rotation: Konfigurieren Sie Docker Log-Rotation
  5. Health Checks: Nutzen Sie Docker Health Checks für Alerting
  6. Regelmäßige Updates: Halten Sie das Postfix-Image aktuell

Erweiterungsmöglichkeiten

  • DKIM-Signierung: E-Mails im Relay signieren für bessere Zustellbarkeit
  • Prometheus Metrics: Postfix-Exporter für detailliertes Monitoring
  • Multiple Relays: Load-Balancing für High-Availability
  • TLS zum Mail-Server: Verschlüsselung der Relay-Verbindung
  • Outbound-Queue-Retention: Längere Speicherung bei Ausfall

Wann ist diese Lösung geeignet?

Geeignet für Weniger geeignet für
Self-hosted Infrastrukturen Externe Cloud-Services (nutzen deren SMTP)
Multiple Docker-Services mit E-Mail-Bedarf Einzelne Container mit einfacher Konfiguration
Umgebungen mit Network-Isolation Flache Netzwerke ohne Segmentierung
Eigener Mail-Server (Mailcow, Postfix) Ausschließlich externe SMTP-Provider