Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduction to Docker at PHPNW2014

Introduction to Docker at PHPNW2014

Slides for my Docker workshop at PHPNW 2014.

https://joind.in/11762

Andreas Hucks

October 04, 2014
Tweet

More Decks by Andreas Hucks

Other Decks in Programming

Transcript

  1. $  vagrant  box  add  -­‐-­‐name  phpnw14-­‐services  \      /path/to/phpnw14-­‐services.box

      
 $  vagrant  box  add  -­‐-­‐name  phpnw14-­‐playground  \      /path/to/phpnw14-­‐playground.box SETUP: VAGRANT BOXES
  2. $  cd  /path/to/vagrantfile   ! $  vagrant  up   !

    $  vagrant  ssh  playground SETUP: SPIN UP VAGRANT & CONNECT
  3. $  pwd   ! /home/vagrant   ! $  whoami  

    ! vagrant   ! $  lsb_release  -­‐a   ! Distributor  ID:  Ubuntu   Description:        Ubuntu  14.04  LTS   Release:                14.04   Codename:              trusty ENVIRONMENT
  4. WHAT ARE (DOCKER) CONTAINERS? • LXC • Have been around

    for some years • They are not VMs • Use the same kernel
  5. WHAT ARE (DOCKER) CONTAINERS? • liblxc • Separated by Kernel

    Namespaces • cgroups • See https:/ /linuxcontainers.org/
  6. WHAT ARE (DOCKER) CONTAINERS? • Docker creates a simple API

    for all of this • Written in Go • Provides a CLI and a RESTlike API
  7. RUNNING DOCKER • Kernel 3.8 or above • AUFS support

    • Cgroups and namespaces enabled • This means no OSX (yet) • Although there is boot2Docker
  8. WHY RUN DOCKER? • Fast, disposable development environments • Easy

    deployment of applications • Testing and integrations tasks
  9. WHY RUN DOCKER? • Microservice architectures • Scaling applications •

    DIY PaaS • … although this will not fit into today's schedule ;)
  10. 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
  11. CONTAINER GOTCHAS • Not a VM! • There is no

    init process, *your* process is PID 1 instead • No reaping, no cron, no services • Zombies! • Security implications, isolation is not complete
  12. WHAT HAPPENED? • Docker downloaded an image from a registry

    • Docker ran our command • It quit (this is important)
  13. HANDS ON • Spin up an Ubuntu Container • Install

    Nginx* • Exit *  echo  "daemon  off;"  >>  /etc/nginx/nginx.conf
  14. $  docker  ps  -­‐a   ! $  docker  commit  [hash]

     myfirstcontainer   ! $  docker  run  myfirstcontainer  nginx WHAT NOW?
  15. $  docker  run  -­‐d  -­‐p  8080:80  myfirstcontainer  nginx   !

    $  docker  ps   ! $  curl  localhost:8080 PROPERLY DETACH AND CONNECT
  16. $  docker  ps   ! $  docker  stop  [name]  

    ! $  docker  rm  [name] CLEAN UP
  17. $  docker  tag  myfirstcontainer  \      registry.dockerworkshop.dev/myfirstcontainer   !

    $  docker  push  \      registry.dockerworkshop.dev/myfirstcontainer PROPERLY TAG & PUSH THE CONTAINER
  18. 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
  19. 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)
  20. 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
  21. HANDS ON • Write a Dockerfile for a Nginx container

    • Build and push it • You may check the cheat folder for "nginx" to save some typing
  22. 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
  23. 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
  24. 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)
  25. 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)
  26. fugu  <command>  [fugufile]  \            [label]

     [docker-­‐options]  [command]  [args...]   ! commands:      run                  wraps  docker  run      build              wraps  docker  build FUGU
  27. #  fugu.yml   ! default:      image:    dockerfile/nginx

         name:      hello-­‐world-­‐nginx      detach:  true      publish:          -­‐  8080:80      volume:          -­‐  /host/path:/container/path            […] FUGUFILE
  28. #  fugu.yml   ! default:      image:    

     registry.dockerworkshop.dev/myfirstcontainer      command:  nginx      name:        fugutest      detach:    true      publish:          -­‐  8080:80 EXAMPLE: OUR FIRST CONTAINER
  29. 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
  30. 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 • …
  31. REQUIREMENTS • Extend our Nginx container with PHP-FPM • Build

    a separate MySQL container • Connect them somehow
  32. 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
  33. $  docker  run  -­‐d  -­‐P  -­‐-­‐name  php5  \    

     -­‐v  /home/vagrant/docker-­‐workshop-­‐app/:/var/www/  \      registry.dockerworkshop.dev/php5 PHP
  34. HANDS ON: MYSQL • Cheat: we use the official MySQL

    Dockerfile ;) • Try to add DB creation, see SQL in web application root • Tag and push
  35. 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
  36. $  docker  run  -­‐d  -­‐P  -­‐-­‐name  php5  —link  mysql:mysql  \

         -­‐v  /home/vagrant/docker-­‐workshop-­‐app/:/var/www/  \      registry.dockerworkshop.dev/php5 PHP
  37. 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
  38. #  fig.yml   ! web:      build:  .  

       command:  python  app.py      links:        -­‐  db      ports:        -­‐  "8000:8000"   db:      image:  postgres FIG