Download - Docker perl build
What's on your box?
Pre-compiled perl distros are terrible.
Bulky, slow, with annoying dependencies.
Not what you need...
Example: Red Hat Enterprize 7.0
5.16 == “end of life”
Doptimize=O2 g pipe fstackprotectorstrong mtune=generic Dversion=5.16.3 Dmyhostname=localhost Dperladmin=root@localhost Dusethreads Duseithreads Ubincompat5005
Example: Red Hat Enterprize 7.0
5.16 == “end of life”
Not exactly built for speed.
Doptimize=O2 g pipe fstackprotectorstrong mtune=generic Dversion=5.16.3 Dmyhostname=localhost Dperladmin=root@localhost Dusethreads Duseithreads Ubincompat5005
Example: Red Hat Enterprize 7.0
5.16 == “end of life”
Not exactly built for speed.
Thread overhead, even if you don't use them.
Doptimize=O2 g pipe fstackprotectorstrong mtune=generic Dversion=5.16.3 Dmyhostname=localhost Dperladmin=root@localhost Dusethreads Duseithreads Ubincompat5005
Try it, you'll like it...
Bad approach: virtual machines...
and version-dirs...
and recompiling for each distro, architecture...
and symlink hell(2)...
…
Tasty alternative: lxc
Essentially an LPAR – we've come full circle.
Use a process to isolate & localize code.
Share the kernel.
Light weight, fast startup, easy to ship.
Fly in the soup
Ever try to use lxc?
Let alone finish the manpages?
Kills my appetite.
RTFMlxc-attach.1lxc-autostart.1lxc-cgroup.1lxc-checkconfig.1lxc-checkpoint.1lxc-clone.1lxc-config.1lxc-console.1lxc-create.1lxc-destroy.1lxc-device.1lxc-execute.1lxc-freeze.1lxc-info.1lxc-ls.1lxc-monitor.1lxc-snapshot.1lxc-start-ephemeral.1lxc-start.1lxc-stop.1lxc-top.1lxc-unfreeze.1lxc-unshare.1lxc-user-nic.1lxc-usernet.5lxc-usernsexec.1lxc-wait.1lxc.7lxc.conf.5lxc.container.conf.5lxc.system.conf.5
Docker: MRE for linux
80/20 of lxc:
Layered filesystem + Repository + Command line.
More nutritious than exciting.
Still evolving.
Catch: Docker's doc is fattening!
Start with full Ubuntu image.
1.6GiB – Heart attack on a plate!
Includes X11 libs, lvm, mdadm, grub, parted... perl.
Q: How can we put docker on a healthy diet?
Start with something lighter-weight underneath?
Keep less of it in the container?
Well... since this is about perl:
A: There is more than one way to do it.
Build perl on a light[er] weight O/S.
Single package for perl + shared libs.
Shell tools available for qx{...}.
Still pretty heavy-weight.
A: There is more than one way to do it.
Copy perl on top of busybox.
Much leaner cuisine.
Decent collection of shell tools.
Shared lib's as layer or via -v.
A: There is more than one way to do it.
Just perl
Minimal for distribution of local perl.
Lacks tools to inspect the build.
A: There is more than one way to do it.
Just the application.
No empty calories.
Requires local perl for distributed use.
Start by getting docker.
They provide shell code for the basics:
$curl -sL https://get.docker.io/ | sh;
$wget -qO- https://get.docker.io/ | sh;
will do the deed on Fedora, Ubuntu/Debian, or Gentoo.
Avoids issues with apt/yum, not much value with emerge.
Need to validate kernel configs.
Be yourself
Don't run as su!
Add your users to “docker” in /etc/group.
After that check that docker is running:
$ docker ps;
Get access to the repository:
$ docker login;
Just a taste...
Minimal base container: busybox.
Good for experimenting:
$ docker pull busybox
Pulling repository busybox
fd5373b3d938: Download complete
...
f06b02872d52: Download complete
Getting inside the box
/bin/sh is default entrypoint:
$ docker run -t -i busybox;
# <-- su in box, login id out.
# ping 8.8.8.8; <-- network available.
...
# exit; <-- exit docker process
$ <-- original EUID
Gentoo is easy to dockerize
Common solution is a “stage-3” system.
Shell + libs + build tools.
Not much else.
About half the size of Ubuntu.
Finding a distribution
Start at the docker registry
https://registry.hub.docker.com/Looking for stage-3 builds:
https://registry.hub.docker.com/search?q=gentoo+stage3
I find:
jgkim/gentoo-stage3 741.2 MB
Reasonable start.
Grabbing an O/S
Get the image:
$ docker pull jgkim/gentoo-stage3;
Run a container:
$ docker run –rm -i -t jgkim/gentoo-stage3;
# gcc --version;
gcc 4.8.4 good supports “--arch=native”
Building a perl container
Github has templates:
http://github.com/Perl/docker-perl
Dockerfiles like “5.020.000-64bit/Dockerfile”.
git acquires “5.020.0-64bit-optimized” directory.
FROM buildpack-deps # parent container
RUN apt-get update && apt-get install -y curl procps # commands to pull perl
RUN mkdir /usr/src/perl
WORKDIR /usr/src/perl # build dir within the container
RUN curl -SL http://www.cpan.org/src/5.0/perl-5.20.0.tar.gz | tar -xz --strip-components=1
RUN ./Configure -Duse64bitall -des \
&& make -j$(nproc) && TEST_JOBS=$(nproc) make test_harness \
&& make install && make veryclean
WORKDIR /root
CMD ["perl5.20.0","-de0"] # /bin/sh perl5.20.0 -de0
Distro's Dockerfile
Check the local arguments
$ perl -V;...
config_args='-de -Dprefix=/opt/perl/5.20 -Doptimize=-O3 -march=native -pipe'
perl -MConfig -E 'say $Config{ config_args }'
New DockerfileFROM jgkim/gentoo-stage3MAINTAINER Steven Lembark <[email protected]>WORKDIR /var/tmp/
RUN wget -O – http://www.cpan.org/src/5.0/perl-5.20.2.tar.gz \| gzip -dc tar | tar xf -;
RUN cd perl-5.20.2 && Configure -de -Dprefix=/opt/perl \-Dman1dir=none -Dman3dir=none \-Doptimize='-O3 -march=native -pipe' ;
RUN make -C perl-5.20.2 all test install distclean;
RUN /opt/perl/bin/h2ph -r -a -l;
CMD [ "/opt/perl/bin/perl", "-d", "-E", "42" ]
Building Perl
The build takes input and optional repository tag.
Input is a directory not “Dockerfile”
$ cd /scratch/docker/gentoo+perl;
$ docker build –tag='lembark/perl-gentoo' . ;
Each step in the Dockerfile is an intermediate image.
Checking local containers
Intermediate images labeled with “<none>”.These were from prior tests.
This one didn't finish:$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE<none> <none> 5906d8edbb59 10 minutes ago 726.1 MB<none> <none> 10f5517fcada 23 minutes ago 726.1 MB<none> <none> 7d328e761704 26 minutes ago 725.5 MB<none> <none> 88f1e41aaed5 27 minutes ago 725.5 MB<none> <none> 28052ace7e04 28 minutes ago 725.5 MB<none> <none> 6f46836220d9 31 minutes ago 725.5 MB
$ docker build --rm=false –tag=lembark/gentoo-perl .;Step 0 : FROM rndevfx/gentoo-stage3-amd64-nomultilib ---> e9d0ce66148cStep 1 : MAINTAINER Steven Lembark ---> Using cache <-- recycled image ---> 41d5480e49e7Step 2 : WORKDIR /var/tmp ---> Using cache ---> 010d3d70ced1...
Step 7 : RUN make all test install; <-- first execution is here. ---> Running in 949c9ddfc2efStep 8 : RUN /opt/perl/bin/h2ph -r -a -l; ---> Running in b084569e8fc3-r and -a options are mutually exclusiveINFO[1342] The command [/bin/sh -c /opt/perl/bin/h2ph -r -a -l;] returned a non-zero code
oops...
True Lazyness
More re-cycled images:
---> Using cache ---> cb4c5cd0607e
Step 8 : RUN /opt/perl/bin/h2ph -r -l /usr/include; ---> Running in 92efee8c31e2require '_h2ph_pre.ph';...
And impatience
$ time docker build --rm=false --tag=lembark/perl-gentoo .Sending build context to Docker daemon 4.096 kBSending build context to Docker daemonStep 0 : FROM rndevfx/gentoo-stage3-amd64-nomultilib...
Step 10 : CMD [ “/opt/perl/bin/perl” ] ---> Using cache ---> f7b83ecbe276Successfully built f7b83ecbe276
real 0m0.241suser 0m0.019ssys 0m0.012
Docker Images:
REPOSITORY VIRTUAL SIZElemark/gentoo-perl 884.4 MBjgkim/gentoo-stage3 741.2 MBlocalhost:5000/lembark/busybox 1.9 MB
Successful build: tagged image
Welcome to perl
“CMD” gets run with an interactive container:
$ docker run –rm -i -t lembark/gentoo-perl;Loading DB routines from perl5db.pl version 1.44Editor support available....
main::(-e:1): 0 DB<1> x $^Vv5.20.2
Choose your toppings
Default for gentoo run /bin/bash <your command>.
Save typing with:
ENTRYPOINT [ “/opt/perl/bin/perl” ]
CMD [ "-d", "-E", "42" ]
Use –entrypoint='/bin/bash' if perl fails.
The next course
Stacked images inherit the ENTRYPOINT:
FROM lembark/gentoo-perl
CMD [ "/path/to/your/program" ]
runs
/opt/perl/bin/perl /path/to/your/program;
Test containers stack
Derive tests from the package.
Add ./t to another image.
WORKDIR [ “/path/to/your/code” ]
CMD [ "/opt/perl/bin/prove" ]
Result: no tests in product image:
docker run foo/bar; run application.
docker run foo/bar-test; run base tests.
Minimizing virtual size
Cannot remove inter-RUN space.
884.4 MB includes 100MB of /var/tmp/perl-5.20.2.
Avoiding it requires a single RUN.
No caching of intermediate steps.
Final size 787.8 MB.
Best for final construction.
Minimal Virtual Size: single "RUN" commandFROM jgkim/gentoo-stage3MAINTAINER Steven Lembark <[email protected]>WORKDIR /var/tmp/
# better yet, put this in a shell script and RUN ./build-perl! RUN wget -O – http://www.cpan.org/src/5.0/perl-5.20.2.tar.gz \| gzip -dc tar | tar xf - \&& cd perl-5.20.2 \&& Configure -de -Dprefix=/opt/perl \
-Dman1dir=none -Dman3dir=none \-Doptimize='-O3 -march=native -pipe' \
&& make all test install distclean \&& cd .. && rm -rf 5.20.2 ;
RUN /opt/perl/bin/h2ph -r -a -l;ENTRYPOINT [ "/opt/perl/bin/perl" ]CMD [ "-d", "-E", "42" ]
In most cases there is still a better way.
Note: You already have a local O/S.
Q: Why add another one to the container?
A: Because we are all used to virtual machines.
Time to reduce the calories...
Copy perl on top of busybox
Build & install into /opt/perl.
/opt/perl/Dockerfile
FROM lembark/busybox_x86
COPY [ “.”, “/opt/perl” ]
ENTRYPOINT [ “/opt/perl/bin/perl” ]
CMD [ , “-d”, “-E”, “0” ]
Check build: docker run –entrypoint='/bin/sh'
Nice combination
Useful shell tools for "qx".
/bin/sh in case of broken build.
Smaller package: REPOSITORY VIRTUAL SIZE
lembark/busybox-perl 67.5 MB
lembark/gentoo-perl 787.8 MB
jgkim/gentoo-stage3 741.2 MB
localhost:5000/lembark/busybox 1.9 MB
Local dir with modules
/opt/perl/5.20/Dockerfile for bare copy of perl:
$ docker build –tag='lembark/perl-5.20' /opt/perl/5.20;
FROM /lembark/busyboxMAINTAINER Steven Lembark <[email protected]>
COPY [ ".", "/opt/perl/5.20" ]WORKDIR /var/tmpENTRYPOINT [ "/opt/perl/5.20/bin/perl" ]CMD [ "-d", "-E", "0" ]
Portion control for perl
What if you don't want CPAN::Reporter in Docker?
A: Keep a “docker-perl” install.
Extract stage3 into /scratch/docker-build.
Build perl “chroot /scratch/docker-build”.
Single /opt/perl with vetted modules.
Works for just about anything.
Nothing artificial, nothing added
Skip the Dockerfile: import a tarball.
"—change" inserts Dockerfile syntax into image.
cd /opt/perl; find . | cpio -ov -Htar |
docker import –change=”VOLUME /lib64” \
--tag=”lembark/perl-5.20.2”;
Minimal base for Plack server.
Essential ingredients
Catch, this won't run as-is: since perl needs shared libs.
In my case, from /lib64.
Q: Where to get them without O/S image?
One way: Share libs
Run containers with read-only mount of /lib64:
docker run -v /lib64:/lib64:r …
Light-weight.
Fast: No images to ship.
Requires homogeneous lib's for distributed use.
Or "-v /var/tmp/$$:/var/tmp"
One way: bundle libs
“ldd” lists shared libs:
COPY them into the image with perl.
Build lib64 image from perl – order doesn't matter. linux-vdso.so.1 (0x00007ffdfbbcb000)libperl.so => /opt/perl/5.20/lib/5.20.2/x86_64-linux/CORE/libperl.so
(0x00007f40f8868000)libnsl.so.1 => /lib64/libnsl.so.1 (0x00007f40f8650000)libdl.so.2 => /lib64/libdl.so.2 (0x00007f40f844c000)libm.so.6 => /lib64/libm.so.6 (0x00007f40f8153000)libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f40f7f1c000)libutil.so.1 => /lib64/libutil.so.1 (0x00007f40f7d19000)libc.so.6 => /lib64/libc.so.6 (0x00007f40f7981000)/lib64/ld-linux-x86-64.so.2 (0x00007f40f8c2b000)
Zero protein pill
Use "-v" to add /lib4 and /opt/perl.
Image: Single #! script to start the application.
Images are a few KB.
Requires homogenous install of perl, application.
One way: static perl
Build perl & modules “--static”.
No hetergenious server issues.
perl image is larger.
Best for tests: no issues with underlying images.
Result: portable, optimized, minimal perl.
Static perl with busybox: 68 MB.
Whole lot less than Ubuntu.
Not a virtual machine.
Plack web server FROM this perl.
Viola!, you're up.
What did all of this get us?
Mainly an optimized, current perl.
With all [and only] the modules you need.
You also save the overhead of shipping an O/S image.
Faster startup.
Easier updates.
Simpler deployment.
SummaryDocker makes lxc approachable.
You don't always need a full O/S distro in the container.
perl on busybox makes a tasty, low-calorie alternative.
Use “-v” to import /lib64 for a full meal.
Even testing gets simpler: derive tests from package.
Say goodby to brewing perl, managing multiple versions.