Containerizing a legacy Perl application like Bugzilla comes with the challenge of managing CPAN modules and other dependencies that the app needs. In 2025, Perl is less common in new apps, but the modules Bugzilla requires may not all be packaged for modern OSs by default. Here are best practices to handle this complex dependency stack:
-
Use a Stable Base Image and Package Manager: Start with a known-good base for your Bugzilla image. Many choose a Perl-specific base image (for example, the official
perlimage on Docker Hub, which is built on Debian or Alpine and includes a specific Perl version). This ensures you have a recent Perl (Bugzilla 5.2 supports Perl 5.24+ typically) and common tools. Using a base like Debian 11 or Ubuntu 20.04 is reasonable, as they still provide packages for many Perl modules. Leverage the OS package manager to install any CPAN modules that are available as packages (these are usually prefixed withlib...-perl). For instance, Bugzilla needs DBI and DBD::mysql â these can often be installed viaapt-get install libdbi-perl libdbd-mysql-perl(providing compiled versions). Similarly, modules like Date::Format, Template-Toolkit, etc., might have Debian packages. Installing those via apt can save you from compiling them and ensures binary compatibility. However, not everything Bugzilla needs will be packaged (or the version might be old), so youâll still use CPAN for the remainder. -
Automate CPAN Module Installation: Non-packaged modules should be installed in the Dockerfile build. A common approach is using cpanminus (
cpanm) along with acpanfilelisting required modules (Bugzillaâs source might include arequirements.txtor documentation of needed modules). You can either manually list out the modules to install or run Bugzillaâs own dependency check script (checksetup.pl) in a mode that installs modules. Bugzilla can be configured to auto-install missing modules via CPAN if you permit it, but in a Docker build you want non-interactive, deterministic installation. Usingcpanmis ideal: it can install from CPAN without prompts and can fail the build if something doesnât install. -
Cache and Layer Dependencies: Building a Perl image from scratch can be time-consuming, especially if it compiles XS modules (C-based components). To optimize, take advantage of Docker layer caching. For example, you might structure the Dockerfile in two stages or layers: (1) a âCPAN buildâ stage that installs all needed Perl modules, and (2) the final stage that copies the installed libraries into a runtime image (if you want to keep the runtime image lean without build tools). Another simpler method is to install everything in one layer but ensure that the layer is only invalidated when dependencies change. You could copy in a file like
cpanfileand then runcpanm --installdeps .(if Bugzilla were set up as a CPAN distribution) or explicitly cpanm each module. The key is to do this before copying your application code, so that changes to the Bugzilla code donât bust the cache of the dependencies. This way, rebuilding the image wonât re-download/recompile CPAN modules every time. -
Consider a âfatâ Base Image: Since you have multiple Bugzilla instances to deploy, it might make sense to build a common base image that has all of Bugzillaâs Perl module dependencies pre-installed. For example, you create
bugzilla-base:5.2image which contains Perl, Apache, and all required CPAN modules, but not the specific site configuration or data. Then for each Bugzilla instance, you have a small DockerfileFROM bugzilla-base:5.2that just adds the Bugzilla configuration (maybe thelocalconfigfile or any branding customizations) and points to the existing modules. This way, the heavy lift of installing modules (which could be dozens of CPAN distributions) is done once. All Bugzilla containers can share that base, saving disk space and build time. It also means if you update a module or Bugzilla version, you do it in one place. The community has embraced similar ideas â for instance, one community image for Bugzilla âprovides a Bugzilla stable version with CPAN modulesâ baked in so that running the container is plug-and-play. You might even use such images as reference or starting points (e.g. thenasqueron/bugzillaimage on Docker Hub includes most dependenciesâ). -
Vendoring Dependencies (Carton): For truly repeatable builds, you can use Carton, a Perl dependency management tool, to lock versions of CPAN modules. Mozillaâs Bugzilla team used Carton to vendor all dependencies for bugzilla.mozilla.org â essentially, they checked in a
cpanfile.snapshotand all the module tarballs. This approach can be excellent for an air-gapped environment because you can bundle all necessary CPAN packages offline. Consider doing a one-time run of Carton to fetch all Bugzilla deps (on a machine with internet), then copy thelocal/liborvendordirectory into your Docker build context. Then your Dockerfile can simply add that directory and your Perl @INC can include it, meaning no internet access is needed to install modules. This makes your build self-contained. The FOSDEM 2018 talk âHow Carton, Docker, and CircleCI Saved my Sanityâ describes how vendoring Perl modules improved reliability for deploying a legacy appâ a relevant insight for 2025 where some CPAN mirrors or modules might disappear or break unexpectedly. -
Slimming the Image: After youâve installed all modules and the application, consider removing unnecessary build tools. For example, youâll likely need
make, compilers, libraries (like openssl dev, mysql client dev) to build certain CPAN modules.ÂInstall them in an earlier step and uninstall them at the end of the Dockerfile (or use multi-stage builds). This reduces the image size and attack surface. Also remove any CPAN build caches that arenât needed at runtime. The final image should contain Perl, the modules, Apache/httpd (if using it), and Bugzillaâs code â but not the entire CPAN build environment.
-
Configuration in the Image: For Bugzilla, youâll run an Apache (httpd) with mod_cgi or mod_perl, or possibly use an alternative like Plack/PSGI. The simplest route is to use Apache with mod_cgi (Bugzilla default) or mod_perl2 for performance. In 2025, mod_perl is still available but can be memory-heavy. If memory is constrained, running under plain CGI or FastCGI might be preferable to keep Apache workers lighter (each mod_perl worker loads the entire app in memory). This is a tuning consideration: mod_perl will speed up Bugzilla responses significantly by preloading Perl modules, but uses more RAM per process. Since you might not have a lot of traffic (assuming these Bugzillas are internal tools), you could stick to CGI which forks a Perl interpreter for each request (slower, but lower constant memory). Itâs a trade-off: if response times are acceptable, CGI is simpler. If you need more speed and have memory headroom, enable mod_perl2 (and ensure to include the
mod_perl2package and Bugzillaâs mod_perl config adjustments). Either way, ensure the Apache config in the container is tuned (limit MaxClients if memory is low, etc.) -
Testing the Build: Because of the CPAN complexity, do thorough testing of the container image. Run Bugzillaâs
checksetup.plinside the container to verify all required modules are seen as installed (it will list any missing ones). Also test functions like sending email (Bugzilla uses sendmail or SMTP â you might use a lightweight send-only SMTP client in the container, like msmtp, configured to relay to your SMTP server). If something doesnât work in the container as it did on a VM, itâs likely a missing dependency or a permission issue.
Handling a legacy tech stack in a modern container requires embracing the mantra: âbuild once, run anywhere.â By pre-building all Perl modules into the container image, you ensure that the runtime environment is consistent and doesnât need internet or manual intervention. This approach has been proven in real-world migrations â teams have found that investing time in setting up the Dockerfile with all dependencies pays off with deployments that âjust workâ in production, even in isolated networks. It can be frustrating to wrestle with CPAN, but with the right strategy (using system packages, cpanminus, and caching layers), you can tame the Perl dependency monster.
Video available:
https://archive.fosdem.org/2018/schedule/event/perl_docker_mozilla/
Â
Â