SlideShare une entreprise Scribd logo
1  sur  48
Télécharger pour lire hors ligne
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!

Contenu connexe

Tendances

Docker & FieldAware
Docker & FieldAwareDocker & FieldAware
Docker & FieldAware
Jakub Jarosz
 

Tendances (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
 

En vedette

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.
 

En vedette (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
 

Similaire à Streamline your development environment with docker

Similaire à 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
 

Dernier

AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
VictorSzoltysek
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
VishalKumarJha10
 

Dernier (20)

AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 

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!