Top Banner
Thinking inside a box: Dockerizing Perl Steven Lembark Workhorse Computing [email protected]
57

Docker perl build

Jul 25, 2015

Download

Technology

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Docker perl build

Thinking inside a box: Dockerizing Perl

Steven LembarkWorkhorse Computing

[email protected]

Page 2: Docker perl build

What's on your box?

Pre-compiled perl distros are terrible.

Bulky, slow, with annoying dependencies.

Not what you need...

Page 3: Docker perl build

Example: Red Hat Enterprize 7.0

5.16 == “end of life”

­Doptimize=­O2 ­g ­pipe ­fstack­protector­strong  ­mtune=generic  ­Dversion=5.16.3 ­Dmyhostname=localhost ­Dperladmin=root@localhost  ­Dusethreads ­Duseithreads ­Ubincompat5005

Page 4: Docker perl build

Example: Red Hat Enterprize 7.0

5.16 == “end of life”

Not exactly built for speed.

­Doptimize=­O2 ­g ­pipe ­fstack­protector­strong  ­mtune=generic  ­Dversion=5.16.3 ­Dmyhostname=localhost ­Dperladmin=root@localhost  ­Dusethreads ­Duseithreads ­Ubincompat5005

Page 5: Docker perl build

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 ­fstack­protector­strong  ­mtune=generic  ­Dversion=5.16.3 ­Dmyhostname=localhost ­Dperladmin=root@localhost  ­Dusethreads ­Duseithreads ­Ubincompat5005

Page 6: Docker perl build

Fresh, not frozen

perl for your architecture.

optimized.

only dependencies you use (need).

Q: How?

Page 7: Docker perl build

Try it, you'll like it...

Bad approach: virtual machines...

Page 8: Docker perl build

Try it, you'll like it...

Bad approach: virtual machines...

and version-dirs...

and recompiling for each distro, architecture...

and symlink hell(2)...

Page 9: Docker perl build

Try it, you'll like it...

False lazyness!

Page 10: Docker perl build

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.

Page 11: Docker perl build

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

Page 12: Docker perl build

Docker: MRE for linux

80/20 of lxc:

Layered filesystem + Repository + Command line.

More nutritious than exciting.

Still evolving.

Page 13: Docker perl build

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.

Page 14: Docker perl build

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:

Page 15: Docker perl build

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.

Page 16: Docker perl build

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.

Page 17: Docker perl build

A: There is more than one way to do it.

Just perl

Minimal for distribution of local perl.

Lacks tools to inspect the build.

Page 18: Docker perl build

A: There is more than one way to do it.

Just the application.

No empty calories.

Requires local perl for distributed use.

Page 19: Docker perl build

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.

Page 20: Docker perl build

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;

Page 21: Docker perl build

Just a taste...

Minimal base container: busybox.

Good for experimenting:

$ docker pull busybox

Pulling repository busybox

fd5373b3d938: Download complete

...

f06b02872d52: Download complete

Page 22: Docker perl build

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

Page 23: Docker perl build

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.

Page 24: Docker perl build

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.

Page 25: Docker perl build

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”

Page 26: Docker perl build

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.

Page 27: Docker perl build

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

Page 28: Docker perl build

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 }'

Page 29: Docker perl build

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" ]

Page 30: Docker perl build

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.

Page 31: Docker perl build

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

Page 32: Docker perl build

$ 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...

Page 33: Docker perl build

Easy fix

RUN /opt/perl/bin/h2ph -r -l /usr/inlcude;

Page 34: Docker perl build

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';...

Page 35: Docker perl build

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

Page 36: Docker perl build

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

Page 37: Docker perl build

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

Page 38: Docker perl build

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.

Page 39: Docker perl build

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;

Page 40: Docker perl build

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.

Page 41: Docker perl build

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.

Page 42: Docker perl build

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" ]

Page 43: Docker perl build

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...

Page 44: Docker perl build

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'

Page 45: Docker perl build

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

Page 46: Docker perl build

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" ]

Page 47: Docker perl build

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.

Page 48: Docker perl build

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.

Page 49: Docker perl build

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?

Page 50: Docker perl build

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"

Page 51: Docker perl build

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)

Page 52: Docker perl build

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.

Page 53: Docker perl build

One way: static perl

Build perl & modules “--static”.

No hetergenious server issues.

perl image is larger.

Best for tests: no issues with underlying images.

Page 54: Docker perl build

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.

Page 55: Docker perl build

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.

Page 56: Docker perl build

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.

Page 57: Docker perl build

References

http://docs.docker.com/

.../builder Dockerfile directives

.../userguide What you think it is.