TechEarl

How to Run Mailpit in Docker (Local Email / SMTP Testing)

Catch and inspect emails your local app sends without bothering a real inbox. Mailpit in Docker gives you an SMTP server on 1025 and a web UI on 8025 — the modern replacement for unmaintained MailHog.

Ishan KarunaratneIshan Karunaratne⏱️ 5 min readUpdated
Share thisCopied

If your app sends email — password reset flows, notifications, the contact form — you don't want it hitting a real inbox in development. The standard solution is a local SMTP server that accepts everything and shows you the messages in a web UI. Mailpit is the modern pick: actively maintained, multi-platform, one Docker container, no config required.

How do I run Mailpit in Docker?

bash
docker run -d --name mailpit \
  -p 1025:1025 -p 8025:8025 \
  axllent/mailpit

That's it. Point your app's mailer at 127.0.0.1:1025 and open the web UI at http://localhost:8025. Every email your app sends shows up there.

Try it with your own values

Configure container name and ports.

Why Mailpit and not MailHog

MailHog was the dev-SMTP standard for years. Its last release was in 2020, and it's been unmaintained since. Mailpit is the spiritual successor by the same kind of community — same ports by default (1025 SMTP, 8025 UI), same role, but maintained, faster, multi-architecture, supports modern features (HTTPS, OAuth in the UI, basic POP3 if you need it).

For new setups: Mailpit. For existing setups using MailHog: the swap is one image and possibly no config change.

Practical usage: point your app at it

Node.js (Nodemailer):

javascript
import nodemailer from 'nodemailer';

const transporter = nodemailer.createTransport({
  host: '127.0.0.1',
  port: 1025,
  secure: false,
  // no auth — Mailpit accepts anything in dev
});

await transporter.sendMail({
  from: 'app@localhost',
  to: 'user@example.com',
  subject: 'Hello from Mailpit',
  text: 'It worked.',
});

Python (smtplib):

python
import smtplib
from email.mime.text import MIMEText

msg = MIMEText('It worked.')
msg['From'] = 'app@localhost'
msg['To'] = 'user@example.com'
msg['Subject'] = 'Hello from Mailpit'

with smtplib.SMTP('127.0.0.1', 1025) as s:
    s.send_message(msg)

Laravel — set in .env:

code
MAIL_MAILER=smtp
MAIL_HOST=127.0.0.1
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=app@localhost

Djangosettings.py:

python
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = '127.0.0.1'
EMAIL_PORT = 1025
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
EMAIL_USE_TLS = False

After hitting send in any of these, refresh the web UI at http://localhost:8025 and the message is there with headers, plain-text body, HTML body, and raw source.

In Compose, with another service

yaml
services:
  app:
    image: my-app
    environment:
      SMTP_HOST: mailpit
      SMTP_PORT: 1025
    depends_on:
      - mailpit

  mailpit:
    image: axllent/mailpit
    ports:
      - "::smtp_port:1025"
      - "::ui_port:8025"
    restart: unless-stopped

From inside the app container, Mailpit is reachable as mailpit:1025. You only need to publish ports to the host if you want to access the SMTP server or the UI from outside Docker.

Persistence (optional)

Mailpit stores messages in memory by default — docker restart mailpit wipes them. For most dev use that's fine. If you want messages to survive restarts:

bash
docker run -d --name :container_name \
  -p :smtp_port:1025 -p :ui_port:8025 \
  -e MP_DATABASE=/data/mailpit.db \
  -v mailpit-data:/data \
  axllent/mailpit

MP_DATABASE tells Mailpit to use an on-disk SQLite database; the named volume persists it.

Common pitfalls

  • Port 1025 already in use. Another SMTP service (or another MailHog/Mailpit). Pick a different host port for the container's 1025.
  • Connecting from another container with 127.0.0.1. Doesn't work — that's the calling container's loopback. Use the Compose service name (mailpit) or the Docker network alias.
  • No emails appearing in the UI. Almost always wrong port or host in the app's SMTP config. Confirm with nc -vz 127.0.0.1 1025 from where the app runs; Mailpit responds with its SMTP banner.
  • TLS/auth errors. Mailpit accepts unencrypted, unauthenticated SMTP by default — perfect for dev. If your app forces TLS, either disable it for dev or configure Mailpit with TLS settings.

What to do next

FAQ

Sources

Authoritative references this article was fact-checked against.

TagsDockerMailpitMailHogSMTPEmailDevelopmentDevOps

Found this useful? Pass it on.

Copied
Ishan Karunaratne

Ishan Karunaratne

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years building software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Currently Chief Technology Officer at a healthcare tech startup, which is where most of these field notes come from.

Keep reading

Related posts