<< back

Running mod_perl with Mojolicious in Docker

I've been working under an old Apache mod_perl setup. I wanted to use Mojolicious for some new services, but I needed to stay within mod_perl, so I decided to go all the way and Dockerize it. After scouring the mod_perl documentation, Plack + Mojolicious configs, and finding an image, I hit the ground running and documented my steps.

mod_perl banner

I love old banners :)

Generate your config

Thanks to motemen for some nicely pre-configured mod_perl and Apache2 images. We're targetting Perl v5.36, and Apache 2.4.58 here. We'll also add the include statement for our VirtualHost configuration file that we'll make later.

docker run --rm motemen/mod_perl:5.36.0-2.4.58 cat /usr/local/apache2/conf/httpd.conf > httpd.conf
echo 'Include /usr/local/apache2/conf/mojolicious.conf' >> httpd.conf

This will leave you with a httpd.conf that will get picked up by Apache when we run it under docker.

Enable Prefork MPM instead of Event MPM

I couldn't get Apache to run without disabling Event MPM and enabling Prefork MPM.

In httpd.conf:

#LoadModule mpm_event_module modules/mod_mpm_event.so
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so

Write your application

All you need to do is write a Mojo application. In this case, I'm using Mojolicious::Lite but this can be done with the whole MVC setup easily as well. Just make sure you have a sub that returns your app so you can pass it to Plack::Builder.

In lib/App.pm:

package App;
use 5.036;
use Mojolicious::Lite -signatures;

sub get_app { app; }

get '/' => sub {
    shift->render( text => "Hello World!" );


Write your Plack shim

Here we write a simple .psgi file that will use our App library and Plack::Builder to create a PSGI application for Plack::Handler::Apache2 to pickup.

In app.psgi:

use 5.036;

use lib 'lib';
use App;
use Plack::Builder;

builder {

Write your mod_perl Apache config

Very straight-forward, just tell Apache where to find our script, and what handler to use.

In mojolicious.conf:

LoadModule perl_module modules/mod_perl.so

<VirtualHost *:80>
<Location />
SetHandler perl-script
PerlResponseHandler Plack::Handler::Apache2
PerlSetVar psgi_app /app.psgi

Write your Dockerfile

Now all thats left is making a Dockerfile. We'll use one of motemen's images, and copy all of the pre-reqs over, install some libraries, you know, Docker stuff.

In Dockerfile:

FROM motemen/mod_perl:5.36.0-2.4.58-2.0.13
COPY app.psgi /app.psgi
COPY lib /usr/local/apache2/lib
COPY httpd.conf /usr/local/apache2/conf/httpd.conf
COPY mojolicious.conf /usr/local/apache2/conf/mojolicious.conf
RUN apt-get update -y && apt-get install -y wget make build-essential
RUN cpan -iT Plack Mojolicious
CMD ["httpd-foreground"]

Run with Docker

Now we can make it go!

$ docker build . -t mod-perl
$ docker run -p 80:80 mod-perl
$ curl http://localhost:80/

"Hello World!"

Running with auto-reloading (for development)

You can make this auto-reload if you use a docker volume for lib/ against /usr/local/apache2/lib/

An example?

An example is available on my github.