New Docker Image for the Warp Web Server

Posted on December 12, 2016

TLDR: docker pull yesodweb/warp for some static web server goodness.


Web frameworks and Haskell

In the world of Haskell, you have quite a few web servers and application frameworks to choose from. WAI, the Web Application Interface library is one of those, and Warp is the super-fast web server for WAI applications.

For a variety of reasons, I doubt Warp is all that well known outside the world of Haskell. I hope that changes, and I believe it just got a little bit more possible.

Building Docker images with Stack

Let me digress for a moment. Stack is the fantastic build/package management tool for Haskell. It is very well-designed, and aims to be a helpful companion in your successful experience with Haskell. While writing Haskell code is not (yet) in my daily work, I build and interact with a fair bit of Haskell code. Early in Stack’s development, we were using Stack to build executables, then using a Dockerfile and docker build to create an image with that new executable.. and we eventually realized we could just have Stack do that all for us. Thus, stack image container was born.

There is a section in the project’s stack.yaml to tell Stack what to build, for example:

image:
  containers:
    - base: "fpco/pid1"
      name: "my/image"
      executables:
        - my-app

Stack generates a Dockerfile for each item in the list of images to build. In this case, I tell Stack to use the fpco/pid1 image as the base (sets FROM in the Dockerfile), tags the image with my/image, and adds the executables listed (my-app in this case).

A need for static web servers

Recently, I have been writing a lot of documentation, a little Asciidoc, a lot of markdown and mkdocs. I love simplicity and automation, so it’s only natural to hook up CI with the full pipeline: monitor the git repos and auto build when commits are made, create HTML and static content, package that up as a docker image, and if the build is for the production branch, deploy that image so it’s immediately available and without me needing to do anything more than check that my latest updates are present on the live site. I’ve setup a few of these pipelines, initially for private documentation behind authentication, and more recently for public display. Overall, the pipeline has worked exceedingly well, and I’m proud of the results.

Back to Warp.

I’ve been impressed with it’s simplicity, speed, and reliability (nginx is also great, but I’m tired of configuring it in today’s high-speed and highly-automated operations world). When I needed a static HTTP server for that public (read: no authentication) doc site, I realized Warp’s static app server would be a great fit, but how would I get it into the pipeline?

Well, Warp is Haskell, and Stack builds Haskell, and it builds docker images, so I sent in one of those fantastically simple but wonderfully gratifying pull requests to ensure stack image container could build us an image in a giffy.

The result?

ᐅ docker pull yesodweb/warp
Using default tag: latest
latest: Pulling from yesodweb/warp
e2dba40aea3c: Pull complete
Digest: sha256:0cfe10919a5294aab231d5726799556313e4c4bd592cbe4c6ba05bdb778151db
Status: Downloaded newer image for yesodweb/warp:latest

How to use it?

ᐅ docker run --rm -it                       \
             -v $(pwd):/var/www/html        \
             -p 127.0.0.1:3000:3000         \
	     yesodweb/warp                  \
	     warp --docroot /var/www/html/
Serving directory /var/www/html/ on port 3000 with ["index.html","index.htm"] index files.

Voilà!

Packaging your own Docker image…

Using yesodweb/warp as our base image, we can package some docs into /var/www/html and create a new image with everything needed. That could look like:

FROM yesodweb/warp:latest

# packaged HTML and static site in here
ADD $TARFILE /var/www/html/

# run static web server with warp
CMD warp --port 3000 --docroot /var/www/html/

Run that image!

ᐅ docker run --rm -it my-doc-image
Serving directory /var/www/html/ on port 3000 with ["index.html","index.htm"] index files.