ruby on rails and docker - why should i care?

68
Ruby on Rails & Docker Why should I care? Adam Hodowany

Upload: adam-hodowany

Post on 16-Apr-2017

489 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: Ruby on Rails and Docker - Why should I care?

Ruby on Rails& Docker

Why should I care?

Adam Hodowany

Page 2: Ruby on Rails and Docker - Why should I care?

About me

• Adam Hodowany

• Ruby and JavaScript developer in Monterail

• @adhodak

Page 3: Ruby on Rails and Docker - Why should I care?

Docker LessDevOps Developer

story

Page 4: Ruby on Rails and Docker - Why should I care?

I wrote an app!Now what?

Page 5: Ruby on Rails and Docker - Why should I care?

$ bundle exec rails server -p 80

It is a joke. Please don’t do it.

Page 6: Ruby on Rails and Docker - Why should I care?

Duh

Page 7: Ruby on Rails and Docker - Why should I care?

But

($7 + $9) ÷ month

Page 8: Ruby on Rails and Docker - Why should I care?

> UserAnswer.count

=> 158_565

Page 9: Ruby on Rails and Docker - Why should I care?

http://giphy.com/gifs/ohdY5OaQmUmVW

Page 10: Ruby on Rails and Docker - Why should I care?

VPS it is

Page 11: Ruby on Rails and Docker - Why should I care?
Page 12: Ruby on Rails and Docker - Why should I care?

Repeatability

Page 13: Ruby on Rails and Docker - Why should I care?

Infrastructure as Code

Page 14: Ruby on Rails and Docker - Why should I care?

Vagrant + Ansible

Page 15: Ruby on Rails and Docker - Why should I care?

Vagrant

• “Development environments made easy”

• Virtual Machine without overhead

• Free, local VPS for testing provisioning scripts

• Local staging

Page 16: Ruby on Rails and Docker - Why should I care?

# 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

Page 17: Ruby on Rails and Docker - Why should I care?

Ansible

• Automation tool

• Configuration using .YML files

• No client on the server

Page 18: Ruby on Rails and Docker - Why should I care?

# build-server.yml

---

- hosts: all

remote_user: "{{ deploy_user }}"

roles:

### Server provisioning roles:

- { role: linux-prereqs }

- { role: postgresql }

- { role: rbenv }

- { role: ruby }

- { role: nginx }

### Site specific roles:

- { role: prepare_site }

- { role: copy-env }

- create database- copy database.yml- copy nginx config

Page 19: Ruby on Rails and Docker - Why should I care?

Docker

Page 20: Ruby on Rails and Docker - Why should I care?

Docker:your application in a

container

Image: KMJ at the German language Wikipedia

Page 21: Ruby on Rails and Docker - Why should I care?

Container1. Application

2. All dependencies

3. Common interface

4. ???

5. PROFIT

Page 22: Ruby on Rails and Docker - Why should I care?

$ bundle exec rails server

$ php artisan serve

$ python manage.py runserver

$ docker run docker-image

Page 23: Ruby on Rails and Docker - Why should I care?

How is it different from VM?

Virtual Machine: Docker:

https://www.docker.com/what-docker

Page 24: Ruby on Rails and Docker - Why should I care?

# Dockerfile

FROM ruby:2.2.0

RUN apt-get update -qq && apt-get install -y build-essential nodejs && gem install bundler

ENV APP_HOME /myapp

RUN mkdir $APP_HOME

WORKDIR $APP_HOME

ADD Gemfile $APP_HOME/Gemfile

ADD Gemfile.lock $APP_HOME/Gemfile.lock

RUN bundle install

ADD . $APP_HOME

CMD ["bundle", "exec", "rails", "server", "--binding", "0.0.0.0"]

- Base Image

- Copy whole application to the image

|- Default “run” command

Page 25: Ruby on Rails and Docker - Why should I care?

$ docker build -t my-project .

$ docker run -p 3000:3000 my-projecthost:container

Page 26: Ruby on Rails and Docker - Why should I care?

Linking containers$ docker run -d --name db postgres$ docker run --link db:db my-project

# config/database.ymldevelopment: host: db ...

Page 27: Ruby on Rails and Docker - Why should I care?

Volumes

$ docker run -v /home/hodak/data:/data my-project

or: shared directories(or files)

(but most likely directories)

host:container

Page 28: Ruby on Rails and Docker - Why should I care?

Docker repositories• Docker Hub

• Official

• Free public repositories

• Alternatives exist

• Self-hosted

• Installed with… Docker

or: GitHubs for Docker images

Page 29: Ruby on Rails and Docker - Why should I care?

99 official repositories including:nginx, redis, node, postgres,

elasticsearch, wordpress,jenkins, ruby…

Maintained by projects creators

Page 30: Ruby on Rails and Docker - Why should I care?

Thousands of unofficial,public repositories

http://gph.is/VxbrxV

Page 31: Ruby on Rails and Docker - Why should I care?

Docker in Development

Page 32: Ruby on Rails and Docker - Why should I care?

Docker Machine

Page 33: Ruby on Rails and Docker - Why should I care?

Volumes are great• My misconception: code always either in

container, or always out of it.

# DockerfileADD . app_dir/

Makes sure app directoryis always in built image

Enables code reload for development$ docker run -v $(pwd):/app_dir my-project

Page 34: Ruby on Rails and Docker - Why should I care?

Docker Compose$ docker build -t my-project .

$ docker run -d --name db postgres$ docker run --link db:db -p "3000:3000" my-project

Page 35: Ruby on Rails and Docker - Why should I care?

$ docker run -d --name db postgres$ docker run --link db:db -p "3000:3000" --env-file .env my-project

Page 36: Ruby on Rails and Docker - Why should I care?

$ 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

Page 37: Ruby on Rails and Docker - Why should I care?

$ 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

Page 38: Ruby on Rails and Docker - Why should I care?

# docker-compose.ymldb: image: postgresweb: build: . command: bundle exec rails server --binding 0.0.0.0 ports: - "3000:3000" links: - db volumes: - .:/myapp env_file: .env

$ docker-compose build$ docker-compose up

Page 39: Ruby on Rails and Docker - Why should I care?

# docker-compose.ymldb: image: postgresredis: image: redissidekiq: build: . command: bundle exec sidekiq volumes: - .:/myapp links: - db - redis env_file: .envweb: build: . command: bundle exec rails server --binding 0.0.0.0 ports: - "3000:3000" links: - db - redis volumes: - .:/myapp env_file: .env

Page 40: Ruby on Rails and Docker - Why should I care?

Use Cases

• Ruby on Rails agency - meh?

• Microservices

• Especially in different technologies

• Working with Freelancers

Page 41: Ruby on Rails and Docker - Why should I care?

Admeshgithub.com/admesh/admesh

Page 42: Ruby on Rails and Docker - Why should I care?
Page 43: Ruby on Rails and Docker - Why should I care?

$ ./configure$ make$ make install

Page 44: Ruby on Rails and Docker - Why should I care?
Page 45: Ruby on Rails and Docker - Why should I care?

# DockerfileCOPY ./lib/admesh-0.98.2.tar.gz $APP_HOME/admesh.tar.gzRUN tar -zxvf admesh.tar.gz && \ cd $APP_HOME/admesh-0.98.2 && \ ./configure && \ make && \ make install

Page 46: Ruby on Rails and Docker - Why should I care?

Continuous Integration with

Docker

Page 47: Ruby on Rails and Docker - Why should I care?

Typical Rails-CI setup$ cp config/codeship.database.yml config/database.yml

$ rvm use 2.1.1

$ bundle install

$ export RAILS_ENV=test

$ bundle exec rake db:drop db:create db:structure:load

$ bundle exec rspec

Page 48: Ruby on Rails and Docker - Why should I care?

Development CI

Ruby versionBundler version

Ruby versionBundler version

Page 49: Ruby on Rails and Docker - Why should I care?

Development CI

Ruby versionBundler version

Ruby versionBundler version

Staging Production

Ruby versionBundler version

Ruby versionBundler version

Page 50: Ruby on Rails and Docker - Why should I care?

• More tricky dependencies

• ImageMagick

• ADMesh

• …

Page 51: Ruby on Rails and Docker - Why should I care?

Development CI Docker Repository

Dev Build

Production

Build

Staging Production

Page 52: Ruby on Rails and Docker - Why should I care?

• Image that has proven itself

• No errors

• Specs passed

Page 53: Ruby on Rails and Docker - Why should I care?

$ cp config/codeship.database.yml config/database.yml

$ rvm use 2.1.1

$ bundle install

$ export RAILS_ENV=test

$ bundle exec rake db:drop db:create db:structure:load

$ bundle exec rspec

Page 54: Ruby on Rails and Docker - Why should I care?

- Start Postgres

|- Build production image

- Set up database

- Run specsAfter specs pass:

Send imageto Docker Hub

# origin/master -> master$ BRANCH_NAME=`echo $GIT_BRANCH | cut -d '/' -f 2-`$ docker rm --force $(docker ps -aq) || echo "ok"

$ docker run -d --name db postgres$ docker build -t my-project -f Dockerfile.prod .

$ docker run --link db:db -e RAILS_ENV=test my-project bundle exec rake db:create db:migrate$ docker run --link db:db -e RAILS_ENV=test my-project bundle exec rspec

$ docker tag my-project hodak/my-project:$BRANCH_NAME$ docker push hodak/my-project:$BRANCH_NAME

Page 55: Ruby on Rails and Docker - Why should I care?

Docker in production

Page 56: Ruby on Rails and Docker - Why should I care?

# build-server.yml---- hosts: all remote_user: "{{ deploy_user }}" roles: ### Server provisioning roles: - { role: linux-prereqs } - { role: postgresql } - { role: rbenv } - { role: ruby } - { role: nginx } ### Site specific roles: - { role: prepare_site } - { role: copy-env }

Page 57: Ruby on Rails and Docker - Why should I care?

# build-server.yml---- hosts: all remote_user: "{{ deploy_user }}" roles: ### Server provisioning roles: - { role: linux-prereqs } - { role: nginx } - { role: docker } ### Site specific roles: - { role: prepare_site } - { role: copy-env }

- create database- copy database.yml- copy nginx config

Page 58: Ruby on Rails and Docker - Why should I care?

• Still must configure nginx

• Pull image from Docker repository

• Not touching GitHub at all

• Synchronise starting containers

• Monitoring

Page 59: Ruby on Rails and Docker - Why should I care?

Data-only container pattern

$ docker run --name dbdata postgres echo "Data-only container for postgres"$ docker run -d --volumes-from dbdata --name db postgres

Page 60: Ruby on Rails and Docker - Why should I care?

docker-compose?

Page 61: Ruby on Rails and Docker - Why should I care?

Just a script

Page 62: Ruby on Rails and Docker - Why should I care?

#!/bin/bashdocker run --name dbdata postgres echo "Data-only container for postgres" || echo "already started"docker run -d --volumes-from dbdata --name db --restart=always postgres || docker start dbdocker pull hodak/my-project:masterdocker tag hodak/my-project:master my-projectdocker run --link db:db my-project bundle exec rake db:create db:migratedocker rm --force my-project || echo "not yet created"docker run -d --link db:db --name my-project --restart=always --env-file .env -p "8080:8080" my-project

Page 63: Ruby on Rails and Docker - Why should I care?

Ansible

Page 64: Ruby on Rails and Docker - Why should I care?

tasks:

- name: application container

docker:

name: my-project

image: hodak/my-project:master

state: reloaded

pull: always

links:

- "db:db"

ports:

- "8080:8080"

restart_policy: always

Page 65: Ruby on Rails and Docker - Why should I care?

Custom deploy script for

Capistrano

Page 66: Ruby on Rails and Docker - Why should I care?

upstart / systemd / supervisor / monit

Page 67: Ruby on Rails and Docker - Why should I care?

Is it worth it?

Page 68: Ruby on Rails and Docker - Why should I care?

Thank you!

Questions?

We’re hiring join.hussa.rs