MailCatcher in Docker

In previous articles, we discussed email testing and using a fake SMTP server to catch emails. This article will show you how to set up a Docker container to host MailCatcher, a simple fake SMTP server.

Why is Docker a good set-up option for MailCatcher?

  • Independent
    MailCatcher is an isolated and independent component with no dependencies. It makes sense to stand up an individual container to handle this.
  • Reusable
    MailCatcher can be used to service any number of applications.
    Depending on your use case, you may want to set up multiple containers (with different ports) to separate the apps. It is easy to duplicate an existing Docker image into a new container.

So, if you already using Docker, then MailCatcher-in-Docker is a quick and easy setup.

Setting up MailCatcher

The general steps to set up and run MailCatcher:

  1. Install Ruby
  2. Install the gem mailcatcher
  3. Run mailcatcher
  4. Verify MailCatcher is running
    View mail at localhost:1080
    Send mail to localhost:1025

Creating the Dockerfile

1. Install Ruby

This could be done the “classic” way (pulling down a Ubuntu image, running command/s to install Ruby, etc).

Luckily, we can skip all that by pulling down the official Ruby Docker image (ruby).

FROM ruby

Translating the rest of the setup steps is quite easy.

2. Install MailCatcher

In the dockerfile, use RUN to execute:

RUN gem install mailcatcher --no-document

The no-document flag means that the documentation for mailcatcher will not be installed. Since this is inside a container we do not need the documentation anyway.

3. Set the path

Gems are installed in the location /usr/local/bundle/bin. Set the container’s PATH env var to include this path, otherwise mailcatcher won’t be found.

ENV PATH=/usr/local/bundle/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

4. Expose ports 1080 and 1025 to the outside

EXPOSE 1080/tcp
EXPOSE 1025/tcp

5. Start MailCatcher with the container

When the container starts, MailCatcher should too.

CMD mailcatcher --foreground --ip=0.0.0.0

Options:

  • foreground — Runs as a daemon in the foreground.
  • ip=0.0.0.0 — Set the IP address.

6. Build the Dockerfile and run the container

Build and tag the image as mailcatcher:

docker build -f Dockerfile . -t "mailcatcher"

Output:

$ docker build -f Dockerfile . -t "mailcatcher"
[+] Building 3.2s (6/6) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 159B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/ruby:latest 3.0s
=> [1/2] FROM docker.io/library/ruby@sha256:74f02cae856057841964d471f0a54a5957dec7079cfe18076c132ce5c6b6ea37 0.0s
=> CACHED [2/2] RUN gem install mailcatcher --no-document 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:8d2e764ae9d861de033a6ea73575df5536102b537b51655f83b6eb1da1c33bd9 0.0s
=> => naming to docker.io/library/mailcatcher 0.0s
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them

Run the mailcatcher container:

docker run -it -d -p 1080:1080 -p 1025:1025 --name mailcatcher mailcatcher

And tada! The container mailcatcher will have started.

If you visit localhost:1080, MailCatcher is up and running.

Testing receiving emails

I configured WhenWise’s local environment to use 127.0.0.1:1025 for mail.

config.action_mailer.smtp_settings = { :address => "localhost", :port => 1025 }

After mail gets sent to port 1025, it can then be viewed at port 1080. Example screenshot of an email sent by the app on MailCatcher:

The Mailcatcher UI to see the “received” emails.

Complete Dockerfile

FROM rubyRUN gem install mailcatcher --no-documentENV PATH=/usr/local/bundle/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binEXPOSE 1080/tcp
EXPOSE 1025/tcp
CMD mailcatcher --foreground --ip=0.0.0.0

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store