Thursday, December 31, 2015

Using a portable SMTP relay server with docker

I have had a very busy year and had the chance to work on a lot of new and useful docker containers. Taking advantage of these holidays, I finally started to catch up here with my latest work on them :D

There's one thing that it's a pretty common requirement of a website: a SMTP email server or relay.
Every web app needs one for different tasks, like sending out notifications, registration emails, password resets, etc. I made a Postfix SMTP relay container that is easy to use with other containers.

Before running the container, first you need to set the following environment variables to configure the SMTP relay host:
  • SMTP_SERVER: Server address of the SMTP server that will send email from our postfix container.
  • SMTP_USERNAME: Username to authenticate with.
  • SMTP_PASSWORD: Password of the SMTP user.
  • SERVER_HOSTNAME: Server hostname for the Postfix container. Emails will appear to come from this hostname domain.
To use it you need to first pull the image:
docker pull juanluisbaptiste/postfix
and then fire it up with the previous variables defined:
docker run -d --name postfix -P \
       -e SMTP_SERVER=smtp.bar.com \
       -e SMTP_USERNAME=foo@bar.com \
       -e SMTP_PASSWORD=XXXXXXXX \
        -e SERVER_HOSTNAME=helpdesk.mycompany.com \        
        juanluisbaptiste/postfix
Lastly, link your container against it:
docker run --name mycontainer --link "postfix:postfix" myimage

Using docker-compose

Or, you could use docker-compose to start your application containers linked against the postfix container with one command. Suppose you have a web application that links against a database and this postfix container. Download and install docker-compose for your platform, and then on your website's docker project, create a new file called docker-compose.yml, and put the following contents there:
myapp:
  build: myapp
  ports:
  - "80:80"
# If running behind a proxy container, expose the ports instead
# and link the proxy container to this one.
#  expose:
#  - "80"
  links:
  - mariadb:mariadb
  - postfix:postfix
  volumes_from:
  - data
mariadb:
  image: centos/mariadb:latest
  expose:
  - "3306"
  volumes_from:
  - data
  environment:
      MYSQL_ROOT_PASSWORD: changeme
postfix:
   image: juanluisbaptiste/postfix:latest
   expose:
   - "25"
  environment:
      SMTP_SERVER: smtp.mycompany.com
      SMTP_USERNAME: user@mycompany.com
      SMTP_PASSWORD: changeme
      SERVER_HOSTNAME: helpdesk.mycompany.com
data:
  image: centos:latest
  volumes:
  - /var/lib/mysql
  - /var/www/webapp

  command: /bin/true
Then, you can launch your webapp, the database and the postfix container with this command:
docker-compose up
All containers will be started in the right order and the webapp will be linked against the mariadb and postfix containers. Also, the webapp and the mariadb database container will share the same data volume container (unrelated to the postfix container but a good practice).

On thing to note, this container doesn't enable client SMTP authentication, the idea is to expose the port 25 to containers, and then link the containers that need a SMTP service against it so the relay isn't publicly exposed.

A note about using gmail as a relay

Since last year, Gmail by default does not allow email clients that don't use OAUTH 2
for authentication (like Thunderbird or Outlook). First you need to enable access to "Less secure apps" on your google settings.

Also take into account that email From: header will contain the email address of the account being used to authenticate against the Gmail SMTP server (SMTP_USERNAME), the one on the email will be ignored by Gmail.

4 comments:

  1. This is going to save me a lot of time/hassle. Can I just ask what do I use to authenticate against the relay?

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. This is awesome!
    Very much appreciated!

    Thank you

    ReplyDelete