15. Vagrant
• “Development environments made easy”
• Virtual Machine without overhead
• Free, local VPS for testing provisioning scripts
• Local staging
16. # Vagrantfile
Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/trusty64"
config.vm.network "forwarded_port", guest: 80, host: 8080
config.vm.network "forwarded_port", guest: 3000, host: 3030
end
$ vagrant up
# break things
$ vagrant destroy
$ vagrant up
33. Volumes are great
• My misconception: code always either in container,
or always out of it.
# Dockerfile
ADD . app_dir/
Makes sure app directory
is always in built image
Enables code reload for development
$ docker run -v $(pwd):/app_dir my-project
34. Docker Compose
$ docker build -t my-project .
$ docker run -d --name db postgres
$ docker run --link db:db -p "3000:3000" my-project
35. $ docker run -d --name db postgres
$ docker run --link db:db -p "3000:3000" --env-file .env
my-project
36. $ docker run -d --name db postgres
$ docker run --link db:db -p "3000:3000" --env-file .env -
v /home/hodak/code/my-project:/my-project my-project
37. $ docker run -d --name db postgres
$ docker run -d --name redis redis
$ docker run -d --name sidekiq --link redis:redis --link db:db --env-file
.env my-project bundle exec sidekiq
$ docker run --link db:db --link redis:redis -p "3000:3000" --env-file .env
-v /home/hodak/code/my-project:/my-project my-project
49. Development CI
Ruby version
Bundler version
Ruby version
Bundler version
Staging Production
Ruby version
Bundler version
Ruby version
Bundler version
Hi everybody,
I’d like to tell you something about Docker in context of developing ruby on rails application, sending it on continuous integration service and deploying it to the server.
my name is Adam,
work as ruby and javascript developer in Monterail
before we begin with Docker,
dev-ops-ish, developer story
what got me to this point, got me interested with docker
note not devops
not as comfortable as should be, can be said about
devops story from developer’s point of view
It’s a story about my side project…
I wrote an app!
now what?
decent developer
people to use it, deploy
knew better
joke
and not a very good one
- everybody do with rails app
of course
one butt
which I knew I would have
app’s design
state after couple of weeks, 200 records per user
heroku pricing in mind
I did a quick math
decided to go the VPS road.
don’t get me wrong about heroku, couple dozens of dollars
all the cool, side projects, learn devops thing eventually
for $5/month I got a decent VPS
could do everything I wanted -> problem -> could -> had to
and what was my next step?
how to deploy rails app
tons of tutorials
chose passenger -> app server, nginx -> http server, capistrano -> deployment automation tool
a lot more to choose from.
find tutorial -> ssh -> steps -> deploy -> done -> right?
big problem, kept bothering me
repeatability of server environment
what if again?
whole process, good couple of hours first time, next time
what ifs: server failed, staging, new project
find tutorial month later? everything from beginning, new server?
devops - pressure - no wonder if it looks like it.
does it? more predictable?
sleep better
nothing like code, hacking on server, praying
- automate the “server setup” part - what infrastructure as code is about
These two tools allowed me to do it rather quickly and I can highly recommend both.
- what is
motto of Vagrant on their website
I don’t buy, Docker is more useful
I really like using Vagrant as “locally hosted servers”
I can SSH to the local server,
I can destroy and create new “server” in a matter of seconds,
I can use Vagrant as a staging environment, to make sure that things like server provisioning, loading ENV variables, e-mail sending, assets precompilation etc. will work on production
Finally something interesting, code!
not a lot - setting vagrant is that easy
my full config (what it does)
can ssh, use like VPS
this is how I work with it
automation tool
connects ssh, runs commands
nice thing
not the only solution, found to be the simplest
configuration looks like; hosts -> user -> roles (sets of commands)
roles - download / write own
if access && user -> run on new server -> 5 minutes -> serve app
what happens here? generic / site specific
Getting to this part was very exciting for me. I could configure server and deploy my application in 5 minutes while, actually, just doing coffee. But I thought - can we do better? It still feels kind of complex.
*click* hear about docker, thought -> what I need?
in its simplest we can say
cool and all, what means
- what is container made of
common interface
what I mean by common interface
image, any application, don’t care what made of, dependencies
run, docker takes care
don’t need xxx installed
all your host needs to understand is docker
how is it different / can’t we do it with vagrant
image from docker website
most important difference - VMs include whole operating system
to deploy rails app, you need to ship it with whole ubuntu or debian server
50mb project, ship with 700mb operating system has to run on a server - which already has an operating system
very heavy and requires a lot of resources
running 3 virtual machines on my laptop would probably make it fly and I would end up with a drone
containers, in contrast, share kernel with linux OS.
while you can have your container using debian or ubuntu, it still shares kernel with its host OS
application can use low level resources it needs from host os
Docker file - only one needed
Docker takes -> builds image based on it
base - each begin, is based on. ruby -> debian; inheritance
run commands - debian, access to commands
add -> copy whole app directory
cmd -> when container starts
what to do with such file?
build -> create image, pull base, run commands
run -> run, create container
this case -> bundle exec rails s
- technically all needed, rails started
- won’t work - db
could install on computer, better use docker (no dependencies)
link containers, have connection
d flag, name, image name
rails config, instead of localhost
besides linking, volumes
shared, between host OS and docker container
files, probably won’t
this is how you run a container with volume
magically shared
not strictly docker concept, important part of ecosystem
share built images, “cloud”
several options
screenshot, docker hub
besides official projects - search unofficial, public repositories
postgres, over 2000
this is kind of madness, most likely don’t want to
when project doesn’t have official -> likely to find
trusting second parties
know roughly what docker is and how to configure
use cases, where can help us
offer in CI and production, most widely used in development
as said earlier, shares kernel with host os -> linux dependent
mac and windows users
docker core team has you covered
part of official docker ecosystem
virtual box + docker machine -> magic -> docker, access to commands
in development, volumes are great
thought with docker you had to ssh to container, install vim or whatever and not use your day-to-day development environment
in docker file can copy whole application directory during build
when running in development, you can use volumes
one more, official tool from docker ecosystem
back to linking example, 2 images (db, app)
app -> depends on having db, must start db every time
- imagine we had to load ENV VARIABLES
specify with —env-file option
starting getting harder
oh wait, VOLUMES
getting ridiculous
might as well go crazy
assume, hypothetically, SIDEKIQ
every time started work
script
fortunately, can do better
interface for that and it’s called DOCKER COMPOSE
configure with - of course - YML file
is YML JavaScript of DevOps world?
starts our application and database
this starts the example with sidekiq
commit it
team members
agency like ours, monterail
no windows, 2 linux, macs, almost all projects RoR
no docker-based development any time soon
nevertheless easily think of some cases where it would be great
microservices, java developers don’t need to have ruby installed
freelance front-end developer, windows, spend a day
personal case, side project
user upload files, STL format, 3D models
show info -> volume, size, triangles
library, CLI, written in C
I fell in love with this project after reading its readme,
where you can find benchmarks from 1996
how to install admesh? easy, nothing fancy, right?
except, when you have to run it on windows
we are in a point where we think about hiring freelance front-end developer
afraid we’ll find good developer running windows
no experience with virtual machines and ubuntu
technicality, not related to core of her work
docker fixes
dockerize application and always have access to admesh command
admesh exotic
easily imagemagick
my favourite part of this setup
see big potential in docker approach
typical rails CI setup
(say what is shown)
ASSUMPTION ruby is installed with rvm
is fine, we’re used to it BUT
can’t easily swap ci server
some problem I see
two, separate environments - Development and CI
assume the same set up
- doesn’t scale well
might say that I’m overreacting about the bundler version
until it matters, worked on a project, bundler security issue, 6 ruby on rails services
- God forbid other non-trivial dependencies, like ImageMagick
or admesh
based per project,
doesn’t happen often rails app works in a void
with Docker. beware, some serious keynote animation magic
work in development, use docker -> push to GitHub -> triggers CI
CI -> Dockerfile -> PRODUCTION READY image (assets precompilation, production gems) -> run specs
specs pass -> send to Docker Repository
sits in Docker Repository, ready to be used
no environment ruby, bundler versions, only understand docker
CI process guarantees all images in repository passed our tests
what are gains
can send straight to production
old process - specs pass in CI env, not production
reminder how CI config looked like
change it using Docker?
Setup part -> branch name to variable -> clear leftover docker images - start with clean slate
(go with slides)
- quickly see how to deploy docker images
what changes in provisioning
reminder, ansible setup
can simplify
SERVER ONLY NEEDS TO UNDERSTAND DOCKER
don’t need ruby or postgres on our server
technically, we don’t need nginx, too, as we could use nginx from docker, but I kind of felt better with it
there is a slight problem we didn’t have before - we can’t create database by running db:create rake task. but we can move this command to run on every deploy - if the database already exists, nothing happens
what changes in deploy, and what stays the same
still nginx
instead of GitHub
instead of starting database / redis processes
still monitor, make sure app or db gets up when it dies
important pattern using postgres in docker container in production
decouple postgres engine - running in a postgres container - from postgres data
(show - image exits immediately - no wasted resources)
similar to using volumes, don’t have to make sure directory exist - enhances portability
remember, we still have to run at least 2 containers - database and our app
need to synchronise it somehow
my first thought was to run it with docker-compose, but, from what I read, it’s an anti pattern and docker-compose is better left on development
you can see the —restart=always option.
docker mechanism to restart containers, when they exit
note, that we pull the newest image from docker repository - not touching github at all
can use ansible for deploy
has built-in docker commands
ansible task could look like this
- from what I know it’s better to use external tool for starting and monitoring processes for anything but the most simple containers, so you can use any such tool