Docker is the modern way for distribute applications. It allows you to create a deployable entity that will run in the same way on almost every *unix platform without the need to install anything more than same basic dependencies required by Docker itself. An ideal choice to run a code sample, a testing environment or your production application. Let’s see how to use it to run a simple Perl script.
You can think about Docker as a lightweight virtualization technology. It uses a combination of the host kernel, a chroot and a network stack to run your application inside an isolated environment (called “container”) where almost everything is under control. This way you can deploy your application wherever you want.
A running Docker container is always based on a Docker image that is usually a minimal Linux distribution. In this environment you can install the libraries your application needs to run. A Docker images is created with the help of a so called “Dockerfile”, a simple sequence of instructions that will be executed to transform a basic image into something you will use.
So stop talking and let’s see some code.
A first Docker Perl test run
In this article we are going to create a simple container to run a simple Perl script, something that can be used to do more complex things next time: we will do nothing more that downloading a web page using LWP::UserAgent. For convenience we will use the official Perl Docker images from Docker Store.
The simplest way to use Docker is to run directly something. So, after installing Docker on your computer, we can run something like this:
docker run --rm perl:latest perl -e 'print $], "\n"'
This will take some time because docker will first download all needed images “layers” and decompress them on your system. But don’t worry, this will be done only once. As a result you will see the the Perl version printed on your shell.
Some explanation needed?
The Docker “run” command used to run something inside the container and is probably the most used command.
The “–rm” option will remove the container when the command has finished. Otherwise Docker will keep the container alive in a stopped status to further use, but we don’t want this now.
After the command and the command options we have the image that we want to run that is “perl:latest” in our case. As already seen if the image is not present on your system Docker will connect to the official public image repository and will try to pull it.
And finally we have the command we want to run inside the container. For now we have run a simple inline script that prints Perl’s version.
Building a custom image
Now, back to our target: downloading a web page. Using the acquired knowledge we could try to run this oneliner:
docker run --rm perl:latest perl -e 'use LWP::UserAgent; print LWP::UserAgent->new->get("http://caribe.cf/")->decoded_content, "\n"'
Would be nice, but unfortunately the basic Perl image has no LWP::UserAgent installed. So it’s time to build our first custom image.
Theoretically we could use the “run” command to launch a sequence of instructions to install LWP::UserAgent using cpanminus and then executing the Perl oneliner, but this will eventually happen every time we run our code. So let’s do it the right way.
To build a Docker image we need a Dockerfile that is a simple sequence of instruction. In our case something very simple like this:
FROM perl:latest RUN cpanm LWP::UserAgent
For your convenience you should create a folder and put the Dockerfile in it. Now we are ready for our first build!
docker build -t perl-with-lwp .
The “-t” option will tag the image with the given string, use it to make your life easier.
The final dot is the build context, that is the current external folder during the image building process.
After cpanminus has done his work you can check the existence of your brand new image using “docker images”. Maybe the size of the image will be a bit more as desired (~900 MB) but we will not care about it in this article.
Now we can resume our previous attempt of downloading a page and modify it using the image we have created. You have only to replace the “perl:latest” image with our “perl-with-lwp” image.
docker run --rm perl-with-lwp perl -e 'use LWP::UserAgent; print LWP::UserAgent->new->get("http://caribe.cf/")->decoded_content, "\n"'
Replacing the one liner with a script file
So far so good, but now we can make things a little more complicated to have a more useful template that can be used for our projects.
Running simple one liners is great, but usually you have a much more complicated script to be executed, usually stored in a PL file. With Docker we have two ways to manage this need.
In the first case we can copy the script inside the image and then execute it. Your Dockerfile will look something like this:
FROM perl:latest RUN cpanm LWP::UserAgent COPY script.pl /root/script.pl CMD perl /root/script.pl
The “COPY” instruction will copy the file from the context folder to the root folder inside the image.
The “CMD” instruction is the default command for this image.
Now create a script.pl file with a few rows of Perl
use strict; use LWP::UserAgent; my $ua = LWP::UserAgent->new; my $res = $ua->get('http://caribe.cf'); print $res->decoded_content, "\n";
Now rebuilding the image relaunching the same build used previously and try to run this:
docker run --rm perl-with-lwp
We don’t need to specify anything after the image name because of the default command defined in the Dockerfile. It works and make sense if you want to build an image that will be used as is.
But if you want to adopt a more generic approach we need to use Docker “volumes”. A volume is a file, or more commonly a folder, that is mounted inside the container.
So create a folder somewhere on your system and place “script.pl” inside it. Then revert the Dockerfile to the previous 2-lines version and rebuild the image again.
This time the “run” will be a bit longer.
docker run --rm -v /path-to-your-folder/:/root/scripts/ perl-with-lwp perl /root/scripts/script.pl
The “-v” options (stands for “volume”) says Docker to mount the system’s folder on the path specified after the column. This way we can run the script inside the folder located in the container.
This approach allows you to create an environment where you run Perl scripts without the need of Perl on your system. You can build images for specific Perl version or images with a specific set of installed modules. So any other system only needs Docker to run it. Wow!