SlideShare a Scribd company logo
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!
Ad

More Related Content

What's hot (18)

DCSF19 Dockerfile Best Practices
DCSF19 Dockerfile Best PracticesDCSF19 Dockerfile Best Practices
DCSF19 Dockerfile Best Practices
Docker, Inc.
 
Docker workshop 0507 Taichung
Docker workshop 0507 Taichung Docker workshop 0507 Taichung
Docker workshop 0507 Taichung
Paul Chao
 
Docker perl build
Docker perl buildDocker perl build
Docker perl build
Workhorse Computing
 
Docker by Example - Basics
Docker by Example - Basics Docker by Example - Basics
Docker by Example - Basics
CodeOps Technologies LLP
 
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
Ben Hall
 
DockerCon EU 2018 - Dockerfile Best Practices
DockerCon EU 2018 - Dockerfile Best PracticesDockerCon EU 2018 - Dockerfile Best Practices
DockerCon EU 2018 - Dockerfile Best Practices
Tibor 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
DockerDocker
Docker
Brian Hogan
 
Docker by Example - Quiz
Docker by Example - QuizDocker by Example - Quiz
Docker by Example - Quiz
CodeOps Technologies LLP
 
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
Krzysztof Sobczak
 
Python virtualenv & pip in 90 minutes
Python virtualenv & pip in 90 minutesPython virtualenv & pip in 90 minutes
Python virtualenv & pip in 90 minutes
Larry Cai
 
Making environment for_infrastructure_as_code
Making environment for_infrastructure_as_codeMaking environment for_infrastructure_as_code
Making environment for_infrastructure_as_code
Soshi Nemoto
 
Vagrant and docker
Vagrant and dockerVagrant and docker
Vagrant and docker
DuckDuckGo
 
Docker workshop DevOpsDays Amsterdam 2014
Docker workshop DevOpsDays Amsterdam 2014Docker workshop DevOpsDays Amsterdam 2014
Docker workshop DevOpsDays Amsterdam 2014
Pini Reznik
 
Build service with_docker_in_90mins
Build service with_docker_in_90minsBuild service with_docker_in_90mins
Build service with_docker_in_90mins
Larry 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 Docker
Erica Windisch
 
Docker & FieldAware
Docker & FieldAwareDocker & FieldAware
Docker & FieldAware
Jakub Jarosz
 
DCSF19 Dockerfile Best Practices
DCSF19 Dockerfile Best PracticesDCSF19 Dockerfile Best Practices
DCSF19 Dockerfile Best Practices
Docker, 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 Production
Ben Hall
 
DockerCon EU 2018 - Dockerfile Best Practices
DockerCon EU 2018 - Dockerfile Best PracticesDockerCon EU 2018 - Dockerfile Best Practices
DockerCon EU 2018 - Dockerfile Best Practices
Tibor 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 Recap
Krzysztof Sobczak
 
Python virtualenv & pip in 90 minutes
Python virtualenv & pip in 90 minutesPython virtualenv & pip in 90 minutes
Python virtualenv & pip in 90 minutes
Larry Cai
 
Making environment for_infrastructure_as_code
Making environment for_infrastructure_as_codeMaking environment for_infrastructure_as_code
Making environment for_infrastructure_as_code
Soshi Nemoto
 
Vagrant and docker
Vagrant and dockerVagrant and docker
Vagrant and docker
DuckDuckGo
 
Docker workshop DevOpsDays Amsterdam 2014
Docker workshop DevOpsDays Amsterdam 2014Docker workshop DevOpsDays Amsterdam 2014
Docker workshop DevOpsDays Amsterdam 2014
Pini Reznik
 
Build service with_docker_in_90mins
Build service with_docker_in_90minsBuild service with_docker_in_90mins
Build service with_docker_in_90mins
Larry 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 Docker
Erica Windisch
 
Docker & FieldAware
Docker & FieldAwareDocker & FieldAware
Docker & FieldAware
Jakub Jarosz
 

Viewers also liked (14)

Intro to Chef
Intro to ChefIntro to Chef
Intro to Chef
Giacomo Bagnoli
 
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
Simon 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 Codefresh
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
 
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
Codefresh
 
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 HQ
Erica Windisch
 
Containers #101 Meetup: Containers and OpenStack
Containers #101 Meetup: Containers and OpenStackContainers #101 Meetup: Containers and OpenStack
Containers #101 Meetup: Containers and OpenStack
Codefresh
 
Chef Cookbook Testing and Continuous Integration
Chef Cookbook Testing and Continuous IntegrationChef Cookbook Testing and Continuous Integration
Chef Cookbook Testing and Continuous Integration
Julian 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 Chef
Chef 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 1
Chef
 
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 Introduction
Sanjeev 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 Deployment
Dan Stine
 
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
Simon 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 Codefresh
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
 
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
Codefresh
 
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 HQ
Erica Windisch
 
Containers #101 Meetup: Containers and OpenStack
Containers #101 Meetup: Containers and OpenStackContainers #101 Meetup: Containers and OpenStack
Containers #101 Meetup: Containers and OpenStack
Codefresh
 
Chef Cookbook Testing and Continuous Integration
Chef Cookbook Testing and Continuous IntegrationChef Cookbook Testing and Continuous Integration
Chef Cookbook Testing and Continuous Integration
Julian 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 Chef
Chef 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 1
Chef
 
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 Introduction
Sanjeev 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 Deployment
Dan Stine
 
Ad

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
Larry Cai
 
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
Przemyslaw Koltermann
 
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 Rushgrove
Docker, Inc.
 
Docker Demo @ IuK Seminar
Docker Demo @ IuK SeminarDocker Demo @ IuK Seminar
Docker Demo @ IuK Seminar
Martin Scharm
 
Docker in Action
Docker in ActionDocker in Action
Docker in Action
Alper Kanat
 
Docker for mere mortals
Docker for mere mortalsDocker for mere mortals
Docker for mere mortals
Henryk Konsek
 
Ruby microservices with Docker - Sergii Koba
Ruby microservices with Docker -  Sergii KobaRuby microservices with Docker -  Sergii Koba
Ruby microservices with Docker - Sergii Koba
Ruby Meditation
 
Docker by Example - Basics
Docker by Example - Basics Docker by Example - Basics
Docker by Example - Basics
Ganesh Samarthyam
 
Learning Docker with Thomas
Learning Docker with ThomasLearning Docker with Thomas
Learning Docker with Thomas
Thomas Tong, FRM, PMP
 
Использование Docker в CI / Александр Акбашев (HERE Technologies)
Использование Docker в CI / Александр Акбашев (HERE Technologies)Использование Docker в CI / Александр Акбашев (HERE Technologies)
Использование Docker в CI / Александр Акбашев (HERE Technologies)
Ontico
 
Docker
DockerDocker
Docker
The Software House
 
Introducing Docker
Introducing DockerIntroducing Docker
Introducing Docker
Francesco Pantano
 
Introduction to Docker
Introduction  to DockerIntroduction  to Docker
Introduction to Docker
Jian 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 2016
XP Conference India
 
桃園市教育局Docker技術入門與實作
桃園市教育局Docker技術入門與實作桃園市教育局Docker技術入門與實作
桃園市教育局Docker技術入門與實作
Philip Zheng
 
Docker, c'est bonheur !
Docker, c'est bonheur !Docker, c'est bonheur !
Docker, c'est bonheur !
Alexandre Salomé
 
Hands-On Session Docker
Hands-On Session DockerHands-On Session Docker
Hands-On Session Docker
LinetsChile
 
時代在變 Docker 要會:台北 Docker 一日入門篇
時代在變 Docker 要會:台北 Docker 一日入門篇時代在變 Docker 要會:台北 Docker 一日入門篇
時代在變 Docker 要會:台北 Docker 一日入門篇
Philip Zheng
 
Docker command
Docker commandDocker command
Docker command
Eric Ahn
 
Learn docker in 90 minutes
Learn docker in 90 minutesLearn docker in 90 minutes
Learn docker in 90 minutes
Larry 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 Rushgrove
Docker, Inc.
 
Docker Demo @ IuK Seminar
Docker Demo @ IuK SeminarDocker Demo @ IuK Seminar
Docker Demo @ IuK Seminar
Martin Scharm
 
Docker in Action
Docker in ActionDocker in Action
Docker in Action
Alper Kanat
 
Docker for mere mortals
Docker for mere mortalsDocker for mere mortals
Docker for mere mortals
Henryk Konsek
 
Ruby microservices with Docker - Sergii Koba
Ruby microservices with Docker -  Sergii KobaRuby microservices with Docker -  Sergii Koba
Ruby microservices with Docker - Sergii Koba
Ruby 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 Docker
Jian 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 2016
XP Conference India
 
桃園市教育局Docker技術入門與實作
桃園市教育局Docker技術入門與實作桃園市教育局Docker技術入門與實作
桃園市教育局Docker技術入門與實作
Philip Zheng
 
Hands-On Session Docker
Hands-On Session DockerHands-On Session Docker
Hands-On Session Docker
LinetsChile
 
時代在變 Docker 要會:台北 Docker 一日入門篇
時代在變 Docker 要會:台北 Docker 一日入門篇時代在變 Docker 要會:台北 Docker 一日入門篇
時代在變 Docker 要會:台北 Docker 一日入門篇
Philip Zheng
 
Docker command
Docker commandDocker command
Docker command
Eric Ahn
 
Ad

Recently uploaded (20)

Adobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest VersionAdobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest Version
kashifyounis067
 
Secure Test Infrastructure: The Backbone of Trustworthy Software Development
Secure Test Infrastructure: The Backbone of Trustworthy Software DevelopmentSecure Test Infrastructure: The Backbone of Trustworthy Software Development
Secure Test Infrastructure: The Backbone of Trustworthy Software Development
Shubham Joshi
 
Adobe Master Collection CC Crack Advance Version 2025
Adobe Master Collection CC Crack Advance Version 2025Adobe Master Collection CC Crack Advance Version 2025
Adobe Master Collection CC Crack Advance Version 2025
kashifyounis067
 
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
Andre Hora
 
Douwan Crack 2025 new verson+ License code
Douwan Crack 2025 new verson+ License codeDouwan Crack 2025 new verson+ License code
Douwan Crack 2025 new verson+ License code
aneelaramzan63
 
Salesforce Data Cloud- Hyperscale data platform, built for Salesforce.
Salesforce Data Cloud- Hyperscale data platform, built for Salesforce.Salesforce Data Cloud- Hyperscale data platform, built for Salesforce.
Salesforce Data Cloud- Hyperscale data platform, built for Salesforce.
Dele Amefo
 
WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)
sh607827
 
F-Secure Freedome VPN 2025 Crack Plus Activation New Version
F-Secure Freedome VPN 2025 Crack Plus Activation  New VersionF-Secure Freedome VPN 2025 Crack Plus Activation  New Version
F-Secure Freedome VPN 2025 Crack Plus Activation New Version
saimabibi60507
 
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Andre Hora
 
Maxon CINEMA 4D 2025 Crack FREE Download LINK
Maxon CINEMA 4D 2025 Crack FREE Download LINKMaxon CINEMA 4D 2025 Crack FREE Download LINK
Maxon CINEMA 4D 2025 Crack FREE Download LINK
younisnoman75
 
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Eric D. Schabell
 
Adobe After Effects Crack FREE FRESH version 2025
Adobe After Effects Crack FREE FRESH version 2025Adobe After Effects Crack FREE FRESH version 2025
Adobe After Effects Crack FREE FRESH version 2025
kashifyounis067
 
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
steaveroggers
 
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage DashboardsAdobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
BradBedford3
 
How to Optimize Your AWS Environment for Improved Cloud Performance
How to Optimize Your AWS Environment for Improved Cloud PerformanceHow to Optimize Your AWS Environment for Improved Cloud Performance
How to Optimize Your AWS Environment for Improved Cloud Performance
ThousandEyes
 
Not So Common Memory Leaks in Java Webinar
Not So Common Memory Leaks in Java WebinarNot So Common Memory Leaks in Java Webinar
Not So Common Memory Leaks in Java Webinar
Tier1 app
 
The Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdfThe Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdf
drewplanas10
 
Designing AI-Powered APIs on Azure: Best Practices& Considerations
Designing AI-Powered APIs on Azure: Best Practices& ConsiderationsDesigning AI-Powered APIs on Azure: Best Practices& Considerations
Designing AI-Powered APIs on Azure: Best Practices& Considerations
Dinusha Kumarasiri
 
Get & Download Wondershare Filmora Crack Latest [2025]
Get & Download Wondershare Filmora Crack Latest [2025]Get & Download Wondershare Filmora Crack Latest [2025]
Get & Download Wondershare Filmora Crack Latest [2025]
saniaaftab72555
 
Meet the Agents: How AI Is Learning to Think, Plan, and Collaborate
Meet the Agents: How AI Is Learning to Think, Plan, and CollaborateMeet the Agents: How AI Is Learning to Think, Plan, and Collaborate
Meet the Agents: How AI Is Learning to Think, Plan, and Collaborate
Maxim Salnikov
 
Adobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest VersionAdobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest Version
kashifyounis067
 
Secure Test Infrastructure: The Backbone of Trustworthy Software Development
Secure Test Infrastructure: The Backbone of Trustworthy Software DevelopmentSecure Test Infrastructure: The Backbone of Trustworthy Software Development
Secure Test Infrastructure: The Backbone of Trustworthy Software Development
Shubham Joshi
 
Adobe Master Collection CC Crack Advance Version 2025
Adobe Master Collection CC Crack Advance Version 2025Adobe Master Collection CC Crack Advance Version 2025
Adobe Master Collection CC Crack Advance Version 2025
kashifyounis067
 
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
Andre Hora
 
Douwan Crack 2025 new verson+ License code
Douwan Crack 2025 new verson+ License codeDouwan Crack 2025 new verson+ License code
Douwan Crack 2025 new verson+ License code
aneelaramzan63
 
Salesforce Data Cloud- Hyperscale data platform, built for Salesforce.
Salesforce Data Cloud- Hyperscale data platform, built for Salesforce.Salesforce Data Cloud- Hyperscale data platform, built for Salesforce.
Salesforce Data Cloud- Hyperscale data platform, built for Salesforce.
Dele Amefo
 
WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)
sh607827
 
F-Secure Freedome VPN 2025 Crack Plus Activation New Version
F-Secure Freedome VPN 2025 Crack Plus Activation  New VersionF-Secure Freedome VPN 2025 Crack Plus Activation  New Version
F-Secure Freedome VPN 2025 Crack Plus Activation New Version
saimabibi60507
 
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Andre Hora
 
Maxon CINEMA 4D 2025 Crack FREE Download LINK
Maxon CINEMA 4D 2025 Crack FREE Download LINKMaxon CINEMA 4D 2025 Crack FREE Download LINK
Maxon CINEMA 4D 2025 Crack FREE Download LINK
younisnoman75
 
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Eric D. Schabell
 
Adobe After Effects Crack FREE FRESH version 2025
Adobe After Effects Crack FREE FRESH version 2025Adobe After Effects Crack FREE FRESH version 2025
Adobe After Effects Crack FREE FRESH version 2025
kashifyounis067
 
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
steaveroggers
 
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage DashboardsAdobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
BradBedford3
 
How to Optimize Your AWS Environment for Improved Cloud Performance
How to Optimize Your AWS Environment for Improved Cloud PerformanceHow to Optimize Your AWS Environment for Improved Cloud Performance
How to Optimize Your AWS Environment for Improved Cloud Performance
ThousandEyes
 
Not So Common Memory Leaks in Java Webinar
Not So Common Memory Leaks in Java WebinarNot So Common Memory Leaks in Java Webinar
Not So Common Memory Leaks in Java Webinar
Tier1 app
 
The Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdfThe Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdf
drewplanas10
 
Designing AI-Powered APIs on Azure: Best Practices& Considerations
Designing AI-Powered APIs on Azure: Best Practices& ConsiderationsDesigning AI-Powered APIs on Azure: Best Practices& Considerations
Designing AI-Powered APIs on Azure: Best Practices& Considerations
Dinusha Kumarasiri
 
Get & Download Wondershare Filmora Crack Latest [2025]
Get & Download Wondershare Filmora Crack Latest [2025]Get & Download Wondershare Filmora Crack Latest [2025]
Get & Download Wondershare Filmora Crack Latest [2025]
saniaaftab72555
 
Meet the Agents: How AI Is Learning to Think, Plan, and Collaborate
Meet the Agents: How AI Is Learning to Think, Plan, and CollaborateMeet the Agents: How AI Is Learning to Think, Plan, and Collaborate
Meet the Agents: How AI Is Learning to Think, Plan, and Collaborate
Maxim Salnikov
 

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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]>
  • 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://[email protected]: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!