This is the seventh post in a series on Modernizing my Personal Web Projects. I mentioned that one of the goals of this project was to revive some of my older projects that tend to get neglected and stop working. So, I went through my GitHub and found an old Perl project that would be perfect to host again. Read on for my experience with migrating Perl projects to Kubernetes.

The project I chose to migrate is gin-rummy-bot, a web-based Gin rummy game and an AI opponent. I became fascinated with Gin while learning poker after coming across the story of Stu Ungar. He had an eidetic memory and won the World Series of Poker main event a record three times. His last win incredibly came sixteen years after his previous win, a feat that will almost certainly never be replicated. But he was also known for being the best Gin rummy player, which he regarded as a more skillful game than Texas Hold’Em.

Anyway, my bot is a simple single-page web app with no JavaScript(!). It has some dependencies on other Perl modules and one of them requires a C library, but otherwise nothing too complex.

Building the Dockerfile

To start with, I used the official Perl image on the Docker Hub. It has an example Dockerfile for use with Carton projects which I took inspiration from. Carton is a dependency manager for Perl and works similarly to Ruby’s Bundler and so on. The initial Dockerfile looked like this:

1
2
3
4
5
6
7
8
FROM perl:5                                                   
RUN cpanm Carton                                   
RUN mkdir /app                                     
WORKDIR /app                                       
COPY cpanfile* /app                                
RUN carton install                                 
COPY . /app                                        
CMD ["carton", "exec", "perl", "-I", ".", "gin.pl"]

Note that the cpanfile is copied before the rest of the working directory. This is for efficiency, since Docker caches the steps – the source code would change frequently and invalidate the cache, while the carton install takes a long time because it needs to download libraries from the network. So it’s better to run carton install first, only when the cpanfile changes, so that it’s usually cached on builds where only the source code is being changed.

I built this with docker build . -t gin-rummy-bot and ran with docker run gin-rummy-bot. This revealed missing dependencies, which I added to the cpanfile until there were no more errors. One of the libraries (File::LibMagic) required the libmagic library, so I had to add that to top of the Dockerfile:

1
2
RUN apt-get update
RUN apt-get -y install libmagic-dev

That did it, and my program was now containerized! The next step was to push to my Docker registry and deploy it to Kubernetes. This happens to be one of my favourite commands:

1
2
export DKR=(registry URL)
k create deployment gin-rummy-bot --image=$DKR/gin-rummy-bot:v0.0.1

Wrapping Up

Since migrating my Perl projects to Kubernetes, I never have to worry about restarting them after server crashes. The cluster keeps them running and makes it easy to publish them to the internet, so they’re easily accessible if I feel like a trip down memory lane…