docker on a diet

28
Docker "Rena ship 07" by New Zealand Defence Force from Wellington, New Zealand - NZ Defence Force assistance to OP Rena. Licensed under CC BY 2.0 via Wikimedia Commons on a diet

Upload: kuan-yen-heng

Post on 14-Jul-2015

1.685 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Docker on a Diet

Docker

"Rena ship 07" by New Zealand Defence Force from Wellington, New Zealand - NZ Defence Force assistance to OP Rena. Licensed under CC BY 2.0 via Wikimedia Commons

on a diet

Page 2: Docker on a Diet

Motivation• Let’s download our base image!

• ZZZzzzz……

Page 3: Docker on a Diet

Sample image sizes

debian:wheezy 85.1 MB

ubuntu:trusty 188.3 MB

phusion/baseimage:0.9.16 279.7 MB

wordpress:4.1.0 470 MB

google/golang:latest 611.3 MB

python:2.7.9 744.9 MB

Page 4: Docker on a Diet
Page 5: Docker on a Diet
Page 6: Docker on a Diet

Docker containers

This

Not this

Page 7: Docker on a Diet

But wait!

– phusion/baseimage README

“Docker only needs to download the base image once: during the first deploy. On every subsequent deploys [sic], only the changes you make on top of the base image are downloaded.”

Page 8: Docker on a Diet

So why lean containers?• Continuous integration / automated testing

• Should you test your containers? (Hint: yes) • Third party CI services boot up a fresh

environment each time

• Fast bootstrapping • A new host in e.g. an autoscaling cluster has to

download all images from scratch

• Bandwidth / transfer • Especially if you’re running a private registry

Page 9: Docker on a Diet

Trim the fatMethod 1

Page 10: Docker on a Diet

Removing artifacts

• Example from phusion/baseimage:

• Just typical housekeeping • Without: 334.6 MB • With: 314 MB (-20.6 MB)

apt-get clean rm -rf /tmp/* /var/tmp/* rm -rf /var/lib/apt/lists/* rm -f /etc/ssh/ssh_host_* rm -rf /usr/share/man/?? rm -rf /usr/share/man/??_*

Page 11: Docker on a Diet

You ain’t gonna need it• phusion/baseimage installs syslog-ng, logrotate and

openssh-server (sshd) • SSH isn’t needed now that we have docker exec

(addressed in a blog post) • Log management: dump process logs to stdout and

use a collection container like progrium/logspout • Alternatively mount /dev/log into your container • With log management + sshd: 314 MB • Without: 279 MB (-35 MB)

Page 12: Docker on a Diet

Reducing dependencies• For example: a frontend app that uses a Gulp

pipeline with gulp-ruby-sass • This requires “gem install sass”, which requires

“apt-get install ruby-full rubygems-integration” • OR you could switch to gulp-sass and use

native bindings to libsass (C implementation) • With gulp-ruby-sass: 487.2 MB • With gulp-sass: 386 MB (-101.2 MB)

Page 13: Docker on a Diet

Delegate rolesMethod 2

Page 14: Docker on a Diet

Splitting your containers

• Differentiate between “build” and “runtime” • Compilation tools and libraries should not be

present in your production environment • Build your app in a “dev” or “builder” container

and transfer it to a “runtime” container • Specialized utility containers as standalone

binaries

Page 15: Docker on a Diet

Build pipeline

• How do I write my Dockerfile now that I need another container (or more) to build my app?

• Script a build pipeline! • Process your source files in a shared volume

with your build container(s) before loading it into your base runtime image as the final step

• A popular approach is to use Makefiles

Page 16: Docker on a Diet

Docker Makefiles

GIT = pie/git BUILD = pie/builder IMAGE = pie/hubot

hubot: docker run --rm -v $(pwd):/opt:rw -e GPG=$$GPG $(GIT) /bin/bash -c “[…]”

hubot.tar: | hubot docker run --rm -v $(pwd):/opt:rw $(BUILD) /bin/bash -c “npm […] && tar […]”

build: hubot.tar Dockerfile docker build -t $(IMAGE):latest --rm --no-cache .

clean: rm -rf hubot && rm -f hubot.tar

Credentials

Git container

Builder container

Shared folder (alternatively, make a data container)

Page 17: Docker on a Diet

Change your imageMethod 3

Page 18: Docker on a Diet

Switching the base image

• Basing your image off Debian instead of Ubuntu results in >100 MB savings off the bat

• Some tweaks needed: different packages, python3 not installed by default, etc

• Example: olberger/baseimage-docker • Before: 279 MB • After: 166.8 MB (-112.2 MB)

Page 19: Docker on a Diet

Reducing dependencies II• phusion/baseimage relies on a Python 3

my_init script which bootstraps runit • Replace runit with s6, a process supervisor

suite designed to run as PID 1, which removes the need for certain workarounds (e.g. environment variables)

• Eliminates python3 as a dependency • Before: 166.8 MB • After: 144.3 MB (-22.5 MB)

Page 20: Docker on a Diet

How low can you go?

• Build Linux from scratch! (LFS) • The hard work has been done for you:

Buildroot and BusyBox • Of course, you could also compile a statically

linked binary, e.g. a Golang app and load it into the scratch image (0 MB) but that’s just crazy talk

Page 21: Docker on a Diet

BusyBox

– busybox README

“BusyBox combines tiny versions of many common UNIX utilities into a single small executable. It provides replacements for most of the utilities you usually find in GNU fileutils, shellutils, etc. […] BusyBox provides a fairly complete environment for any small or embedded system.”

Page 22: Docker on a Diet

Here be dragons

Page 23: Docker on a Diet

Switching the base image II• BusyBox weighs in at 2.4 MB (!!) • Seriously barebones • A popular setup is to include opkg and

piggyback on the OpenWRT package index • An example being progrium/busybox (4.8 MB) • Roll your own using progrium/rootbuilder

• Before: 183 MB • After: 56 MB (-127 MB)

Page 24: Docker on a Diet

Caveats• OpenWRT packages are intended for routers

and embedded systems, hence it has a rather limited selection

• Packages not available in OpenWRT (nodejs, redis, nginx, etc) usually have to be compiled from source, often with manual tweaks

• There is a new project, docker-alpine based on Alpine Linux that has a more general purpose package index (using apk)

Page 25: Docker on a Diet

A tiny baseimage• https://registry.hub.docker.com/u/gigablah/baseimage/

• Result: 5.8 MB

FROM progrium/busybox MAINTAINER Chris Heng <[email protected]>

ADD s6-2.0.0.1.tar.gz / ADD service /etc/service

RUN mkdir -p /var/spool/cron/crontabs

ENTRYPOINT ["/usr/bin/s6-svscan", "-t0"] CMD ["/etc/service"]

Page 26: Docker on a Diet

In short…

Original image (nodejs app) 426 MB

Without ruby dependency 325 MB

Without sshd and syslog-ng 290 MB

With Debian as base 183 MB

With s6 as init system 166 MB

With BusyBox as base 56 MB

Page 27: Docker on a Diet

References

• http://phusion.github.io/baseimage-docker/ • https://blog.phusion.nl/2015/01/20/baseimage-docker-fat-

containers-treating-containers-vms/ • http://buildroot.uclibc.org/ • http://www.busybox.net/ • http://skarnet.org/software/s6/ • http://blog.tutum.co/2014/12/02/docker-and-s6-my-new-

favorite-process-supervisor/ • https://registry.hub.docker.com/u/gigablah/baseimage/ • http://gliderlabs.viewdocs.io/docker-alpine

Page 28: Docker on a Diet

Thank you

[email protected] https://github.com/gigablah

@gigablah