ANDREAS HUCKS
Software Architect at SensioLabs DE
@meandmymonkey
Slide 3
Slide 3 text
WHAT TO COPY FROM USB DRIVES
• Only copy /boxes if you didn't download
them already
• Only copy /installers if you don't have
Vagrant and/or Virtualbox
• … and even then only the necessary files
SOFTWARE DEVELOPMENT
IS ABOUT BREAKING
PROBLEMS INTO SMALLER
PIECES
Slide 9
Slide 9 text
WHAT ARE (DOCKER) CONTAINERS?
• Linux Containers
• Have been around for some years
• They are not VMs
• Use the same kernel
Slide 10
Slide 10 text
WHAT ARE (DOCKER) CONTAINERS?
• Kernel Namespaces
• cgroups
• See https:/
/linuxcontainers.org/
Slide 11
Slide 11 text
WHAT ARE (DOCKER) CONTAINERS?
• Docker creates a simple API for all of this
• Written in Go
• Provides a CLI and a RESTlike API
Slide 12
Slide 12 text
RUNNING DOCKER
• Kernel 3.8 or above
• Union Filesystem support
• Cgroups and namespaces enabled
• This means no OSX (yet)
• Although there is boot2docker
Slide 13
Slide 13 text
WHY RUN DOCKER?
• Fast, disposable development
environments
• Easy deployment of applications
• Testing and integrations tasks
Slide 14
Slide 14 text
WHY RUN DOCKER?
• Microservice architectures
• Scaling applications
• DIY PaaS
• … although this will not fit into today's
schedule ;)
Slide 15
Slide 15 text
BUT WHAT ABOUT
PUPPET|ANSIBLE|CHEF|SALT?
• Docker does not replace configuration
management tools
• These tools can in fact be used to provision
docker platforms and/or containers
themselves
Slide 16
Slide 16 text
CONTAINER GOTCHAS
• Not a VM!
• There is no init process, *your* process is
PID 1 instead
• Security implications, isolation is not
complete
• No reaping, no cron, no services
• Zombies!
Slide 17
Slide 17 text
NODE (PID 1)
SOMESCRIPT (PID 2)
SOMETOOL (PID 3)
Slide 18
Slide 18 text
NODE (PID 1)
SOMESCRIPT (PID 2)
SOMETOOL (PID 3)
Slide 19
Slide 19 text
NODE (PID 1)
SOMETOOL (PID 3)
Slide 20
Slide 20 text
NODE (PID 1)
SOMETOOL (PID 3)
Brraaainns.
Slide 21
Slide 21 text
$ docker run \
registry.dockerworkshop.dev/ubuntu:14.04 \
echo "Hello World"
HELLO WORLD
Slide 22
Slide 22 text
WHAT HAPPENED?
• Docker downloaded an image from a
registry
• Docker ran our command
• It quit (this is important)
Slide 23
Slide 23 text
$ docker run \
registry.dockerworkshop.dev/ubuntu:14.04 \
/bin/bash
INSIDE THE CONTAINER
Slide 24
Slide 24 text
$ docker run -‐ti \
registry.dockerworkshop.dev/ubuntu:14.04 \
/bin/bash
OOPS, SECOND TRY
Slide 25
Slide 25 text
$ docker images
$ docker images -‐a
LIST DOCKER IMAGES
Slide 26
Slide 26 text
HANDS ON
• Spin up an Ubuntu Container
• Install Nginx*
• Exit
* echo "daemon off;" >> /etc/nginx/nginx.conf
Slide 27
Slide 27 text
$ docker ps -‐a
$ docker commit [hash] myfirstcontainer
$ docker run myfirstcontainer nginx
WHAT NOW?
Slide 28
Slide 28 text
$ docker run -‐d -‐p 8080:80 myfirstcontainer nginx
$ docker ps
$ curl localhost:8080
PROPERLY DETACH AND CONNECT
SHOULDN'T THIS BE
AUTOMATED?
• It's called Dockerfile
• Defines all build steps
• Build and tag (not push) in a single
command
• Cache results to speed up consecutive
builds
Slide 35
Slide 35 text
FROM ubuntu:14.04
RUN apt-‐get -‐y install python-‐pip
RUN apt-‐get -‐y install python-‐dev liblzma-‐dev […]
ADD . /docker-‐registry
ADD ./config/boto.cfg /etc/boto.cfg
RUN pip install /docker-‐registry/depends/docker-‐
registry-‐core
[…]
EXPOSE 5000
CMD exec docker-‐registry
DOCKERFILE
(Excerpt from Dockerfile for Docker Registry)
Slide 36
Slide 36 text
docker build [OPTIONS] PATH
-‐-‐force-‐rm=false Remove intermediate containers
-‐-‐no-‐cache=false Do not use cache when building
-‐q, -‐-‐quiet=false Suppress verbose output
-‐-‐rm=true Remove intermediate containers
-‐t, -‐-‐tag="" Repository name and tag
DOCKERFILE
HANDS ON
• We need a container running PHP-CLI
• For simplicity, a global phpunit.phar install
• We need a workdir to define where we will
run our tests later
• Tag as registry.dockerworkshop.dev/
phpunit:php55
Slide 42
Slide 42 text
$ docker run -‐rm \
registry.dockerworkshop.dev/phpunit:php55 phpunit
EXECUTE
Slide 43
Slide 43 text
HANDS ON
• Build another phpunit container
• This time, running PHP 5.3.x
• (Yes, 5.3)
• Hint: There is a ubuntu:12.04 in the registry
• Tag as registry.dockerworkshop.dev/
phpunit:php53
Slide 44
Slide 44 text
$ docker run -‐rm \
registry.dockerworkshop.dev/phpunit:php53 phpunit
EXECUTE
Slide 45
Slide 45 text
NICE, BUT…
• Isolated, throw-away testing
environments!
• We still have a dedicated config on the CI
side, because it needs to know about
specifics (like the container names)
Slide 46
Slide 46 text
No content
Slide 47
Slide 47 text
INTRODUCING FUGU
• Written in Go
• Utility to preconfigure docker run & build
commands
• For single containers
• A single, simple YAML file
• Allows us to configure our tests a bit
similar to Travis (right in our project)
Slide 48
Slide 48 text
fugu [fugufile] \
[label] [docker-‐options] [command] [args...]
commands:
run wraps docker run
build wraps docker build
FUGU
HANDS ON
• Add a fugu.yml to our PHP Project
• Use two labels to run both PHP Versions
• Result:
• $ fugu run php55
• $ fugu run php53
Slide 52
Slide 52 text
IDEAS
• Build a complete single container with DB
and fixtures and run Behat
• Build separate DB containers with different
fixtures
• If a test fails, push the resulting container
to a registry for further analysis
• …
Slide 53
Slide 53 text
DOCKERIZING A
WEB APP
Slide 54
Slide 54 text
REQUIREMENTS
• Extend our Nginx container with PHP-FPM
• Build a separate MySQL container
• Connect them somehow
Slide 55
Slide 55 text
HANDS ON: PHP
• Base: our Nginx container
• Install PHP Packages and supervisord
• Download and install composer
• Replace webroot, Nginx config, index.html
• Set CMD to supervisor
• Tag and push
HANDS ON: MYSQL
• Cheat: we use the official MySQL
Dockerfile ;)
• Try to add DB creation, see SQL in web
application root
• Tag and push
Slide 58
Slide 58 text
$ docker run -‐d -‐P -‐-‐name mysql \
registry.dockerworkshop.dev/mysql
MYSQL
Slide 59
Slide 59 text
CONNECTING
• The PHP container needs to now where to
find the DB
• Solution: Links
• Create environment variables with
network info
• Add entries to /etc/hosts
HANDS ON
• Run the PHP container interactively and
check out the /etc/hosts file
• Modify the database connection code in
src/app.php line 27 to use the new
hostname