on native Linux APIs. Docker... automates deploying applications inside containers provides access to kernel APIs using libcontainer (Docker 1.0) or native LXC (older releases) must run on a Linux host can only run Linux containers Docker is not necessarily a replacement for full virtualization. 3 / 17
environments (some overlap with Vagrant) spin up continuous integration environments continuous delivery test on different distributions build applications for different package managers In general, Docker excels at building discrete, non-stateful application stacks. You would not use Docker to deploy persistent components like databases. 4 / 17
- - - - - + - - - - - - - - - - - - - - + | | | | u s e r l a n d | u s e r l a n d | | | | + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | | | | k e r n e l | k e r n e l | | | | + - - - - - - - - - - - - - - + - - - - - - - - - - - - - - + | | | h y p e r v i s o r | | | + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + VM completely isolated kernel and userland dedicated resources hypervisor can support multiple operating systems as guests + - - - - - - - - - - - - - - + - - - - - - - - - - - - - - + | | | | u s e r l a n d | u s e r l a n d | | | | + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | | | c o n t a i n e r l a y e r | | | + - - - - - - - - - - - - - - + - - - - - - - - - - - - - - + | | | k e r n e l | | | + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + Container shares kernel space with other instances higher density due to lower overhead guests must be the same operating system as the host Containers vs. VMs 5 / 17
the product of a chain of saved changes, all the way back to a parent image. Container A writable layer on top of an image. Containers: preserve state (run status) include metadata about the instance (e.g., resource allocations) Terminology 6 / 17
(AuFS), which allows several filesystems to be mounted simultaneously. Docker images are layers in the union filesystem. Each layer has a direct ancestor (parent image). Only the topmost layer (the container) is writable. 7 / 17
the filesystem. When building an image, Docker applies each change in sequence. Updating an existing image is very speedy, since the lower layers have not changed. $ d o c k e r h i s t o r y g o I M A G E C R E A T E D C R E A T E D B Y S I Z E f a a 5 1 0 3 1 5 1 c 2 A b o u t a n h o u r a g o / b i n / s h - c # ( n o p ) E N T R Y P O I N T [ / w w w / a p p ] 0 B 5 b c 3 a 9 2 2 7 3 3 0 A b o u t a n h o u r a g o / b i n / s h - c g o b u i l d a p p . g o 8 . 2 2 5 M B 3 3 f 1 8 2 a 5 1 2 a a A b o u t a n h o u r a g o / b i n / s h - c # ( n o p ) W O R K D I R / w w w 0 B e 5 e c b 9 4 2 b 6 c e A b o u t a n h o u r a g o / b i n / s h - c g o g e t g i t h u b . c o m / z e n a z n / g o j i 1 . 9 5 3 M B c 0 8 4 2 8 9 0 3 2 8 7 A b o u t a n h o u r a g o / b i n / s h - c # ( n o p ) E N V G O P A T H = / g o 0 B a 8 a 6 2 1 9 e 5 d 4 f A b o u t a n h o u r a g o / b i n / s h - c # ( n o p ) A D D d i r : d 2 d 2 8 c 8 2 5 4 5 6 0 3 d e c 0 4 1 7 . 9 1 M B c 5 b 9 f d 5 a 3 3 a c A b o u t a n h o u r a g o / b i n / s h - c a p t - g e t i n s t a l l - y g o l a n g g i t 2 1 1 . 4 M B 1 7 2 5 6 f c 9 5 2 8 6 A b o u t a n h o u r a g o / b i n / s h - c a p t - g e t u p d a t e 4 . 3 1 3 M B e 5 4 c a 5 e f a 2 e 9 3 w e e k s a g o / b i n / s h - c a p t - g e t u p d a t e & & a p t - g e t i n s t a l l 1 7 8 . 4 k B 6 c 3 7 f 7 9 2 d d a c 3 w e e k s a g o / b i n / s h - c a p t - g e t u p d a t e & & a p t - g e t i n s t a l l 8 3 . 6 1 M B 8 3 f f 7 6 8 0 4 0 a 0 3 w e e k s a g o / b i n / s h - c s e d - i ' s / ^ # \ s * \ ( d e b . * u n i v e r s e \ ) $ / 1 . 9 0 3 k B 2 f 4 b 4 d 6 a 4 a 0 6 3 w e e k s a g o / b i n / s h - c e c h o ' # ! / b i n / s h ' > / u s r / s b i n / p o l i c 1 9 4 . 5 k B d 7 a c 5 e 4 f 1 8 1 2 3 w e e k s a g o / b i n / s h - c # ( n o p ) A D D f i l e : a d c 4 7 d 0 3 d a 6 b b 2 4 1 8 e 1 9 2 . 5 M B 5 1 1 1 3 6 e a 3 c 5 a 1 3 m o n t h s a g o 0 B In the history above, the highlighted lines represent commits introduced while building the Go image from the demo. 8 / 17
image from a Dockerfile. A Dockerfile is simply a text file with instructions. Each step runs independently, adding a commit to the image history. F R O M u b u n t u # I n s t a l l s y s t e m d e p e n d e n c i e s R U N a p t - g e t u p d a t e R U N a p t - g e t i n s t a l l - y g o l a n g g i t # I n s t a l l t h e a p p l i c a t i o n c o d e A D D . / w w w # I n s t a l l G o d e p e n d e n c i e s E N V G O P A T H / g o R U N g o g e t g i t h u b . c o m / z e n a z n / g o j i # B u i l d t h e a p p W O R K D I R / w w w R U N g o b u i l d a p p . g o # R u n t h e a p p E N T R Y P O I N T [ " / w w w / a p p " ] 9 / 17
be affected by vulnerabilities allowing arbitrary code execution. To isolate containers, Docker: gives containers have individual kernel namespaces for accessing resources allocates resources using Linux c g r o u p s , limiting DOS attacks prunes unnecessary kernel capabilities (even if the container is running as r o o t , it does not have the same access as the r o o t on the host) There is at least one published exploit affecting pre-1.0 releases. 10 / 17
n s t a l l d o c k e r Since Docker only runs on Linux, you need to run the containers inside a VM. Vagrant has built-in support for deploying Docker containers, but you can also use boot2docker. For the demo, we'll use Vagrant. $ b r e w t a p c a s k r o o m / c a s k $ b r e w c a s k i n s t a l l v a g r a n t v i r t u a l b o x 11 / 17
. 0 : 8 0 0 0 Docker container exposes port 8 0 0 0 as l o c a l h o s t : 9 0 0 0 on the host HAProxy on the Vagrant VM forwards HTTP requests to l o c a l h o s t : 9 0 0 0 Structure ├── V a g r a n t f i l e ├── a p p │ ├── D o c k e r f i l e │ ├── G e m f i l e │ └── a p p . r b └── v a g r a n t └── p u p p e t ├── f i l e s │ └── h a p r o x y . c f g ├── f i l e s e r v e r . c o n f ├── m a n i f e s t s └── s i t e . p p Hello world! We'll use Docker to provision a simple “Hello world!” app on a Vagrant VM. 12 / 17
F I L E _ A P I _ V E R S I O N = " 2 " V a g r a n t . c o n f i g u r e ( V A G R A N T F I L E _ A P I _ V E R S I O N ) d o | c o n f i g | c o n f i g . v m . b o x = " t r u s t y 6 4 " c o n f i g . v m . n e t w o r k " f o r w a r d e d _ p o r t " , g u e s t : 8 0 , h o s t : 8 0 8 0 # I n s t a l l a n d c o n f i g u r e H A P r o x y c o n f i g . v m . s y n c e d _ f o l d e r " v a g r a n t / p u p p e t " , " / e t c / p u p p e t " c o n f i g . v m . p r o v i s i o n " p u p p e t " d o | p u p p e t | p u p p e t . m a n i f e s t s _ p a t h = " v a g r a n t / p u p p e t / m a n i f e s t s " p u p p e t . m a n i f e s t _ f i l e = " s i t e . p p " p u p p e t . o p t i o n s = " - - v e r b o s e - - f i l e s e r v e r c o n f i g = / e t c / p u p p e t / f i l e s e r v e r . c o n f " e n d # P r o v i s i o n t h e S i n a t r a a p p c o n f i ] . v m . p r o v i s i o n " d o c k e r " d o | d o c k e r | d o c k e r . b u i l d _ i m a g e " / v a g r a n t / a p p " , a r g s : " - t a p p " d o c k e r . r u n " a p p " , a r g s : " - p 9 0 0 0 : 8 0 0 0 " e n d e n d 13 / 17
i n a t r a ' s e t : b i n d , ' 0 . 0 . 0 . 0 ' s e t : p o r t , 8 0 0 0 g e t ' / ' d o " p u t s ' H e l l o w o r l d ! ' " e n d Dockerfile F R O M u b u n t u # I n s t a l l s y s t e m d e p e n d e n c i e s R U N a p t - g e t u p d a t e R U N a p t - g e t i n s t a l l - y r u b y R U N g e m i n s t a l l b u n d l e r # I n s t a l l a p p l i c a t i o n c o d e A D D . / w w w # I n s t a l l R u b y d e p e n d e n c i e s W O R K D I R / w w w R U N b u n d l e i n s t a l l # R u n t h e a p p E N T R Y P O I N T [ " r u b y " , " / w w w / a p p . r b " ] Hello world! 14 / 17
n t u p $ h t t p l o c a l h o s t : 8 0 8 0 H T T P / 1 . 1 2 0 0 O K C o n n e c t i o n : c l o s e C o n t e n t - L e n g t h : 4 8 C o n t e n t - T y p e : t e x t / h t m l ; c h a r s e t = u t f - 8 D a t e : F r i , 1 1 J u l 2 0 1 4 1 5 : 0 1 : 0 3 G M T S e r v e r : W E B r i c k / 1 . 3 . 1 ( R u b y / 1 . 9 . 3 / 2 0 1 3 - 1 1 - 2 2 ) X - C o n t e n t - T y p e - O p t i o n s : n o s n i f f X - F r a m e - O p t i o n s : S A M E O R I G I N X - X s s - P r o t e c t i o n : 1 ; m o d e = b l o c k p u t s ' H e l l o w o r l d ! ' 15 / 17
multiple distinct applications on the same machine, without worrying about configuration collisions. Our demo actually runs three “Hello world!” apps, in Ruby, Python, and Go. The only shared configuration we need to maintain is for HAProxy. $ h t t p - b l o c a l h o s t : 8 0 8 0 / r u b y p u t s ' H e l l o w o r l d ! ' $ h t t p - b l o c a l h o s t : 8 0 8 0 / p y t h o n p r i n t ( ' H e l l o w o r l d ! ' ) $ h t t p - b l o c a l h o s t : 8 0 8 0 / g o f m t . P r i n t l n ( " H e l l o w o r l d ! " ) 16 / 17