Mik
Mik

Reputation: 453

How do I set up my Dockerfile to use cpanm to install a specific version of a Perl module?

Within my Dockerfile, I am setting up the Perl modules that will be installed when run, like so:

RUN ["cpanm", "Carp", "Carp::Heavy", "Class::Data::Inheritable"]

However, for one module, I need a specific version of a module, not the latest one. How can I specify that version in the above line?

I've been searching online for hours, and haven't turned up anything useful yet.

Upvotes: 8

Views: 6207

Answers (4)

Eugen Konkov
Eugen Konkov

Reputation: 25153

To specify target module version you can use

cpanm MIYAGAWA/Plack-0.99_05.tar.gz              # full distribution path
cpanm http://example.org/LDS/CGI.pm-3.20.tar.gz  # install from URL
cpanm ~/dists/MyCompany-Enterprise-1.00.tar.gz   # install from a local file

See official documentation: https://metacpan.org/dist/App-cpanminus/view/bin/cpanm

But better, to my mind, would be to use cpanfile. See --cpanfile option https://metacpan.org/dist/App-cpanminus/view/bin/cpanm#-cpanfile and format of this file https://metacpan.org/pod/cpanfile

But if you have many modules (like me), I recommend to use cpm. It installs modules in parallel very fast. Also with help of docker we could cache builds, thus rebuilds will takes seconds. Here is my Dockerfile:

## Modules
WORKDIR ${APP_ROOT}

# install modules outside of WORKDIR, so it will not interfere when we do COPY . .
RUN  mkdir -p ../modules
RUN  ln -s ../modules local

RUN  cpanm -n -L ./local App::cpm Carton::Snapshot  && rm -rf /root/.cpanm
COPY cpanfile ./
COPY cpanfile.snapshot ./
RUN  \
  --mount=type=cache,target=/root/.perl-cpm   \
  cpm install  -w 16  --no-test  -L ./local   \
  --with-develop


# regenerate cpanfile.snapshot
# https://github.com/miyagawa/Carmel#cpm
# cpm doesn't have the ability to manage cpanfile.snapshot file on its own.
RUN  carton install
# You can copy snapshot from container by running:
# docker cp <container_name>:${APP_ROOT}/cpanfile.snapshot.latest ./cpanfile.snapshot

Upvotes: 0

Mik
Mik

Reputation: 453

For anyone who's searching for this same answer in the future, another option can be found here in the documentation for cpanm:

cpanm [email protected]

If you have a long list of modules, consider feeding a cpanfile into cpanm rather than listing them all in the Dockerfile.

The easiest way to specify a particular version number for a module in a cpanfile is like this:

requires 'Text::ParseWords', '==3.1';

The syntax for requesting the latest version of a module is this:

requires 'Text::ParseWords';

Requesting a minimum version: (note the lack of '==')

requires 'Text::ParseWords', '3.1';

The syntax for requesting specific versions in other ways is fairly well-documented here.

Another great write-up of the use of cpanm and a cpanfile can be found in Installation of cpan modules by cpanm and cpanfile.

Upvotes: 8

Sinan &#220;n&#252;r
Sinan &#220;n&#252;r

Reputation: 118138

Instead of specifying a module name, specify a URL. Eg, instead of Class::Data::Inheritable, use https://cpan.metacpan.org/authors/id/T/TM/TMTM/Class-Data-Inheritable-0.06.tar.gz

You can find the applicable URL by going to the module page on metacpan, selecting the version you want, and copying the download link.

PS: You might want to also set PERL_CPANM_OPT=--from https://cpan.metacpan.org/ in the environment so cpanm only downloads using HTTPS.

Upvotes: 7

Camilo Silva
Camilo Silva

Reputation: 8721

To have CPAN install a specific version of a module, you need to provide the full module distribution filename including the author. For example to install the module Set::Object version 1.28, at the command line type:

cpan SAMV/Set-Object-1.28.tar.gz

Same thing apply with Docker, just add

RUN cpan SAMV/Set-Object-1.28.tar.gz

Upvotes: 4

Related Questions