SlideShare a Scribd company logo
1 of 48
Download to read offline
Streamline your dev env with Docker 
Giacomo Bagnoli, #RUBYDAY2014
WHOAMI 
Giacomo Bagnoli 
Currently Backend Engineer at Gild 
Previously at Amazon and Asidev 
Twitter: @gbagnoli 
Github: gbagnoli 
about.me/gbagnoli
WHAT'S WRONG WITH MY DEV ENVIRONMENT? 
Nothing in particular. It's not* broken, so let's fix it. 
* conditions apply
WHAT'S WRONG WITH MY DEV ENVIRONMENT? 
Your development 
environment is probably 
a beautiful, unique 
snowflake 
Photo credits: https://www.flickr.com/photos/amagill/4223790595/
WHAT'S DOCKER, ANYWAY?!? 
Open source platform 
Docker Engine 
Container management runtime 
Packaging tools for images 
Docker Hub
CONTAINERS, UH? 
Operating system-level virtualization* 
Runs multiple isolated linux systems 
On a single host, with a single kernel 
No /sbin/init, no device emulation 
Think them as chroot on steroids 
Isolation provided by linux cgroups and namespaces 
Resource limiting and prioritization via cgroups 
Resource usage accounting via cgroups 
* not a virtualization method, containers != VM
DOCKER IMAGES (0) 
Portable, read-only layers. 
Images are composed at run-time to 
form the container root FS using an 
union filesystem. 
Processes tricked to see the filesystem 
as R/W. 
The writable layer is discarded if the 
container is not committed. 
The read-only and portable properties 
are important as they enable sharing 
(via the docker hub).
DOCKER IMAGES (1) 
Docker images form a Direct Acyclic Graph. 
Each layer is cached (possibly) and reused by other images. 
This means that if multiple images derive from debian:wheezy, 
that particular image is shared by all of them (thus downloaded 
once). 
Images are pushed/pull to/from the docker hub.
DOCKER IMAGES (2) 
$ docker pull ubuntu:14.04 
$ docker pull ubuntu:12.04 
$ docker pull redis:2.8.13 
$ docker pull debian:wheezy 
$ docker pull mongo:2.6.4 
$ docker images 
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE 
redis 2.8.13 dd52dc9c8f76 9 minutes ago 98.44 MB 
mongo 2.6.4 dd1f260c0731 12 minutes ago 391.2 MB 
debian wheezy 9cdcc6025135 18 hours ago 85.19 MB 
ubuntu 14.04 96864a7d2df3 2 days ago 204.4 MB 
ubuntu 12.04 ec966722cde4 2 days ago 103.8 MB
DOCKER IMAGES (3) 
$ docker images ‐‐tree 
└─511136ea3c5a Virtual Size: 0 B 
└─b37448882294 Virtual Size: 85.19 MB 
└─9cdcc6025135 Virtual Size: 85.19 MB Tags: debian:wheezy 
├─e365f7cdb352 Virtual Size: 85.52 MB 
│ └─b15940870e43 Virtual Size: 85.52 MB 
│ └─22ad4fc6b16f Virtual Size: 98.44 MB 
│ └─bd1e22dd175d Virtual Size: 98.44 MB 
│ └─3b1ce200fdad Virtual Size: 98.44 MB 
│ └─dd52dc9c8f76 Virtual Size: 98.44 MB Tags: redis:2.8.13 
└─49fd1ae472a8 Virtual Size: 85.52 MB 
└─6c203838fd07 Virtual Size: 99.62 MB 
└─b1cd74f30329 Virtual Size: 391.2 MB 
└─9d0a3438646f Virtual Size: 391.2 MB 
└─dd1f260c0731 Virtual Size: 391.2 MB Tags: mongo:2.6.4
LET'S BUILD A RUBY2 IMAGE 
Ubuntu 14.04 image has no ruby at all. Repos have ruby 1.9. 
Let's create an image with 2.1 as default. 
Dockerfile: 
FROM ubuntu:14.04 
MAINTAINER Giacomo Bagnoli <gbagnoli@gmail.com> 
RUN echo "deb http://ppa.launchpad.net/brightbox/ruby‐ng/ubuntu trusty main" >  
/etc/apt/sources.list.d/ruby‐ng.list 
RUN apt‐key adv ‐‐keyserver hkp://keyserver.ubuntu.com:80 ‐‐recv‐keys C3173AA6 
RUN apt‐get update 
RUN apt‐get install ‐y ruby2.1 
Build! 
$ docker build ‐‐rm ‐t rubyday/ruby:2.1 .
RUBY2 IMAGE 
Each directive in the Dockerfile adds a layer 
$ docker images ‐‐tree 
└─96864a7d2df3 Virtual Size: 204.4 MB Tags: ubuntu:14.04 
└─8f1b6341c5be Virtual Size: 204.4 MB # MAINTAINER 
└─d323cc59da91 Virtual Size: 204.4 MB # RUN 
└─724a6664d97a Virtual Size: 204.4 MB # RUN 
└─8614dab05fbe Virtual Size: 224.8 MB # RUN 
└─d7ae4a198781 Virtual Size: 257.2 MB Tags: rubyday/ruby:2.1 # RUN 
$ docker run ‐t rubyday/ruby:2.1 ruby ‐v 
ruby 2.1.2p95 (2014‐05‐08 revision 45877) [x86_64‐linux‐gnu] 
Woah, 53Mb. apt‐get update adds 20Mb to the image.
I TRIED... 
Let's remove apt-get files by adding another RUN statement 
diff ‐‐git a/ruby2/Dockerfile b/ruby2/Dockerfile 
index dd37dcb..2b9c105 100644 
‐‐‐ a/ruby2/Dockerfile 
+++ b/ruby2/Dockerfile 
@@ ‐8,3 +8,4 @@ 
RUN echo "deb http://ppa.launchpad.net/brightbox/ruby‐ng/ubuntu trusty main" > / 
RUN apt‐key adv ‐‐keyserver hkp://keyserver.ubuntu.com:80 ‐‐recv‐keys C3173AA6 
RUN apt‐get update 
RUN apt‐get install ‐y ruby2.1 
+RUN rm ‐rf /var/lib/apt/lists/* /var/cache/apt/archives/*.deb
... GRUMPY CAT SAYS
LAYERS.. 
$ docker images ‐‐tree 
└─96864a7d2df3 Virtual Size: 204.4 MB Tags: ubuntu:14.04 
└─8f1b6341c5be Virtual Size: 204.4 MB # MAINTAINER 
└─d323cc59da91 Virtual Size: 204.4 MB # RUN 
└─724a6664d97a Virtual Size: 204.4 MB # RUN 
└─8614dab05fbe Virtual Size: 224.8 MB # RUN 
└─d7ae4a198781 Virtual Size: 257.2 MB # RUN 
└─b8bb3ce3008e Virtual Size: 257.2 MB Tags: rubyday/ruby:2.1 # RUN 
Remember that every directive adds a layer. Layers are read only.
LET'S TRY ONCE MORE 
Let's rewrite the Dockerfile 
FROM ubuntu:14.04 
MAINTAINER Giacomo Bagnoli <gbagnoli@gmail.com> 
RUN  
echo "deb http://ppa.launchpad.net/brightbox/ruby‐ng/ubuntu trusty main"  
> /etc/apt/sources.list.d/ruby‐ng.list &&  
apt‐key adv ‐‐keyserver hkp://keyserver.ubuntu.com:80 ‐‐recv‐keys C3173AA6 &&  
apt‐get update &&  
apt‐get install ‐y ruby2.1 &&  
rm ‐rf /var/lib/apt/lists/* /var/cache/apt/archives/*.deb
REBUILD 
Build: 
$ docker build ‐‐rm ‐t rubyday/ruby:2.1 . 
$ docker images 
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE 
rubyday/ruby 2.1 b337a5c538f3 About a minute ago 236.9 MB 
└─96864a7d2df3 Virtual Size: 204.4 MB Tags: ubuntu:14.04 
└─86ae939e2da3 Virtual Size: 204.4 MB # MAINTAINER 
└─b337a5c538f3 Virtual Size: 236.9 MB Tags: gild/ruby:2.1 # RUN 
yay!
PAT ME ON THE BACK
... ONE MORE THING 
We probably want ‐dev packages and bundle 
Let's update the Dockerfile 
FROM ubuntu:14.04 
MAINTAINER Giacomo Bagnoli 
RUN  
echo "deb http://ppa.launchpad.net/brightbox/ruby‐ng/ubuntu trusty main"  
> /etc/apt/sources.list.d/ruby‐ng.list 
RUN apt‐key adv ‐‐keyserver hkp://keyserver.ubuntu.com:80 ‐‐recv‐keys C3173AA6 
RUN apt‐get update &&  
apt‐get install ‐y build‐essential &&  
apt‐get install ‐y ruby2.1 ruby2.1‐dev &&  
update‐alternatives ‐‐set ruby /usr/bin/ruby2.1 &&  
update‐alternatives ‐‐set gem /usr/bin/gem2.1 &&  
rm ‐rf /var/lib/apt/lists/* /var/cache/apt/archives/*.deb 
RUN gem install bundle
TIME FOR RAILS 
Let's try creating a Dockerfile for a rails app. 
The app is a random simple TODO list 
application found on Github. 
It's a rails4 application that uses SQL, nothing 
fancy. 
Let's assume we are developing this app 
targeting postgresql. 
Github url: 
https://github.com/gbagnoli/todo‐rails4‐angularjs
A WORD ON LINKING 
In docker, we can access service(s) running in other container(s) via linking. 
Linking a container to another will setup some environment variables in it, allowing the container to 
discover and connect to the service. 
We will use this feature to access postgres from our app container.
THE DOCKERFILE 
FROM rubyday/ruby:2.1 
MAINTAINER Giacomo Bagnoli <gbagnoli@gmail.com> 
RUN adduser todo ‐‐home /opt/todo ‐‐shell /bin/bash ‐‐disabled‐password ‐‐gecos "" 
RUN apt‐get update &&  
apt‐get install ‐y libpq‐dev nodejs &&  
rm ‐rf /var/lib/apt/lists/* /var/cache/apt/archives/*.deb 
ADD Gemfile /opt/todo/ 
ADD Gemfile.lock /opt/todo/ 
RUN chown ‐R todo:todo /opt/todo 
RUN su ‐c "D=/opt/todo/bundle; mkdir $D && bundle install ‐‐deployment ‐‐path $D" 
‐s /bin/bash ‐l todo 
WORKDIR /opt/todo 
EXPOSE 3000 
ADD . /opt/todo 
RUN chown ‐R todo:todo /opt/todo 
USER todo 
ENTRYPOINT ["/bin/bash", "/opt/todo/bin/docker_entrypoint.sh"] 
CMD ["bundle", "exec", "rails", "server"]
DOCKERFILE EXPLAINED (0) 
FROM rubyday/ruby:2.1 
MAINTAINER Giacomo Bagnoli <gbagnoli@gmail.com>
DOCKERFILE EXPLAINED (1) 
RUN adduser todo ‐‐home /opt/todo ‐‐shell /bin/bash ‐‐disabled‐password ‐‐gecos "" 
RUN apt‐get update &&  
apt‐get install ‐y libpq‐dev nodejs &&  
rm ‐rf /var/lib/apt/lists/* /var/cache/apt/archives/*.deb
DOCKERFILE EXPLAINED (2) 
ADD Gemfile /opt/todo/ 
ADD Gemfile.lock /opt/todo/ 
RUN chown ‐R todo:todo /opt/todo 
RUN su ‐c "D=/opt/todo/bundle; mkdir $D && bundle install ‐‐deployment ‐‐path $D" 
‐s /bin/bash ‐l todo
DOCKERFILE EXPLAINED (3) 
WORKDIR /opt/todo 
EXPOSE 3000 
ADD . /opt/todo 
RUN chown ‐R todo:todo /opt/todo
DOCKERFILE EXPLAINED (4) 
USER todo 
ENTRYPOINT ["/bin/bash", "/opt/todo/bin/docker_entrypoint.sh"] 
CMD ["bundle", "exec", "rails", "server"]
POSTGRES CONTAINER (0) 
$ docker pull postgres:9.3 
$ docker run ‐d ‐‐name postgres ‐t postgres:9.3 
a5723351c46ce015d585dd49f230ecb376557d0b955f233dbff3bf92f3a6721d 
$ docker ps 
CONTAINER ID IMAGE [...] PORTS NAMES 
a5723351c46c postgres:9 [...] 5432/tcp postgres 
This container EXPOSEs port 5432. 
Question is, how do we connect to it?
We can't just hardcode its ip address, as it defeats the purpose... 
$ docker inspect postgres | grep NetworkSettings ‐A 9 
"NetworkSettings": { 
"Bridge": "docker0", 
"Gateway": "172.17.42.1", 
"IPAddress": "172.17.0.4", 
"IPPrefixLen": 16, 
"PortMapping": null, 
"Ports": { 
"5432/tcp": null 
} 
}, 
POSTGRES CONTAINER (1)
THE WRAPPER SCRIPT (0) 
In the Dockerfile, an ENTRYPOINT was specified. 
#!/bin/bash 
# exit with error if a variable is unbound (not set) 
set ‐u 
# exit with error if a command returns a non‐zero status 
set ‐e 
PGADDR=$DB_PORT_5432_TCP_ADDR 
PGPORT=$DB_PORT_5432_TCP_PORT 
PGDBNAME="${DATABASE_NAME:‐todo}" 
PGUSER="${DATABASE_USER:‐postgres}" 
# export database configuration for rails. 
export DATABASE_URL="postgresql://${PGUSER}@${PGADDR}:${PGPORT}/${PGDBNAME}" 
# exec what the user wants 
exec "$@"
THE WRAPPER SCRIPT (1) 
Trying to execute the container will throw an error (it's a feature!) 
$ docker run ‐‐rm ‐‐name todoapp ‐t rubyday/todo 
/opt/todo/bin/docker_entrypoint.sh: line 6: DB_PORT_5432_TCP_ADDR: unbound variable
LINKING! 
$ docker run ‐‐rm ‐‐link postgres:db ‐‐name todoapp  
‐t rubyday/todo /bin/bash ‐c 'env' 
DB_ENV_PGDATA=/var/lib/postgresql/data 
DB_NAME=/todoapp/db 
DB_PORT_5432_TCP_ADDR=172.17.0.4 
DB_PORT=tcp://172.17.0.4:5432 
DB_ENV_LANG=en_US.utf8 
DB_PORT_5432_TCP=tcp://172.17.0.4:5432 
DB_ENV_PG_MAJOR=9.3 
DB_PORT_5432_TCP_PORT=5432 
DB_PORT_5432_TCP_PROTO=tcp 
DB_ENV_PG_VERSION=9.3.5‐1.pgdg70+1 
DATABASE_URL=postgresql://postgres@172.17.0.4:5432/todo 
‐‐link postgres:db link container named postgres with alias db 
alias db tells docker to prefix all variables with DB
START! 
Pretty much standard business 
$ docker run ‐‐rm ‐‐link postgres:db ‐t rubyday/todo bundle exec rake db:create 
$ docker run ‐‐rm ‐‐link postgres:db ‐t rubyday/todo bundle exec rake db:schema:load 
$ docker run ‐‐link postgres:db ‐‐name todoapp ‐p 3000:3000 ‐d ‐t rubyday/todo 
7540f7647309110c53d2349cf7c68d1388e0f43de3d5904396fa2bb4041b6b28 
$ docker ps 
CONTAINER ID IMAGE [..] PORTS NAMES 
7540f7647309 rubyday/todo:latest [..] 0.0.0.0:3000‐>3000/tcp todoapp 
a5723351c46c postgres:9 [..] 5432/tcp postgres,todoapp/db 
‐p 3000:3000 creates a port forward from the host to the container
DOES IT WORK? 
$ netstat -lnp | grep 3000 
tcp6 0 0 :::3000 :::* LISTEN 3645/docker-proxy 
$ curl -v http://localhost:3000 
* Connected to localhost (127.0.0.1) port 3000 (#0) 
> GET / HTTP/1.1 
> User-Agent: curl/7.35.0 
> Host: localhost:3000 
> Accept: */* 
>< 
HTTP/1.1 200 OK 
[...] 
Good.
TOO MUCH WORK. LET'S AUTOMATE 
Enters FIG. 
fig.yml: 
web: 
build: . 
links: 
- db 
ports: 
- "3000:3000" 
db: 
image: postgres:9.3 
ports: 
- "5432"
..SMALL TWEAK FOR FIG 
diff --git a/bin/docker_entrypoint.sh b/bin/docker_entrypoint.sh 
index 0775ece..b69980c 100644 
--- a/bin/docker_entrypoint.sh 
+++ b/bin/docker_entrypoint.sh 
@@ -3,8 +3,8 @@ 
set -u 
set -e 
-PGADDR=$DB_PORT_5432_TCP_ADDR 
-PGPORT=$DB_PORT_5432_TCP_PORT 
+PGADDR=$DB_1_PORT_5432_TCP_ADDR 
+PGPORT=$DB_1_PORT_5432_TCP_PORT 
PGDBNAME="${DATABASE_NAME:-todo}" 
PGUSER="${DATABASE_USER:-postgres}"
PROFIT! 
$ fig up ‐d # familiar, huh? 
$ fig run web bundle exec rake db:create 
$ fig run web bundle exec rake db:schema:load 
$ netstat ‐lnp | grep 3000 
tcp6 0 0 :::3000 :::* LISTEN 24727/docker‐proxy 
$ curl ‐v http://localhost:3000 
* Connected to localhost (127.0.0.1) port 3000 (#0) 
> GET / HTTP/1.1 
> User‐Agent: curl/7.35.0 
> Host: localhost:3000 
> Accept: */* 
>< 
HTTP/1.1 200 OK 
[...]
MORE FIG COMMANDS 
$ fig ps 
Name Command State Ports 
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
todo_db_1 postgres Up 49160‐>5432/tcp 
todo_web_1 bundle exec rails server Up 3000‐>3000/tcp 
# if we remove the :3000 for the web port in the fig.yml 
$ fig scale web=2 
Starting todo_web_2... 
$ fig ps 
Name Command State Ports 
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
todo_db_1 postgres Up 49172‐>5432/tcp 
todo_web_2 bundle exec rails server Up 49174‐>3000/tcp 
todo_web_1 bundle exec rails server Up 49173‐>3000/tcp
VERY OPINIONATED TIPS 
Leverage the cache. 
$ time docker build ‐t rubyday/todo . 
# ==> 0m1.384s 
$ touch app/models/user.rb && time docker build ‐t rubyday/todo . 
# ==> 0m4.835s 
# Move the ADD . statement above bundle, then rebuild from scratch 
$ touch app/model/user.rb && time docker build ‐t rubyday/todo . 
# ==> 1m54.277s
VERY OPINIONATED TIPS 
Choose your storage driver wisely. 
devicemapper is slower. AUFS works ok. 
BTRFS is ... well... btrfs the future.
VERY OPINIONATED TIPS 
Always tag your image(s). 
Always pull supplying a tag. 
Always use a tag for FROM. 
Don't rely on :latest tag.
VERY OPINIONATED TIPS 
If possible, avoid run+commit. 
Prefer Dockerfiles. 
Waaaaaay more reproducible.
VERY OPINIONATED TIPS 
Installing ssh into the container is not clever. 
NSINIT is your friend (gist) 
https://gist.github.com/ubergarm/ed42ebbea293350c30a6
VERY OPINIONATED TIPS 
One process per container. Don't fork. 
Don't doublefork either. Stay in foreground.
VERY OPINIONATED TIPS 
Use a process manager. 
Both upstart or systemd are good at it. 
Run containers without the ‐d.
THANKS! 
That's all. For now.
QUESTIONS? 
QUESTIONS?
SHAMELESS PLUG 
These slides were made with applause 
https://github.com/Granze/applause 
Go check it out, it's AWESOME!

More Related Content

What's hot

DCSF19 Dockerfile Best Practices
DCSF19 Dockerfile Best PracticesDCSF19 Dockerfile Best Practices
DCSF19 Dockerfile Best PracticesDocker, Inc.
 
Docker workshop 0507 Taichung
Docker workshop 0507 Taichung Docker workshop 0507 Taichung
Docker workshop 0507 Taichung Paul Chao
 
Real World Experience of Running Docker in Development and Production
Real World Experience of Running Docker in Development and ProductionReal World Experience of Running Docker in Development and Production
Real World Experience of Running Docker in Development and ProductionBen Hall
 
DockerCon EU 2018 - Dockerfile Best Practices
DockerCon EU 2018 - Dockerfile Best PracticesDockerCon EU 2018 - Dockerfile Best Practices
DockerCon EU 2018 - Dockerfile Best PracticesTibor Vass
 
Running Docker in Development & Production (DevSum 2015)
Running Docker in Development & Production (DevSum 2015)Running Docker in Development & Production (DevSum 2015)
Running Docker in Development & Production (DevSum 2015)Ben Hall
 
Docker Warsaw Meetup 12/2017 - DockerCon 2017 Recap
Docker Warsaw Meetup 12/2017 - DockerCon 2017 RecapDocker Warsaw Meetup 12/2017 - DockerCon 2017 Recap
Docker Warsaw Meetup 12/2017 - DockerCon 2017 RecapKrzysztof Sobczak
 
Python virtualenv & pip in 90 minutes
Python virtualenv & pip in 90 minutesPython virtualenv & pip in 90 minutes
Python virtualenv & pip in 90 minutesLarry Cai
 
Making environment for_infrastructure_as_code
Making environment for_infrastructure_as_codeMaking environment for_infrastructure_as_code
Making environment for_infrastructure_as_codeSoshi Nemoto
 
Vagrant and docker
Vagrant and dockerVagrant and docker
Vagrant and dockerDuckDuckGo
 
Docker workshop DevOpsDays Amsterdam 2014
Docker workshop DevOpsDays Amsterdam 2014Docker workshop DevOpsDays Amsterdam 2014
Docker workshop DevOpsDays Amsterdam 2014Pini Reznik
 
Build service with_docker_in_90mins
Build service with_docker_in_90minsBuild service with_docker_in_90mins
Build service with_docker_in_90minsLarry Cai
 
Reproducibility of computational workflows is automated using continuous anal...
Reproducibility of computational workflows is automated using continuous anal...Reproducibility of computational workflows is automated using continuous anal...
Reproducibility of computational workflows is automated using continuous anal...Kento Aoyama
 
Provisioning & Deploying with Docker
Provisioning & Deploying with DockerProvisioning & Deploying with Docker
Provisioning & Deploying with DockerErica Windisch
 
Docker & FieldAware
Docker & FieldAwareDocker & FieldAware
Docker & FieldAwareJakub Jarosz
 

What's hot (18)

DCSF19 Dockerfile Best Practices
DCSF19 Dockerfile Best PracticesDCSF19 Dockerfile Best Practices
DCSF19 Dockerfile Best Practices
 
Docker workshop 0507 Taichung
Docker workshop 0507 Taichung Docker workshop 0507 Taichung
Docker workshop 0507 Taichung
 
Docker perl build
Docker perl buildDocker perl build
Docker perl build
 
Docker by Example - Basics
Docker by Example - Basics Docker by Example - Basics
Docker by Example - Basics
 
Real World Experience of Running Docker in Development and Production
Real World Experience of Running Docker in Development and ProductionReal World Experience of Running Docker in Development and Production
Real World Experience of Running Docker in Development and Production
 
DockerCon EU 2018 - Dockerfile Best Practices
DockerCon EU 2018 - Dockerfile Best PracticesDockerCon EU 2018 - Dockerfile Best Practices
DockerCon EU 2018 - Dockerfile Best Practices
 
Running Docker in Development & Production (DevSum 2015)
Running Docker in Development & Production (DevSum 2015)Running Docker in Development & Production (DevSum 2015)
Running Docker in Development & Production (DevSum 2015)
 
Docker
DockerDocker
Docker
 
Docker by Example - Quiz
Docker by Example - QuizDocker by Example - Quiz
Docker by Example - Quiz
 
Docker Warsaw Meetup 12/2017 - DockerCon 2017 Recap
Docker Warsaw Meetup 12/2017 - DockerCon 2017 RecapDocker Warsaw Meetup 12/2017 - DockerCon 2017 Recap
Docker Warsaw Meetup 12/2017 - DockerCon 2017 Recap
 
Python virtualenv & pip in 90 minutes
Python virtualenv & pip in 90 minutesPython virtualenv & pip in 90 minutes
Python virtualenv & pip in 90 minutes
 
Making environment for_infrastructure_as_code
Making environment for_infrastructure_as_codeMaking environment for_infrastructure_as_code
Making environment for_infrastructure_as_code
 
Vagrant and docker
Vagrant and dockerVagrant and docker
Vagrant and docker
 
Docker workshop DevOpsDays Amsterdam 2014
Docker workshop DevOpsDays Amsterdam 2014Docker workshop DevOpsDays Amsterdam 2014
Docker workshop DevOpsDays Amsterdam 2014
 
Build service with_docker_in_90mins
Build service with_docker_in_90minsBuild service with_docker_in_90mins
Build service with_docker_in_90mins
 
Reproducibility of computational workflows is automated using continuous anal...
Reproducibility of computational workflows is automated using continuous anal...Reproducibility of computational workflows is automated using continuous anal...
Reproducibility of computational workflows is automated using continuous anal...
 
Provisioning & Deploying with Docker
Provisioning & Deploying with DockerProvisioning & Deploying with Docker
Provisioning & Deploying with Docker
 
Docker & FieldAware
Docker & FieldAwareDocker & FieldAware
Docker & FieldAware
 

Viewers also liked

Docker dev ops for cd meetup 12-14
Docker dev ops for cd meetup 12-14Docker dev ops for cd meetup 12-14
Docker dev ops for cd meetup 12-14Simon Storm
 
How Docker Accelerates Continuous Development at Codefresh
How Docker Accelerates Continuous Development at CodefreshHow Docker Accelerates Continuous Development at Codefresh
How Docker Accelerates Continuous Development at CodefreshCodefresh
 
Codefresh + BlazeMeter Webinar: Continuous Testing for Containerized Applicat...
Codefresh + BlazeMeter Webinar: Continuous Testing for Containerized Applicat...Codefresh + BlazeMeter Webinar: Continuous Testing for Containerized Applicat...
Codefresh + BlazeMeter Webinar: Continuous Testing for Containerized Applicat...Codefresh
 
Codefresh + Cloud 66 webinar: Testing Strategies for Docker Driven Development
Codefresh + Cloud 66 webinar: Testing Strategies for Docker Driven DevelopmentCodefresh + Cloud 66 webinar: Testing Strategies for Docker Driven Development
Codefresh + Cloud 66 webinar: Testing Strategies for Docker Driven DevelopmentCodefresh
 
Docker driven development pipeline webinar (1)
Docker driven development pipeline webinar (1)Docker driven development pipeline webinar (1)
Docker driven development pipeline webinar (1)Codefresh
 
Docker for Developers: Dev, Test, Deploy @ BucksCo Devops at MeetMe HQ
Docker for Developers: Dev, Test, Deploy @ BucksCo Devops at MeetMe HQDocker for Developers: Dev, Test, Deploy @ BucksCo Devops at MeetMe HQ
Docker for Developers: Dev, Test, Deploy @ BucksCo Devops at MeetMe HQErica Windisch
 
Containers #101 Meetup: Containers and OpenStack
Containers #101 Meetup: Containers and OpenStackContainers #101 Meetup: Containers and OpenStack
Containers #101 Meetup: Containers and OpenStackCodefresh
 
Chef Cookbook Testing and Continuous Integration
Chef Cookbook Testing and Continuous IntegrationChef Cookbook Testing and Continuous Integration
Chef Cookbook Testing and Continuous IntegrationJulian Dunn
 
Chef Fundamentals Training Series Module 1: Overview of Chef
Chef Fundamentals Training Series Module 1: Overview of ChefChef Fundamentals Training Series Module 1: Overview of Chef
Chef Fundamentals Training Series Module 1: Overview of ChefChef Software, Inc.
 
Overview of Chef - Fundamentals Webinar Series Part 1
Overview of Chef - Fundamentals Webinar Series Part 1Overview of Chef - Fundamentals Webinar Series Part 1
Overview of Chef - Fundamentals Webinar Series Part 1Chef
 
Intro to Codefresh YAML
Intro to Codefresh YAML  Intro to Codefresh YAML
Intro to Codefresh YAML Codefresh
 
Chef for DevOps - an Introduction
Chef for DevOps - an IntroductionChef for DevOps - an Introduction
Chef for DevOps - an IntroductionSanjeev Sharma
 
Jenkins and Chef: Infrastructure CI and Automated Deployment
Jenkins and Chef: Infrastructure CI and Automated DeploymentJenkins and Chef: Infrastructure CI and Automated Deployment
Jenkins and Chef: Infrastructure CI and Automated DeploymentDan Stine
 

Viewers also liked (14)

Intro to Chef
Intro to ChefIntro to Chef
Intro to Chef
 
Docker dev ops for cd meetup 12-14
Docker dev ops for cd meetup 12-14Docker dev ops for cd meetup 12-14
Docker dev ops for cd meetup 12-14
 
How Docker Accelerates Continuous Development at Codefresh
How Docker Accelerates Continuous Development at CodefreshHow Docker Accelerates Continuous Development at Codefresh
How Docker Accelerates Continuous Development at Codefresh
 
Codefresh + BlazeMeter Webinar: Continuous Testing for Containerized Applicat...
Codefresh + BlazeMeter Webinar: Continuous Testing for Containerized Applicat...Codefresh + BlazeMeter Webinar: Continuous Testing for Containerized Applicat...
Codefresh + BlazeMeter Webinar: Continuous Testing for Containerized Applicat...
 
Codefresh + Cloud 66 webinar: Testing Strategies for Docker Driven Development
Codefresh + Cloud 66 webinar: Testing Strategies for Docker Driven DevelopmentCodefresh + Cloud 66 webinar: Testing Strategies for Docker Driven Development
Codefresh + Cloud 66 webinar: Testing Strategies for Docker Driven Development
 
Docker driven development pipeline webinar (1)
Docker driven development pipeline webinar (1)Docker driven development pipeline webinar (1)
Docker driven development pipeline webinar (1)
 
Docker for Developers: Dev, Test, Deploy @ BucksCo Devops at MeetMe HQ
Docker for Developers: Dev, Test, Deploy @ BucksCo Devops at MeetMe HQDocker for Developers: Dev, Test, Deploy @ BucksCo Devops at MeetMe HQ
Docker for Developers: Dev, Test, Deploy @ BucksCo Devops at MeetMe HQ
 
Containers #101 Meetup: Containers and OpenStack
Containers #101 Meetup: Containers and OpenStackContainers #101 Meetup: Containers and OpenStack
Containers #101 Meetup: Containers and OpenStack
 
Chef Cookbook Testing and Continuous Integration
Chef Cookbook Testing and Continuous IntegrationChef Cookbook Testing and Continuous Integration
Chef Cookbook Testing and Continuous Integration
 
Chef Fundamentals Training Series Module 1: Overview of Chef
Chef Fundamentals Training Series Module 1: Overview of ChefChef Fundamentals Training Series Module 1: Overview of Chef
Chef Fundamentals Training Series Module 1: Overview of Chef
 
Overview of Chef - Fundamentals Webinar Series Part 1
Overview of Chef - Fundamentals Webinar Series Part 1Overview of Chef - Fundamentals Webinar Series Part 1
Overview of Chef - Fundamentals Webinar Series Part 1
 
Intro to Codefresh YAML
Intro to Codefresh YAML  Intro to Codefresh YAML
Intro to Codefresh YAML
 
Chef for DevOps - an Introduction
Chef for DevOps - an IntroductionChef for DevOps - an Introduction
Chef for DevOps - an Introduction
 
Jenkins and Chef: Infrastructure CI and Automated Deployment
Jenkins and Chef: Infrastructure CI and Automated DeploymentJenkins and Chef: Infrastructure CI and Automated Deployment
Jenkins and Chef: Infrastructure CI and Automated Deployment
 

Similar to Streamline your development environment with docker

Learn docker in 90 minutes
Learn docker in 90 minutesLearn docker in 90 minutes
Learn docker in 90 minutesLarry Cai
 
Be a better developer with Docker (revision 3)
Be a better developer with Docker (revision 3)Be a better developer with Docker (revision 3)
Be a better developer with Docker (revision 3)Nicola Paolucci
 
The Dockerfile Explosion and the Need for Higher Level Tools by Gareth Rushgrove
The Dockerfile Explosion and the Need for Higher Level Tools by Gareth RushgroveThe Dockerfile Explosion and the Need for Higher Level Tools by Gareth Rushgrove
The Dockerfile Explosion and the Need for Higher Level Tools by Gareth RushgroveDocker, Inc.
 
Docker Demo @ IuK Seminar
Docker Demo @ IuK SeminarDocker Demo @ IuK Seminar
Docker Demo @ IuK SeminarMartin Scharm
 
Docker in Action
Docker in ActionDocker in Action
Docker in ActionAlper Kanat
 
Docker for mere mortals
Docker for mere mortalsDocker for mere mortals
Docker for mere mortalsHenryk Konsek
 
Ruby microservices with Docker - Sergii Koba
Ruby microservices with Docker -  Sergii KobaRuby microservices with Docker -  Sergii Koba
Ruby microservices with Docker - Sergii KobaRuby Meditation
 
Использование Docker в CI / Александр Акбашев (HERE Technologies)
Использование Docker в CI / Александр Акбашев (HERE Technologies)Использование Docker в CI / Александр Акбашев (HERE Technologies)
Использование Docker в CI / Александр Акбашев (HERE Technologies)Ontico
 
Introduction to Docker
Introduction  to DockerIntroduction  to Docker
Introduction to DockerJian Wu
 
Introduction to Docker - Learning containerization XP conference 2016
Introduction to Docker - Learning containerization  XP conference 2016Introduction to Docker - Learning containerization  XP conference 2016
Introduction to Docker - Learning containerization XP conference 2016XP Conference India
 
桃園市教育局Docker技術入門與實作
桃園市教育局Docker技術入門與實作桃園市教育局Docker技術入門與實作
桃園市教育局Docker技術入門與實作Philip Zheng
 
Hands-On Session Docker
Hands-On Session DockerHands-On Session Docker
Hands-On Session DockerLinetsChile
 
時代在變 Docker 要會:台北 Docker 一日入門篇
時代在變 Docker 要會:台北 Docker 一日入門篇時代在變 Docker 要會:台北 Docker 一日入門篇
時代在變 Docker 要會:台北 Docker 一日入門篇Philip Zheng
 
Docker command
Docker commandDocker command
Docker commandEric Ahn
 

Similar to Streamline your development environment with docker (20)

Learn docker in 90 minutes
Learn docker in 90 minutesLearn docker in 90 minutes
Learn docker in 90 minutes
 
Docker as an every day work tool
Docker as an every day work toolDocker as an every day work tool
Docker as an every day work tool
 
Be a better developer with Docker (revision 3)
Be a better developer with Docker (revision 3)Be a better developer with Docker (revision 3)
Be a better developer with Docker (revision 3)
 
The Dockerfile Explosion and the Need for Higher Level Tools by Gareth Rushgrove
The Dockerfile Explosion and the Need for Higher Level Tools by Gareth RushgroveThe Dockerfile Explosion and the Need for Higher Level Tools by Gareth Rushgrove
The Dockerfile Explosion and the Need for Higher Level Tools by Gareth Rushgrove
 
Docker Demo @ IuK Seminar
Docker Demo @ IuK SeminarDocker Demo @ IuK Seminar
Docker Demo @ IuK Seminar
 
Docker in Action
Docker in ActionDocker in Action
Docker in Action
 
Docker for mere mortals
Docker for mere mortalsDocker for mere mortals
Docker for mere mortals
 
Ruby microservices with Docker - Sergii Koba
Ruby microservices with Docker -  Sergii KobaRuby microservices with Docker -  Sergii Koba
Ruby microservices with Docker - Sergii Koba
 
Docker by Example - Basics
Docker by Example - Basics Docker by Example - Basics
Docker by Example - Basics
 
Learning Docker with Thomas
Learning Docker with ThomasLearning Docker with Thomas
Learning Docker with Thomas
 
Использование Docker в CI / Александр Акбашев (HERE Technologies)
Использование Docker в CI / Александр Акбашев (HERE Technologies)Использование Docker в CI / Александр Акбашев (HERE Technologies)
Использование Docker в CI / Александр Акбашев (HERE Technologies)
 
Docker
DockerDocker
Docker
 
Introducing Docker
Introducing DockerIntroducing Docker
Introducing Docker
 
Introduction to Docker
Introduction  to DockerIntroduction  to Docker
Introduction to Docker
 
Introduction to Docker - Learning containerization XP conference 2016
Introduction to Docker - Learning containerization  XP conference 2016Introduction to Docker - Learning containerization  XP conference 2016
Introduction to Docker - Learning containerization XP conference 2016
 
桃園市教育局Docker技術入門與實作
桃園市教育局Docker技術入門與實作桃園市教育局Docker技術入門與實作
桃園市教育局Docker技術入門與實作
 
Docker, c'est bonheur !
Docker, c'est bonheur !Docker, c'est bonheur !
Docker, c'est bonheur !
 
Hands-On Session Docker
Hands-On Session DockerHands-On Session Docker
Hands-On Session Docker
 
時代在變 Docker 要會:台北 Docker 一日入門篇
時代在變 Docker 要會:台北 Docker 一日入門篇時代在變 Docker 要會:台北 Docker 一日入門篇
時代在變 Docker 要會:台北 Docker 一日入門篇
 
Docker command
Docker commandDocker command
Docker command
 

Recently uploaded

Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf31events.com
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprisepreethippts
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Mater
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEEVICTOR MAESTRE RAMIREZ
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
VK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web DevelopmentVK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web Developmentvyaparkranti
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfExploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfkalichargn70th171
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentationvaddepallysandeep122
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 

Recently uploaded (20)

Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprise
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
VK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web DevelopmentVK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web Development
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfExploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
 
Advantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your BusinessAdvantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your Business
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentation
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 

Streamline your development environment with docker

  • 1. Streamline your dev env with Docker Giacomo Bagnoli, #RUBYDAY2014
  • 2. WHOAMI Giacomo Bagnoli Currently Backend Engineer at Gild Previously at Amazon and Asidev Twitter: @gbagnoli Github: gbagnoli about.me/gbagnoli
  • 3. WHAT'S WRONG WITH MY DEV ENVIRONMENT? Nothing in particular. It's not* broken, so let's fix it. * conditions apply
  • 4. WHAT'S WRONG WITH MY DEV ENVIRONMENT? Your development environment is probably a beautiful, unique snowflake Photo credits: https://www.flickr.com/photos/amagill/4223790595/
  • 5. WHAT'S DOCKER, ANYWAY?!? Open source platform Docker Engine Container management runtime Packaging tools for images Docker Hub
  • 6. CONTAINERS, UH? Operating system-level virtualization* Runs multiple isolated linux systems On a single host, with a single kernel No /sbin/init, no device emulation Think them as chroot on steroids Isolation provided by linux cgroups and namespaces Resource limiting and prioritization via cgroups Resource usage accounting via cgroups * not a virtualization method, containers != VM
  • 7. DOCKER IMAGES (0) Portable, read-only layers. Images are composed at run-time to form the container root FS using an union filesystem. Processes tricked to see the filesystem as R/W. The writable layer is discarded if the container is not committed. The read-only and portable properties are important as they enable sharing (via the docker hub).
  • 8. DOCKER IMAGES (1) Docker images form a Direct Acyclic Graph. Each layer is cached (possibly) and reused by other images. This means that if multiple images derive from debian:wheezy, that particular image is shared by all of them (thus downloaded once). Images are pushed/pull to/from the docker hub.
  • 9. DOCKER IMAGES (2) $ docker pull ubuntu:14.04 $ docker pull ubuntu:12.04 $ docker pull redis:2.8.13 $ docker pull debian:wheezy $ docker pull mongo:2.6.4 $ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE redis 2.8.13 dd52dc9c8f76 9 minutes ago 98.44 MB mongo 2.6.4 dd1f260c0731 12 minutes ago 391.2 MB debian wheezy 9cdcc6025135 18 hours ago 85.19 MB ubuntu 14.04 96864a7d2df3 2 days ago 204.4 MB ubuntu 12.04 ec966722cde4 2 days ago 103.8 MB
  • 10. DOCKER IMAGES (3) $ docker images ‐‐tree └─511136ea3c5a Virtual Size: 0 B └─b37448882294 Virtual Size: 85.19 MB └─9cdcc6025135 Virtual Size: 85.19 MB Tags: debian:wheezy ├─e365f7cdb352 Virtual Size: 85.52 MB │ └─b15940870e43 Virtual Size: 85.52 MB │ └─22ad4fc6b16f Virtual Size: 98.44 MB │ └─bd1e22dd175d Virtual Size: 98.44 MB │ └─3b1ce200fdad Virtual Size: 98.44 MB │ └─dd52dc9c8f76 Virtual Size: 98.44 MB Tags: redis:2.8.13 └─49fd1ae472a8 Virtual Size: 85.52 MB └─6c203838fd07 Virtual Size: 99.62 MB └─b1cd74f30329 Virtual Size: 391.2 MB └─9d0a3438646f Virtual Size: 391.2 MB └─dd1f260c0731 Virtual Size: 391.2 MB Tags: mongo:2.6.4
  • 11. LET'S BUILD A RUBY2 IMAGE Ubuntu 14.04 image has no ruby at all. Repos have ruby 1.9. Let's create an image with 2.1 as default. Dockerfile: FROM ubuntu:14.04 MAINTAINER Giacomo Bagnoli <gbagnoli@gmail.com> RUN echo "deb http://ppa.launchpad.net/brightbox/ruby‐ng/ubuntu trusty main" > /etc/apt/sources.list.d/ruby‐ng.list RUN apt‐key adv ‐‐keyserver hkp://keyserver.ubuntu.com:80 ‐‐recv‐keys C3173AA6 RUN apt‐get update RUN apt‐get install ‐y ruby2.1 Build! $ docker build ‐‐rm ‐t rubyday/ruby:2.1 .
  • 12. RUBY2 IMAGE Each directive in the Dockerfile adds a layer $ docker images ‐‐tree └─96864a7d2df3 Virtual Size: 204.4 MB Tags: ubuntu:14.04 └─8f1b6341c5be Virtual Size: 204.4 MB # MAINTAINER └─d323cc59da91 Virtual Size: 204.4 MB # RUN └─724a6664d97a Virtual Size: 204.4 MB # RUN └─8614dab05fbe Virtual Size: 224.8 MB # RUN └─d7ae4a198781 Virtual Size: 257.2 MB Tags: rubyday/ruby:2.1 # RUN $ docker run ‐t rubyday/ruby:2.1 ruby ‐v ruby 2.1.2p95 (2014‐05‐08 revision 45877) [x86_64‐linux‐gnu] Woah, 53Mb. apt‐get update adds 20Mb to the image.
  • 13. I TRIED... Let's remove apt-get files by adding another RUN statement diff ‐‐git a/ruby2/Dockerfile b/ruby2/Dockerfile index dd37dcb..2b9c105 100644 ‐‐‐ a/ruby2/Dockerfile +++ b/ruby2/Dockerfile @@ ‐8,3 +8,4 @@ RUN echo "deb http://ppa.launchpad.net/brightbox/ruby‐ng/ubuntu trusty main" > / RUN apt‐key adv ‐‐keyserver hkp://keyserver.ubuntu.com:80 ‐‐recv‐keys C3173AA6 RUN apt‐get update RUN apt‐get install ‐y ruby2.1 +RUN rm ‐rf /var/lib/apt/lists/* /var/cache/apt/archives/*.deb
  • 15. LAYERS.. $ docker images ‐‐tree └─96864a7d2df3 Virtual Size: 204.4 MB Tags: ubuntu:14.04 └─8f1b6341c5be Virtual Size: 204.4 MB # MAINTAINER └─d323cc59da91 Virtual Size: 204.4 MB # RUN └─724a6664d97a Virtual Size: 204.4 MB # RUN └─8614dab05fbe Virtual Size: 224.8 MB # RUN └─d7ae4a198781 Virtual Size: 257.2 MB # RUN └─b8bb3ce3008e Virtual Size: 257.2 MB Tags: rubyday/ruby:2.1 # RUN Remember that every directive adds a layer. Layers are read only.
  • 16. LET'S TRY ONCE MORE Let's rewrite the Dockerfile FROM ubuntu:14.04 MAINTAINER Giacomo Bagnoli <gbagnoli@gmail.com> RUN echo "deb http://ppa.launchpad.net/brightbox/ruby‐ng/ubuntu trusty main" > /etc/apt/sources.list.d/ruby‐ng.list && apt‐key adv ‐‐keyserver hkp://keyserver.ubuntu.com:80 ‐‐recv‐keys C3173AA6 && apt‐get update && apt‐get install ‐y ruby2.1 && rm ‐rf /var/lib/apt/lists/* /var/cache/apt/archives/*.deb
  • 17. REBUILD Build: $ docker build ‐‐rm ‐t rubyday/ruby:2.1 . $ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE rubyday/ruby 2.1 b337a5c538f3 About a minute ago 236.9 MB └─96864a7d2df3 Virtual Size: 204.4 MB Tags: ubuntu:14.04 └─86ae939e2da3 Virtual Size: 204.4 MB # MAINTAINER └─b337a5c538f3 Virtual Size: 236.9 MB Tags: gild/ruby:2.1 # RUN yay!
  • 18. PAT ME ON THE BACK
  • 19. ... ONE MORE THING We probably want ‐dev packages and bundle Let's update the Dockerfile FROM ubuntu:14.04 MAINTAINER Giacomo Bagnoli RUN echo "deb http://ppa.launchpad.net/brightbox/ruby‐ng/ubuntu trusty main" > /etc/apt/sources.list.d/ruby‐ng.list RUN apt‐key adv ‐‐keyserver hkp://keyserver.ubuntu.com:80 ‐‐recv‐keys C3173AA6 RUN apt‐get update && apt‐get install ‐y build‐essential && apt‐get install ‐y ruby2.1 ruby2.1‐dev && update‐alternatives ‐‐set ruby /usr/bin/ruby2.1 && update‐alternatives ‐‐set gem /usr/bin/gem2.1 && rm ‐rf /var/lib/apt/lists/* /var/cache/apt/archives/*.deb RUN gem install bundle
  • 20. TIME FOR RAILS Let's try creating a Dockerfile for a rails app. The app is a random simple TODO list application found on Github. It's a rails4 application that uses SQL, nothing fancy. Let's assume we are developing this app targeting postgresql. Github url: https://github.com/gbagnoli/todo‐rails4‐angularjs
  • 21. A WORD ON LINKING In docker, we can access service(s) running in other container(s) via linking. Linking a container to another will setup some environment variables in it, allowing the container to discover and connect to the service. We will use this feature to access postgres from our app container.
  • 22. THE DOCKERFILE FROM rubyday/ruby:2.1 MAINTAINER Giacomo Bagnoli <gbagnoli@gmail.com> RUN adduser todo ‐‐home /opt/todo ‐‐shell /bin/bash ‐‐disabled‐password ‐‐gecos "" RUN apt‐get update && apt‐get install ‐y libpq‐dev nodejs && rm ‐rf /var/lib/apt/lists/* /var/cache/apt/archives/*.deb ADD Gemfile /opt/todo/ ADD Gemfile.lock /opt/todo/ RUN chown ‐R todo:todo /opt/todo RUN su ‐c "D=/opt/todo/bundle; mkdir $D && bundle install ‐‐deployment ‐‐path $D" ‐s /bin/bash ‐l todo WORKDIR /opt/todo EXPOSE 3000 ADD . /opt/todo RUN chown ‐R todo:todo /opt/todo USER todo ENTRYPOINT ["/bin/bash", "/opt/todo/bin/docker_entrypoint.sh"] CMD ["bundle", "exec", "rails", "server"]
  • 23. DOCKERFILE EXPLAINED (0) FROM rubyday/ruby:2.1 MAINTAINER Giacomo Bagnoli <gbagnoli@gmail.com>
  • 24. DOCKERFILE EXPLAINED (1) RUN adduser todo ‐‐home /opt/todo ‐‐shell /bin/bash ‐‐disabled‐password ‐‐gecos "" RUN apt‐get update && apt‐get install ‐y libpq‐dev nodejs && rm ‐rf /var/lib/apt/lists/* /var/cache/apt/archives/*.deb
  • 25. DOCKERFILE EXPLAINED (2) ADD Gemfile /opt/todo/ ADD Gemfile.lock /opt/todo/ RUN chown ‐R todo:todo /opt/todo RUN su ‐c "D=/opt/todo/bundle; mkdir $D && bundle install ‐‐deployment ‐‐path $D" ‐s /bin/bash ‐l todo
  • 26. DOCKERFILE EXPLAINED (3) WORKDIR /opt/todo EXPOSE 3000 ADD . /opt/todo RUN chown ‐R todo:todo /opt/todo
  • 27. DOCKERFILE EXPLAINED (4) USER todo ENTRYPOINT ["/bin/bash", "/opt/todo/bin/docker_entrypoint.sh"] CMD ["bundle", "exec", "rails", "server"]
  • 28. POSTGRES CONTAINER (0) $ docker pull postgres:9.3 $ docker run ‐d ‐‐name postgres ‐t postgres:9.3 a5723351c46ce015d585dd49f230ecb376557d0b955f233dbff3bf92f3a6721d $ docker ps CONTAINER ID IMAGE [...] PORTS NAMES a5723351c46c postgres:9 [...] 5432/tcp postgres This container EXPOSEs port 5432. Question is, how do we connect to it?
  • 29. We can't just hardcode its ip address, as it defeats the purpose... $ docker inspect postgres | grep NetworkSettings ‐A 9 "NetworkSettings": { "Bridge": "docker0", "Gateway": "172.17.42.1", "IPAddress": "172.17.0.4", "IPPrefixLen": 16, "PortMapping": null, "Ports": { "5432/tcp": null } }, POSTGRES CONTAINER (1)
  • 30. THE WRAPPER SCRIPT (0) In the Dockerfile, an ENTRYPOINT was specified. #!/bin/bash # exit with error if a variable is unbound (not set) set ‐u # exit with error if a command returns a non‐zero status set ‐e PGADDR=$DB_PORT_5432_TCP_ADDR PGPORT=$DB_PORT_5432_TCP_PORT PGDBNAME="${DATABASE_NAME:‐todo}" PGUSER="${DATABASE_USER:‐postgres}" # export database configuration for rails. export DATABASE_URL="postgresql://${PGUSER}@${PGADDR}:${PGPORT}/${PGDBNAME}" # exec what the user wants exec "$@"
  • 31. THE WRAPPER SCRIPT (1) Trying to execute the container will throw an error (it's a feature!) $ docker run ‐‐rm ‐‐name todoapp ‐t rubyday/todo /opt/todo/bin/docker_entrypoint.sh: line 6: DB_PORT_5432_TCP_ADDR: unbound variable
  • 32. LINKING! $ docker run ‐‐rm ‐‐link postgres:db ‐‐name todoapp ‐t rubyday/todo /bin/bash ‐c 'env' DB_ENV_PGDATA=/var/lib/postgresql/data DB_NAME=/todoapp/db DB_PORT_5432_TCP_ADDR=172.17.0.4 DB_PORT=tcp://172.17.0.4:5432 DB_ENV_LANG=en_US.utf8 DB_PORT_5432_TCP=tcp://172.17.0.4:5432 DB_ENV_PG_MAJOR=9.3 DB_PORT_5432_TCP_PORT=5432 DB_PORT_5432_TCP_PROTO=tcp DB_ENV_PG_VERSION=9.3.5‐1.pgdg70+1 DATABASE_URL=postgresql://postgres@172.17.0.4:5432/todo ‐‐link postgres:db link container named postgres with alias db alias db tells docker to prefix all variables with DB
  • 33. START! Pretty much standard business $ docker run ‐‐rm ‐‐link postgres:db ‐t rubyday/todo bundle exec rake db:create $ docker run ‐‐rm ‐‐link postgres:db ‐t rubyday/todo bundle exec rake db:schema:load $ docker run ‐‐link postgres:db ‐‐name todoapp ‐p 3000:3000 ‐d ‐t rubyday/todo 7540f7647309110c53d2349cf7c68d1388e0f43de3d5904396fa2bb4041b6b28 $ docker ps CONTAINER ID IMAGE [..] PORTS NAMES 7540f7647309 rubyday/todo:latest [..] 0.0.0.0:3000‐>3000/tcp todoapp a5723351c46c postgres:9 [..] 5432/tcp postgres,todoapp/db ‐p 3000:3000 creates a port forward from the host to the container
  • 34. DOES IT WORK? $ netstat -lnp | grep 3000 tcp6 0 0 :::3000 :::* LISTEN 3645/docker-proxy $ curl -v http://localhost:3000 * Connected to localhost (127.0.0.1) port 3000 (#0) > GET / HTTP/1.1 > User-Agent: curl/7.35.0 > Host: localhost:3000 > Accept: */* >< HTTP/1.1 200 OK [...] Good.
  • 35. TOO MUCH WORK. LET'S AUTOMATE Enters FIG. fig.yml: web: build: . links: - db ports: - "3000:3000" db: image: postgres:9.3 ports: - "5432"
  • 36. ..SMALL TWEAK FOR FIG diff --git a/bin/docker_entrypoint.sh b/bin/docker_entrypoint.sh index 0775ece..b69980c 100644 --- a/bin/docker_entrypoint.sh +++ b/bin/docker_entrypoint.sh @@ -3,8 +3,8 @@ set -u set -e -PGADDR=$DB_PORT_5432_TCP_ADDR -PGPORT=$DB_PORT_5432_TCP_PORT +PGADDR=$DB_1_PORT_5432_TCP_ADDR +PGPORT=$DB_1_PORT_5432_TCP_PORT PGDBNAME="${DATABASE_NAME:-todo}" PGUSER="${DATABASE_USER:-postgres}"
  • 37. PROFIT! $ fig up ‐d # familiar, huh? $ fig run web bundle exec rake db:create $ fig run web bundle exec rake db:schema:load $ netstat ‐lnp | grep 3000 tcp6 0 0 :::3000 :::* LISTEN 24727/docker‐proxy $ curl ‐v http://localhost:3000 * Connected to localhost (127.0.0.1) port 3000 (#0) > GET / HTTP/1.1 > User‐Agent: curl/7.35.0 > Host: localhost:3000 > Accept: */* >< HTTP/1.1 200 OK [...]
  • 38. MORE FIG COMMANDS $ fig ps Name Command State Ports ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ todo_db_1 postgres Up 49160‐>5432/tcp todo_web_1 bundle exec rails server Up 3000‐>3000/tcp # if we remove the :3000 for the web port in the fig.yml $ fig scale web=2 Starting todo_web_2... $ fig ps Name Command State Ports ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ todo_db_1 postgres Up 49172‐>5432/tcp todo_web_2 bundle exec rails server Up 49174‐>3000/tcp todo_web_1 bundle exec rails server Up 49173‐>3000/tcp
  • 39. VERY OPINIONATED TIPS Leverage the cache. $ time docker build ‐t rubyday/todo . # ==> 0m1.384s $ touch app/models/user.rb && time docker build ‐t rubyday/todo . # ==> 0m4.835s # Move the ADD . statement above bundle, then rebuild from scratch $ touch app/model/user.rb && time docker build ‐t rubyday/todo . # ==> 1m54.277s
  • 40. VERY OPINIONATED TIPS Choose your storage driver wisely. devicemapper is slower. AUFS works ok. BTRFS is ... well... btrfs the future.
  • 41. VERY OPINIONATED TIPS Always tag your image(s). Always pull supplying a tag. Always use a tag for FROM. Don't rely on :latest tag.
  • 42. VERY OPINIONATED TIPS If possible, avoid run+commit. Prefer Dockerfiles. Waaaaaay more reproducible.
  • 43. VERY OPINIONATED TIPS Installing ssh into the container is not clever. NSINIT is your friend (gist) https://gist.github.com/ubergarm/ed42ebbea293350c30a6
  • 44. VERY OPINIONATED TIPS One process per container. Don't fork. Don't doublefork either. Stay in foreground.
  • 45. VERY OPINIONATED TIPS Use a process manager. Both upstart or systemd are good at it. Run containers without the ‐d.
  • 48. SHAMELESS PLUG These slides were made with applause https://github.com/Granze/applause Go check it out, it's AWESOME!