Intro to Docker + Tips on Using Docker with Rails Apps

Intro to Docker + Tips on Using Docker with Rails Apps

Slides from my talk at the San Francisco Rails Meetup, 2/20/2014.

32701e4c5c6d91bbbb092077f8bdd2f8?s=128

Brian Morearty

February 20, 2014
Tweet

Transcript

  1. ì   Introduction  to  Docker  +  Tips  on  using  

    Docker  for  Rails  Apps   Brian  Morearty                                                                                                                                                                                                                Feb  20,  2014  
  2. Your  Host   15  Docker  Tips  in  5  Minutes  

    2  
  3. 15  Docker  Tips  in  5  Minutes   3   • 

    Brian  Morearty   •  Rails  consultant   •  Docker  partner:      
  4. What  is  Docker?   15  Docker  Tips  in  5  Minutes

      4  
  5. Well,  What  is  it  NOT?   15  Docker  Tips  in

     5  Minutes   5  
  6. Hands  on  with  Docker   6   • It’s  not  like

     Chef  or   Puppet…   • But…it  does  enable  you  to   set  up  a  machine  with  a   script.  
  7. Hands  on  with  Docker   7   • It’s  not  a

     VM…   • But…it  does  run  processes   in  an  isolated   environment  from  the   host  machine.  
  8. Ok,  what  IS  it?   15  Docker  Tips  in  5

     Minutes   8  
  9. Hands  on  with  Docker   9   • Open  source  wrapper

      around  Linux  containers.   • Lets  you  package,  deploy,   and  run  your  app  with  its   dependencies.  
  10. Hands  on  with  Docker   10   • Similar  to  a

     VM  (has   snapshots  etc.),  but:   • Doesn’t  preallocate   memory   • Instant  startup  
  11. Hands  on  with  Docker   11   • The  container  relies

     on  the   host  OS  for:   •  Process  &  thread   management   •  Memory  allocaQon   •  Networking   •  Etc.  
  12. Hands  on  with  Docker   12   • Does  not  rely

     on  the  host   OS  for:   •  Dependencies  (supporQng   processes)  
  13. Hands  on  with  Docker   13   • A  Dockerfile  is

     a  script  to   create  a  Docker  container   •  It’s  opQonal.     •  You  can  just  install  stuff  in  a   command-­‐line  shell.  
  14. Hands  on  with  Docker   14   • Containers  are  built

     in   layers.   •  File  system  is  Copy-­‐On-­‐ Write   •  Touch  a  byte  in  a  file.  Your   file  gets  copied  up  to  the   current  layer.  
  15. Hands  on  with  Docker   15   • Layers  are  cool.

      •  Build  containers  on   containers.     •  Stand  on  shoulders.  
  16. Sample  use  cases   15  Docker  Tips  in  5  Minutes

      16  
  17. Hands  on  with  Docker   17   • Easier  developer  machine

      setup  with  lots  of   dependencies   •  Whether  in  a  corp  environment   •  Or  make  it  easier  to  contribute   to  your  open  source  project  
  18. Hands  on  with  Docker   18   • Easier  distribuQon  &

      installaQon  of  your  app   •  Whether  open  or  closed  source  
  19. Hands  on  with  Docker   19   • Set  up  your

     prod   environment  but  you   dislike  Chef  
  20. Hands  on  with  Docker   20   • Deploy  in  VMs

     but  you   want  to  have  more   RAM  available  
  21. Hands  on  with  Docker   21   • Separate  conflicQng  

    dependencies  (openssl,   ruby,  etc.)  among  your   apps  and  layers.    
  22. 15  Docker  Tips  in  5  Minutes   22   SO

     LET’S   SEE  IT  
  23. (Skipping  Past  the  Tutorial  to  Get  to   the  Railsy

     Part…)   15  Docker  Tips  in  5  Minutes   23  
  24. 15  Docker  Tips  in  5  Minutes   24   • A

     Dockerfile  for  a   Rails  app  
  25. 15  Docker  Tips  in  5  Minutes   25   #

    This will build the handson-namer image! FROM ubuntu:12.10! MAINTAINER Your Name, your@email.com! ! # Install dependencies! RUN apt-get update! RUN apt-get install -y curl git \! build-essential ruby2.1.0! RUN gem install rubygems-update! RUN update_rubygems! RUN gem install bundler --no-ri --no-rdoc! ! # Rails uses this port ya know! EXPOSE 3000! ! # Copy the app into the container at build time! ADD namer /opt/namer! WORKDIR /opt/namer! RUN bundle install! ! # Set the startup command! CMD ["rails", "server"]!
  26. 15  Docker  Tips  in  5  Minutes   26   • 

    Takes  minutes  the  first  Qme.   •  Takes  seconds  the  next  Qme.   •  Only  re-­‐executes  any  steps  a]er   the  first  one  that  changed.   ! $ docker build -t railsapp .!
  27. 15  Docker  Tips  in  5  Minutes   27   • 

    Run  detached   •  Map  host  port  80  to  container   port  3000   •  Except  there’s  no  DB.  Crash.   ! $ docker run -d -p 80:3000 railsapp!
  28. 15  Docker  Tips  in  5  Minutes   28   • Now

     make  a   Dockerfile  for  a   Postgres  server   •  Or  at  least  part  of  one  
  29. 15  Docker  Tips  in  5  Minutes   29   FROM

    ubuntu! MAINTAINER Alvin Lai <al@alvinlai.com>! ! RUN add-apt-repository ppa:pitti/postgresql! RUN apt-get -y update! ! ENV PG_VERSION 9.2! ENV LOCALE en_US! ENV LANGUAGE en_US.UTF-8! ENV LANG en_US.UTF-8! ENV LC_ALL en_US.UTF-8! ! RUN apt-get -y install postgresql-$PG_VERSION postgresql-client- $PG_VERSION postgresql-contrib-$PG_VERSION! ! RUN service postgresql start && \! su postgres sh -c "createuser -d -r -s docker" && \! su postgres sh -c "createdb -O docker docker" && \! su postgres sh -c "psql -c \"GRANT ALL PRIVILEGES ON DATABASE docker to docker;\""! ! EXPOSE 5432! CMD ["su", "postgres", "-c", "/usr/lib/postgresql/$PG_VERSION/bin/ postgres -D /var/lib/postgresql/$PG_VERSION/main/ -c config_file=/etc/ postgresql/$PG_VERSION/main/postgresql.conf"]! ! EXPOSE 5432!
  30. 15  Docker  Tips  in  5  Minutes   30   • It

     looks  a  lot  like   that  last  one.   • But  exposes  port   5432.  
  31. 15  Docker  Tips  in  5  Minutes   31   • Now,

     connect  them.   • How?  
  32. 15  Docker  Tips  in  5  Minutes   32   • Names

     and  Links.  
  33. 15  Docker  Tips  in  5  Minutes   33   • 

    Run  detached   •  Name  the  container  “pg”   •  (The  image  is  named  postgres)   •  Don’t  use  -p…it  would  expose  port   5432  to  the  host.   ! $ docker run -d -name pg postgres!
  34. 15  Docker  Tips  in  5  Minutes   34   • 

    Sets  up  a  network  bridge  to  pg   •  Injects  env  vars  in  the  railsapp   container  (pg’s  ip  addr,  port   mapping,  etc.)   ! $ docker run -d -p 80:3000 -link pg \! railsapp!
  35. 15  Docker  Tips  in  5  Minutes   35   • 

    config/database.yml   production:! adapter: postgresql! database: railsapp_production! username: railsapp! host: <%=
 ENV['PG_PORT_5432_TCP_ADDR'] %>! port: <%=
 ENV['PG_PORT_5432_TCP_PORT'] %>! pool: 5! timeout: 5000!
  36. Hands  on  with  Docker   36   • It  works.  Try

     it.   J  
  37. Hands  on  with  Docker   37   • One  last  thing.

     
  38. Using  Docker  with  Rails  apps:  how  to   cache  “bundle

     install”  when  the  gems   haven’t  changed   Hands  on  with  Docker   38  
  39. Hands  on  with  Docker   39   •  Problem:  commands

     that  depend  on  a   configuraQon  file  will  not  be  cached  if:   •  that  file  is  part  of  an  ADDed  directory,   and   •  the  directory  tree  contains     other  frequently-­‐modified  files.   ‐︎  e.g.,  a  Gemfile   e.g.,  an  app  directory  ‐︎     e.g.,  source  files  ‐︎   ‑︎︎  e.g.,  bundle  install  
  40. FROM ubuntu:12.10! MAINTAINER Your Name, your@email.com! ! # Install system

    dependencies (cached)! RUN apt-get install ...! ! # Copy the app into the container! # (DOES NOT use cache when myapp changes)! ADD myapp /opt/myapp! WORKDIR /opt/myapp! RUN bundle install! ! # Set the startup command! CMD ["rails", "server"]! Hands  on  with  Docker   40  
  41. Hands  on  with  Docker   41   •  Change  the

     app  and  rebuild  the   image.   à bundle install  can’t  be   cached.  (Because  the  ADD   invalidated  the  cache.)   à must  reinstall  all  dependency   gems  
  42. Hands  on  with  Docker   42   • Kinda  defeats  

    the  purpose  of   the  Docker   cache  
  43. Hands  on  with  Docker   43   • The  soluNon:  two

     ADDs.     •  First  add  the  Gemfile  (and   Gemfile.lock).   •  Then  bundle  install.   •  Then  ADD  the  whole  app.  
  44. FROM ubuntu:12.10! MAINTAINER Your Name, your@email.com! ! # Install system

    dependencies (cached)! RUN apt-get install ...! ! # Copy the Gemfile and Gemfile.lock! # (CACHED unless they changed)! ADD myapp/Gemfile /tmp/Gemfile! ADD myapp/Gemfile.lock /tmp/Gemfile.lock! WORKDIR /tmp! RUN bundle install! ! # Now copy the app into the container! ADD myapp /opt/myapp! WORKDIR /opt/myapp! ! # Set the startup command! CMD ["rails", "server"]! Hands  on  with  Docker   44   Before  ADDing   the  app  
  45. Hands  on  with  Docker   45   • Finally…  

  46. For  videos  and   exercises,  buy  the   self-­‐paced  

    Hands  on  with   Docker  class.     In  partnership  with   Docker,  Inc.     handsonwith.com   15  Docker  Tips  in  5  Minutes   46