Perl base image for Docker
This base image uses the latest perl official
image as a starting point, and adds
Carton to manage dependencies for your Perl app. This image is updated
Backwards incompatible change: Dockerfiles don't have support for
COPYinstructions. What this means is that we cannot write
a Dockerfile that works differently based on the presence or absence
of a file or directory. To implement the hook system, this image now
requires the project to have a non-empty
directory at the root of your projects.
If you try to build your image and get an error like:
Step 1 : COPY .docker-build-hooks/* /app/ No source files were specified
you need to add the
.docker-build-hooksdirectory, with a file
inside. See the "Quick Start" section for details.
We hope to remove this requirement in the future if the Dockerfile
specification gains support for this, and we apologize for this
backwards incompatibility, we hope the flexibility the new hooks
system provides compensates for this one-time fix.
Create a Dockerfile for your project with just this content:
You also need to create an empty folder for the hooks, even if you don't
use them. On your project, do:
mkdir .docker-build-hooks touch .docker-build-hooks/.keep
You should commit the
to your repository.
.keep is needed because git doesn't version directories,
only files, so an empty directory would not be created when you
clone the repository unless there is a file inside. Also Dockerfile
COPY will fail with empty directories.
The build process will make sure that:
- all dependencies listed in
cpanfileand locked with
carton installlocally on your development
laptop to create the second file) are installed under
- your application is copied to the container under
- the workdir is set to
/appand and all commands run as
- all commands you execute with
docker runare executed within
carton execto make sure your environment is sane, and PERL5LIB will include
/app/lib, which allows you to just use your own application modules
directly without futzing with
More details below in the "Inside the box" section.
Inside the box
The image takes care of the usual boring stuff for all Perl projects
ONBUILD rules. These are executed when your own image is
built. We try to minimize the layer sizes, but at the same time provide
hooks that you can tweak to your needs.
The build process is a sequence of 5 steps or phases, each of those has
associated before and after optional hooks.
You can create an executable file inside the
directory at the root of you project with the correct format, and this
base image will call them in the proper moment. If any of the hooks
exists with status code different from 0, the build process will
The format of the hook files is
<prefix> values are
is defined below for each of the build steps. The
suffix is optional, and it is used to define the order in which multiple
hooks are executed. We
sort the filenames alphanumerically and execute
them in order. Please note that
-10 will be executed before
0-padding like this:
The fist build step is to initialize the hook system. We copy the
contents of the
.docker-build-hooks/ directory to
There is no
before- hook, but you can define a
after- hook using
init-hooks as hook name.
You should use the
after-init-hooks hook to install system packages
that you might need to compile your dependencies afterwards.
apt-get install -y libmagic-dev is required to install
File::LibMagic Perl module.
Your application will be forced to run under the
There are no hooks for this phase.
cpanfile.snapshot are copied from the root of
your project, and we execute
carton install --deployment to install
your Perl dependencies. We cleanup some of the build artifacts that both
cpanm tools create, to make sure your image is as small
Afterwards, we copy all the files from your project into the
CMD you specify is forced to run under
carton exec by using an
There are no hooks for this phase.
How to use
This is a Dockerfile for a simple Dancer app:
FROM melopt/perl-carton-base ## Expose the default Dancer port EXPOSE 3000 ## Start the app! CMD ["./bin/app.pl"]
Build it with the usual
docker build -t my_dancer_app, and run it with
docker run -it -p 3000:3000 my_dancer_app. Update your frontend
nginx/varnish/apache server configuration to use the app port.
For a worker-style Perl app, the Dockerfile is even simpler:
FROM melopt/perl-carton-base ## Start the app! CMD ["./bin/start_worker.pl"]
That's all it takes...
Pedro Melo, email@example.com