SlideShare a Scribd company logo
1 of 31
Download to read offline
Ruby microservices
With Docker
About me
● Serhii Koba
● Position
○ Web Team lead at MobiDev
○ Lecturer at KhAI
● Fullstack
○ BE: Ruby, Go, Php, Python
○ FE: Vue JS
○ DO: Docker, Ansible
○ IoT, Blockchain, Android
● Blogger a bit
● Personal moto:
Until we learn - we live
Social media:
● http://1devblog.org
● github: @sergey-koba-mobidev
● twitter: @KobaSerhii
● facebook: @kobaserhii
What we will talk about
● How Docker helps building Ruby Microservices
● Automating development processes
● Repeatable environment
● Optimization of Docker images
● Refactoring Docker Compose files
● Central logging with Docker
● Routing requests to microservices
● Deploy?
What we will not talk about
● When to use microservices
● What is the best framework/language for microservices
● How to migrate to microservices
● How to install Docker, Docker Compose
● Docker for Dummies :)
● Is Rails good for Microservices
Docker
Two words about Docker
● Application build and deploy tool
● Containers based virtualization (shares
host OS kernel)
● Each container is based on image
● Each piece of software (service) should be
a container
● Lightweight
● Secure
https://www.docker.com/what-container
Ruby microservice: Sinatra + Trailblazer
# service.rb
# https://github.com/bark-iot/
require 'sinatra'
set :bind, '0.0.0.0'
set :port, 80
get '/houses' do
result = House::List.(user_id: USER['id'])
if result.success?
body
House::Representer.for_collection.new(result['models']
).to_json
else
status 422
body
result['contract.default'].errors.messages.uniq.to_json
end
end
# concepts/house/operations/list.rb
class House < Sequel::Model(DB)
class List < Trailblazer::Operation
step Contract::Build()
step Contract::Validate()
step :list_by_user_id
#...
def list_by_user_id(options, params:, **)
options['models'] = House.where(user_id:
params[:user_id]).all
options['models']
end
end
end
Hi @apotonick
Dockerfile
FROM ruby:2.5.0
# Pg
RUN apt-get update -qq && apt-get install 
-y build-essential libpq-dev lsb-release
ENV APP_ROOT /app
RUN mkdir $APP_ROOT
WORKDIR $APP_ROOT
EXPOSE 80
# Bundle
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN gem update bundler && bundle install --jobs 4
# Copy the rest of source
COPY . /app
Build image
docker build -f Dockerfile.test -t
house-service/test .
List images
docker images
REPOSITORY | TAG | IMAGE ID | CREATED | SIZE
house-service/test | latest | c9b0fe5b01d1 | 2 minutes ago | 985MB
Run
docker run -i -p 80:80
house-service/test bundle exec ruby
service.rb
985 MB
Dockerfile: Use Alpine linux
FROM ruby:2.5.0-alpine
# Pg
RUN apk --update --upgrade add postgresql-dev git
build-base
ENV APP_ROOT /app
RUN mkdir $APP_ROOT
WORKDIR $APP_ROOT
EXPOSE 80
# Bundle
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN gem update bundler && bundle install --jobs 4
# Copy the rest of source
COPY . /app
Build image
docker build -f Dockerfile.test -t
house-service/test .
List images
docker images
REPOSITORY | TAG | IMAGE ID | CREATED |
SIZE
house-service/test | latest | ab58dd76e0d3 | 2 minutes ago |
320MB
320 MB
Dockerfile: Multistage builds
FROM ruby:2.5.0-alpine as bundler
# CODE FROM PREVIOUS SLIDE
# Stage 2
FROM ruby:2.5.0-alpine
RUN apk --update --upgrade add postgresql-dev
EXPOSE 80
ENV APP_ROOT /app
RUN mkdir $APP_ROOT
WORKDIR $APP_ROOT
# Copy the rest of source
COPY . /app
COPY --from=bundler /usr/local/bundle
/usr/local/bundle
Build image
docker build -f Dockerfile.test -t
house-service/test .
List images
docker images
REPOSITORY | TAG | IMAGE ID | CREATED |
SIZE
house-service/test | latest | 8f5a46611b7e | 2 minutes ago |
127MB
127 MB
Dockerfile: Results
8x
Docker Compose
Docker Compose: Yml file
Let's assume each service is placed in a
separate folder
./house-service
./user-service
./device-service
...
house-service:
build: ../house-service
command: bundle exec ruby service.rb
networks:
- my-network
ports:
- 80
volumes:
- ../house-service/:/app
environment:
POSTGRES_USER: my_user
POSTGRES_PASSWORD: my_pass
POSTGRES_DB: my_db
RACK_ENV: development
stdin_open: true
tty: true
Docker Compose: Multiple services
services:
db:
image: postgres:latest
ports:
- "5432:5432"
environment:
POSTGRES_USER: my_user
POSTGRES_PASSWORD: my_pass
POSTGRES_DB: my_db
redis:
image: redis:4.0.5
house-service:
…
user-service:
…
user-service:
build: ../user-service
command: bundle exec ruby service.rb
networks:
- my-network
ports:
- 80
volumes:
- ../user-service/:/app
environment:
POSTGRES_USER: my_user
POSTGRES_PASSWORD: my_pass
POSTGRES_DB: my_db
RACK_ENV: development
stdin_open: true
tty: true
Run services: docker-compose up -d
16 lines
Docker Compose: extension fields
● Yaml anchors and extend
● Docker Compose file version 3.4
● “X-” sections (extension fields)
x-base-service: &base-service
command: bundle exec ruby
service.rb
networks:
- my-network
ports:
- 80
environment:
POSTGRES_USER: my_user
POSTGRES_PASSWORD: my_pass
POSTGRES_DB: my_db
stdin_open: true
tty: true
users-service:
<< : *base-service
build: ../users-service
volumes:
- ../users-service/:/app
5 lines
Docker Compose: Production
In production we want to do things
differently:
● Use images instead of build
● Remove stdin and tty
● Remove volumes with app
code
● Remove test containers
x-base-service: &base-service
command: bundle exec ruby service.rb
networks:
- my-network
ports:
- 80
environment:
POSTGRES_USER: my_user
POSTGRES_PASSWORD: my_pass
POSTGRES_DB: my_db
RACK_ENV: production
users-service:
<< : *base-service
image: myapp/users-service:latest
Two options:
● Two separate docker-compose.yml files
● Overriding files
Docker Compose: Multiple Files
Run Development
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d
# docker-compose.yml PRODUCTION
house-service:
image: myapp/house-service:latest
command: bundle exec ruby service.rb
networks:
- my-network
ports:
- 80
environment:
POSTGRES_USER: my_user
POSTGRES_PASSWORD: my_pass
POSTGRES_DB: my_db
# docker-compose.dev.yml DEV
house-service:
build: ../user-service
command: bundle exec ruby service.rb
environment:
RACK_ENV: development
Central Logging
Logging
● View logs from multiple Docker containers
● Tracing data across multiple containers
● Tracing user action across multiple containers
● Aggregate logs
● Search logs
View logs on a single container
docker-compose -f docker-compose.yml -f
docker-compose.dev.yml logs house-service
Logging: ELK stack
Logging: ELK with Docker
logstash:
build: docker/logstash/
command: logstash -f
/etc/logstash/conf.d/logstash.conf
ports:
- "12201:12201/udp"
kibana:
build: docker/kibana/
ports:
- "5601:5601"
elasticsearch:
image: elasticsearch:latest
command: elasticsearch
-Enetwork.host=0.0.0.0
ports:
- "9200:9200"
- "9300:9300"
environment:
ES_JAVA_OPTS: "-Xms750m
-Xmx750m"
volumes:
- /usr/share/elasticsearch/data
Logging: ELK with Docker
# kibana.yml
port: 5601
host: "0.0.0.0"
elasticsearch_url: "http://elasticsearch:9200"
elasticsearch_preserve_host: true
kibana_index: ".kibana"
default_app_id: "discover"
request_timeout: 300000
shard_timeout: 0
verify_ssl: true
bundled_plugin_ids:
- plugins/dashboard/index
- ...
// logstash.conf
input {
gelf {}
}
output {
elasticsearch {
hosts => "elasticsearch:9200"
}
}
Logging: Gelf driver for Docker containers
x-logging: &logging
driver: gelf
options:
gelf-address: 'udp://localhost:12201'
tag: '{{.Name}}'
house-service:
<< : *logging
user-service:
<< : *logging
Template
variable
Logging: Add log messages to Ruby service
class House < Sequel::Model(DB)
class Create < Trailblazer::Operation
step Model(House, :new)
step :generate_key_and_secret
step Contract::Persist()
step :log_success
failure :log_failure
#...
def log_success(options, params:, model:, **)
LOGGER.info "[#{self.class}] Created house with params #{params.to_json}. House:
#{House::Representer.new(model).to_json}"
end
def log_failure(options, params:, **)
LOGGER.info "[#{self.class}] Failed to create house with params #{params.to_json}"
end
end
Logging: Kibana
Routing
Routing: first try
house-service:
...
ports:
- 3000
user-service:
...
ports:
- 3001
device-service:
...
ports:
- 3002
# house-service/service.rb
require 'sinatra'
set :bind, '0.0.0.0'
set :port, 3000
# user-service/service.rb
require 'sinatra'
set :bind, '0.0.0.0'
set :port, 3001
http://localhost:3000
http://localhost:3001
Routing: Docker haproxy
lb:
image: dockercloud/haproxy
links:
- house-service
volumes:
-
/var/run/docker.sock:/var/run/docker.sock
ports:
- 80:80
house-service:
...
environment:
VIRTUAL_HOST: "*/houses*"
VIRTUAL_HOST_WEIGHT: 102
http://samos-it.com/posts/docker-multi-website-single-ip-host-haproxy.html
Docker
Swarm
Compatible
Possible routers
- Docker cloud proxy (Deprecated)
- Traefik https://traefik.io/
- Caddy https://caddyserver.com/
- Zookeeper
Conclusion
Conclusion
● All in one environment and tools for Ruby microservices
● Minimized Docker images
● Minimized Docker Compose file
● Central logging and tracing using ELK
● Routing (balancing) requests
What’s next?
● Authorization layers?
● gRPC for inter communication?
● Message broker?
● Migrating monolith Rails app to Microservices? :)

More Related Content

What's hot

Developing and Deploying PHP with Docker
Developing and Deploying PHP with DockerDeveloping and Deploying PHP with Docker
Developing and Deploying PHP with DockerPatrick Mizer
 
手把手帶你學Docker 03042017
手把手帶你學Docker 03042017手把手帶你學Docker 03042017
手把手帶你學Docker 03042017Paul Chao
 
Docker summit 2015: 以 Docker Swarm 打造多主機叢集環境
Docker summit 2015: 以 Docker Swarm 打造多主機叢集環境Docker summit 2015: 以 Docker Swarm 打造多主機叢集環境
Docker summit 2015: 以 Docker Swarm 打造多主機叢集環境謝 宗穎
 
Drone CI/CD 自動化測試及部署
Drone CI/CD 自動化測試及部署Drone CI/CD 自動化測試及部署
Drone CI/CD 自動化測試及部署Bo-Yi Wu
 
Dockerize your Symfony application - Symfony Live NYC 2014
Dockerize your Symfony application - Symfony Live NYC 2014Dockerize your Symfony application - Symfony Live NYC 2014
Dockerize your Symfony application - Symfony Live NYC 2014André Rømcke
 
Docker Continuous Delivery Workshop
Docker Continuous Delivery WorkshopDocker Continuous Delivery Workshop
Docker Continuous Delivery WorkshopJirayut Nimsaeng
 
PHP development with Docker
PHP development with DockerPHP development with Docker
PHP development with DockerYosh de Vos
 
Lessons Learned: Using Concourse In Production
Lessons Learned: Using Concourse In ProductionLessons Learned: Using Concourse In Production
Lessons Learned: Using Concourse In ProductionShingo Omura
 
Docker and DevOps --- new IT culture
Docker and DevOps --- new IT cultureDocker and DevOps --- new IT culture
Docker and DevOps --- new IT cultureTerry Chen
 
Using docker to develop NAS applications
Using docker to develop NAS applicationsUsing docker to develop NAS applications
Using docker to develop NAS applicationsTerry Chen
 
Docker 101 - from 0 to Docker in 30 minutes
Docker 101 - from 0 to Docker in 30 minutesDocker 101 - from 0 to Docker in 30 minutes
Docker 101 - from 0 to Docker in 30 minutesLuciano Fiandesio
 
Docker workshop 0507 Taichung
Docker workshop 0507 Taichung Docker workshop 0507 Taichung
Docker workshop 0507 Taichung Paul Chao
 
Super powered Drupal development with docker
Super powered Drupal development with dockerSuper powered Drupal development with docker
Super powered Drupal development with dockerMaciej Lukianski
 
Introduction to Docker
Introduction to DockerIntroduction to Docker
Introduction to DockerKuan Yen Heng
 
Dockerize Me: Distributed PHP applications with Symfony, Docker, Consul and A...
Dockerize Me: Distributed PHP applications with Symfony, Docker, Consul and A...Dockerize Me: Distributed PHP applications with Symfony, Docker, Consul and A...
Dockerize Me: Distributed PHP applications with Symfony, Docker, Consul and A...Alexey Petrov
 
Introduction to Docker at SF Peninsula Software Development Meetup @Guidewire
Introduction to Docker at SF Peninsula Software Development Meetup @GuidewireIntroduction to Docker at SF Peninsula Software Development Meetup @Guidewire
Introduction to Docker at SF Peninsula Software Development Meetup @GuidewiredotCloud
 
Getting instantly up and running with Docker and Symfony
Getting instantly up and running with Docker and SymfonyGetting instantly up and running with Docker and Symfony
Getting instantly up and running with Docker and SymfonyAndré Rømcke
 
Docker 0.11 at MaxCDN meetup in Los Angeles
Docker 0.11 at MaxCDN meetup in Los AngelesDocker 0.11 at MaxCDN meetup in Los Angeles
Docker 0.11 at MaxCDN meetup in Los AngelesJérôme Petazzoni
 

What's hot (20)

Developing and Deploying PHP with Docker
Developing and Deploying PHP with DockerDeveloping and Deploying PHP with Docker
Developing and Deploying PHP with Docker
 
手把手帶你學Docker 03042017
手把手帶你學Docker 03042017手把手帶你學Docker 03042017
手把手帶你學Docker 03042017
 
Docker summit 2015: 以 Docker Swarm 打造多主機叢集環境
Docker summit 2015: 以 Docker Swarm 打造多主機叢集環境Docker summit 2015: 以 Docker Swarm 打造多主機叢集環境
Docker summit 2015: 以 Docker Swarm 打造多主機叢集環境
 
Drone CI/CD 自動化測試及部署
Drone CI/CD 自動化測試及部署Drone CI/CD 自動化測試及部署
Drone CI/CD 自動化測試及部署
 
Dockerize your Symfony application - Symfony Live NYC 2014
Dockerize your Symfony application - Symfony Live NYC 2014Dockerize your Symfony application - Symfony Live NYC 2014
Dockerize your Symfony application - Symfony Live NYC 2014
 
Docker Continuous Delivery Workshop
Docker Continuous Delivery WorkshopDocker Continuous Delivery Workshop
Docker Continuous Delivery Workshop
 
PHP development with Docker
PHP development with DockerPHP development with Docker
PHP development with Docker
 
Lessons Learned: Using Concourse In Production
Lessons Learned: Using Concourse In ProductionLessons Learned: Using Concourse In Production
Lessons Learned: Using Concourse In Production
 
Docker and DevOps --- new IT culture
Docker and DevOps --- new IT cultureDocker and DevOps --- new IT culture
Docker and DevOps --- new IT culture
 
Django via Docker
Django via DockerDjango via Docker
Django via Docker
 
Using docker to develop NAS applications
Using docker to develop NAS applicationsUsing docker to develop NAS applications
Using docker to develop NAS applications
 
Docker 101 - from 0 to Docker in 30 minutes
Docker 101 - from 0 to Docker in 30 minutesDocker 101 - from 0 to Docker in 30 minutes
Docker 101 - from 0 to Docker in 30 minutes
 
Docker workshop 0507 Taichung
Docker workshop 0507 Taichung Docker workshop 0507 Taichung
Docker workshop 0507 Taichung
 
Super powered Drupal development with docker
Super powered Drupal development with dockerSuper powered Drupal development with docker
Super powered Drupal development with docker
 
Introduction to Docker
Introduction to DockerIntroduction to Docker
Introduction to Docker
 
Dockerize Me: Distributed PHP applications with Symfony, Docker, Consul and A...
Dockerize Me: Distributed PHP applications with Symfony, Docker, Consul and A...Dockerize Me: Distributed PHP applications with Symfony, Docker, Consul and A...
Dockerize Me: Distributed PHP applications with Symfony, Docker, Consul and A...
 
Docker orchestration
Docker orchestrationDocker orchestration
Docker orchestration
 
Introduction to Docker at SF Peninsula Software Development Meetup @Guidewire
Introduction to Docker at SF Peninsula Software Development Meetup @GuidewireIntroduction to Docker at SF Peninsula Software Development Meetup @Guidewire
Introduction to Docker at SF Peninsula Software Development Meetup @Guidewire
 
Getting instantly up and running with Docker and Symfony
Getting instantly up and running with Docker and SymfonyGetting instantly up and running with Docker and Symfony
Getting instantly up and running with Docker and Symfony
 
Docker 0.11 at MaxCDN meetup in Los Angeles
Docker 0.11 at MaxCDN meetup in Los AngelesDocker 0.11 at MaxCDN meetup in Los Angeles
Docker 0.11 at MaxCDN meetup in Los Angeles
 

Similar to Ruby microservices with Docker - Sergii Koba

JDD2014: Docker.io - versioned linux containers for JVM devops - Dominik Dorn
JDD2014: Docker.io - versioned linux containers for JVM devops - Dominik DornJDD2014: Docker.io - versioned linux containers for JVM devops - Dominik Dorn
JDD2014: Docker.io - versioned linux containers for JVM devops - Dominik DornPROIDEA
 
Streamline your development environment with docker
Streamline your development environment with dockerStreamline your development environment with docker
Streamline your development environment with dockerGiacomo Bagnoli
 
Docker in everyday development
Docker in everyday developmentDocker in everyday development
Docker in everyday developmentJustyna Ilczuk
 
Making kubernetes simple for developers
Making kubernetes simple for developersMaking kubernetes simple for developers
Making kubernetes simple for developersSuraj Deshmukh
 
桃園市教育局Docker技術入門與實作
桃園市教育局Docker技術入門與實作桃園市教育局Docker技術入門與實作
桃園市教育局Docker技術入門與實作Philip Zheng
 
Docker for mere mortals
Docker for mere mortalsDocker for mere mortals
Docker for mere mortalsHenryk Konsek
 
Docker module 1
Docker module 1Docker module 1
Docker module 1Liang Bo
 
From development environments to production deployments with Docker, Compose,...
From development environments to production deployments with Docker, Compose,...From development environments to production deployments with Docker, Compose,...
From development environments to production deployments with Docker, Compose,...Jérôme Petazzoni
 
Настройка окружения для кросскомпиляции проектов на основе docker'a
Настройка окружения для кросскомпиляции проектов на основе docker'aНастройка окружения для кросскомпиляции проектов на основе docker'a
Настройка окружения для кросскомпиляции проектов на основе docker'acorehard_by
 
Learned lessons in a real world project
Learned lessons in a real world projectLearned lessons in a real world project
Learned lessons in a real world projectCodium
 
時代在變 Docker 要會:台北 Docker 一日入門篇
時代在變 Docker 要會:台北 Docker 一日入門篇時代在變 Docker 要會:台北 Docker 一日入門篇
時代在變 Docker 要會:台北 Docker 一日入門篇Philip Zheng
 
Kubernetes - training micro-dragons without getting burnt
Kubernetes -  training micro-dragons without getting burntKubernetes -  training micro-dragons without getting burnt
Kubernetes - training micro-dragons without getting burntAmir Moghimi
 
DCEU 18: Building Your Development Pipeline
DCEU 18: Building Your Development PipelineDCEU 18: Building Your Development Pipeline
DCEU 18: Building Your Development PipelineDocker, Inc.
 
Docker and IBM Integration Bus
Docker and IBM Integration BusDocker and IBM Integration Bus
Docker and IBM Integration BusGeza Geleji
 
Introduction to Docker
Introduction to DockerIntroduction to Docker
Introduction to DockerLuong Vo
 

Similar to Ruby microservices with Docker - Sergii Koba (20)

Docker as development environment
Docker as development environmentDocker as development environment
Docker as development environment
 
JDD2014: Docker.io - versioned linux containers for JVM devops - Dominik Dorn
JDD2014: Docker.io - versioned linux containers for JVM devops - Dominik DornJDD2014: Docker.io - versioned linux containers for JVM devops - Dominik Dorn
JDD2014: Docker.io - versioned linux containers for JVM devops - Dominik Dorn
 
Streamline your development environment with docker
Streamline your development environment with dockerStreamline your development environment with docker
Streamline your development environment with docker
 
Docker in everyday development
Docker in everyday developmentDocker in everyday development
Docker in everyday development
 
Docker+java
Docker+javaDocker+java
Docker+java
 
Making kubernetes simple for developers
Making kubernetes simple for developersMaking kubernetes simple for developers
Making kubernetes simple for developers
 
Intro to docker
Intro to dockerIntro to docker
Intro to docker
 
桃園市教育局Docker技術入門與實作
桃園市教育局Docker技術入門與實作桃園市教育局Docker技術入門與實作
桃園市教育局Docker技術入門與實作
 
Docker for mere mortals
Docker for mere mortalsDocker for mere mortals
Docker for mere mortals
 
Docker module 1
Docker module 1Docker module 1
Docker module 1
 
From development environments to production deployments with Docker, Compose,...
From development environments to production deployments with Docker, Compose,...From development environments to production deployments with Docker, Compose,...
From development environments to production deployments with Docker, Compose,...
 
Docking with Docker
Docking with DockerDocking with Docker
Docking with Docker
 
Настройка окружения для кросскомпиляции проектов на основе docker'a
Настройка окружения для кросскомпиляции проектов на основе docker'aНастройка окружения для кросскомпиляции проектов на основе docker'a
Настройка окружения для кросскомпиляции проектов на основе docker'a
 
Learning Docker with Thomas
Learning Docker with ThomasLearning Docker with Thomas
Learning Docker with Thomas
 
Learned lessons in a real world project
Learned lessons in a real world projectLearned lessons in a real world project
Learned lessons in a real world project
 
時代在變 Docker 要會:台北 Docker 一日入門篇
時代在變 Docker 要會:台北 Docker 一日入門篇時代在變 Docker 要會:台北 Docker 一日入門篇
時代在變 Docker 要會:台北 Docker 一日入門篇
 
Kubernetes - training micro-dragons without getting burnt
Kubernetes -  training micro-dragons without getting burntKubernetes -  training micro-dragons without getting burnt
Kubernetes - training micro-dragons without getting burnt
 
DCEU 18: Building Your Development Pipeline
DCEU 18: Building Your Development PipelineDCEU 18: Building Your Development Pipeline
DCEU 18: Building Your Development Pipeline
 
Docker and IBM Integration Bus
Docker and IBM Integration BusDocker and IBM Integration Bus
Docker and IBM Integration Bus
 
Introduction to Docker
Introduction to DockerIntroduction to Docker
Introduction to Docker
 

More from Ruby Meditation

Is this Legacy or Revenant Code? - Sergey Sergyenko | Ruby Meditation 30
Is this Legacy or Revenant Code? - Sergey Sergyenko  | Ruby Meditation 30Is this Legacy or Revenant Code? - Sergey Sergyenko  | Ruby Meditation 30
Is this Legacy or Revenant Code? - Sergey Sergyenko | Ruby Meditation 30Ruby Meditation
 
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...Ruby Meditation
 
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29Ruby Meditation
 
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...Ruby Meditation
 
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28 How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28 Ruby Meditation
 
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28Ruby Meditation
 
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...Ruby Meditation
 
Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...
Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...
Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...Ruby Meditation
 
Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...
Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...
Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...Ruby Meditation
 
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...Ruby Meditation
 
What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27
What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27
What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27Ruby Meditation
 
New features in Rails 6 - Nihad Abbasov (RUS) | Ruby Meditation 26
New features in Rails 6 -  Nihad Abbasov (RUS) | Ruby Meditation 26New features in Rails 6 -  Nihad Abbasov (RUS) | Ruby Meditation 26
New features in Rails 6 - Nihad Abbasov (RUS) | Ruby Meditation 26Ruby Meditation
 
Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26
Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26
Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26Ruby Meditation
 
Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...
Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...
Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...Ruby Meditation
 
Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26
Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26
Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26Ruby Meditation
 
Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25
Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25
Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25Ruby Meditation
 
Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...
Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...
Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...Ruby Meditation
 
Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...
Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...
Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...Ruby Meditation
 
Rails App performance at the limit - Bogdan Gusiev
Rails App performance at the limit - Bogdan GusievRails App performance at the limit - Bogdan Gusiev
Rails App performance at the limit - Bogdan GusievRuby Meditation
 
GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23
GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23
GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23Ruby Meditation
 

More from Ruby Meditation (20)

Is this Legacy or Revenant Code? - Sergey Sergyenko | Ruby Meditation 30
Is this Legacy or Revenant Code? - Sergey Sergyenko  | Ruby Meditation 30Is this Legacy or Revenant Code? - Sergey Sergyenko  | Ruby Meditation 30
Is this Legacy or Revenant Code? - Sergey Sergyenko | Ruby Meditation 30
 
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...
 
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29
 
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...
 
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28 How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28
 
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28
 
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...
 
Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...
Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...
Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...
 
Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...
Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...
Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...
 
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
 
What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27
What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27
What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27
 
New features in Rails 6 - Nihad Abbasov (RUS) | Ruby Meditation 26
New features in Rails 6 -  Nihad Abbasov (RUS) | Ruby Meditation 26New features in Rails 6 -  Nihad Abbasov (RUS) | Ruby Meditation 26
New features in Rails 6 - Nihad Abbasov (RUS) | Ruby Meditation 26
 
Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26
Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26
Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26
 
Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...
Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...
Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...
 
Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26
Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26
Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26
 
Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25
Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25
Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25
 
Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...
Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...
Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...
 
Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...
Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...
Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...
 
Rails App performance at the limit - Bogdan Gusiev
Rails App performance at the limit - Bogdan GusievRails App performance at the limit - Bogdan Gusiev
Rails App performance at the limit - Bogdan Gusiev
 
GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23
GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23
GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23
 

Recently uploaded

Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Mark Simos
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...Nikki Chapple
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...BookNet Canada
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...itnewsafrica
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
Laying the Data Foundations for Artificial Intelligence!
Laying the Data Foundations for Artificial Intelligence!Laying the Data Foundations for Artificial Intelligence!
Laying the Data Foundations for Artificial Intelligence!Memoori
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesManik S Magar
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integrationmarketing932765
 
Dynamical Context introduction word sensibility orientation
Dynamical Context introduction word sensibility orientationDynamical Context introduction word sensibility orientation
Dynamical Context introduction word sensibility orientationBuild Intuit
 
Landscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfLandscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfAarwolf Industries LLC
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
QMMS Lesson 2 - Using MS Excel Formula.pdf
QMMS Lesson 2 - Using MS Excel Formula.pdfQMMS Lesson 2 - Using MS Excel Formula.pdf
QMMS Lesson 2 - Using MS Excel Formula.pdfROWELL MARQUINA
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesBernd Ruecker
 
All These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFAll These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFMichael Gough
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observabilityitnewsafrica
 

Recently uploaded (20)

Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
Laying the Data Foundations for Artificial Intelligence!
Laying the Data Foundations for Artificial Intelligence!Laying the Data Foundations for Artificial Intelligence!
Laying the Data Foundations for Artificial Intelligence!
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
 
Dynamical Context introduction word sensibility orientation
Dynamical Context introduction word sensibility orientationDynamical Context introduction word sensibility orientation
Dynamical Context introduction word sensibility orientation
 
Landscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfLandscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdf
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
QMMS Lesson 2 - Using MS Excel Formula.pdf
QMMS Lesson 2 - Using MS Excel Formula.pdfQMMS Lesson 2 - Using MS Excel Formula.pdf
QMMS Lesson 2 - Using MS Excel Formula.pdf
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architectures
 
All These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFAll These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDF
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
 

Ruby microservices with Docker - Sergii Koba

  • 2. About me ● Serhii Koba ● Position ○ Web Team lead at MobiDev ○ Lecturer at KhAI ● Fullstack ○ BE: Ruby, Go, Php, Python ○ FE: Vue JS ○ DO: Docker, Ansible ○ IoT, Blockchain, Android ● Blogger a bit ● Personal moto: Until we learn - we live Social media: ● http://1devblog.org ● github: @sergey-koba-mobidev ● twitter: @KobaSerhii ● facebook: @kobaserhii
  • 3. What we will talk about ● How Docker helps building Ruby Microservices ● Automating development processes ● Repeatable environment ● Optimization of Docker images ● Refactoring Docker Compose files ● Central logging with Docker ● Routing requests to microservices ● Deploy?
  • 4. What we will not talk about ● When to use microservices ● What is the best framework/language for microservices ● How to migrate to microservices ● How to install Docker, Docker Compose ● Docker for Dummies :) ● Is Rails good for Microservices
  • 6. Two words about Docker ● Application build and deploy tool ● Containers based virtualization (shares host OS kernel) ● Each container is based on image ● Each piece of software (service) should be a container ● Lightweight ● Secure https://www.docker.com/what-container
  • 7. Ruby microservice: Sinatra + Trailblazer # service.rb # https://github.com/bark-iot/ require 'sinatra' set :bind, '0.0.0.0' set :port, 80 get '/houses' do result = House::List.(user_id: USER['id']) if result.success? body House::Representer.for_collection.new(result['models'] ).to_json else status 422 body result['contract.default'].errors.messages.uniq.to_json end end # concepts/house/operations/list.rb class House < Sequel::Model(DB) class List < Trailblazer::Operation step Contract::Build() step Contract::Validate() step :list_by_user_id #... def list_by_user_id(options, params:, **) options['models'] = House.where(user_id: params[:user_id]).all options['models'] end end end Hi @apotonick
  • 8. Dockerfile FROM ruby:2.5.0 # Pg RUN apt-get update -qq && apt-get install -y build-essential libpq-dev lsb-release ENV APP_ROOT /app RUN mkdir $APP_ROOT WORKDIR $APP_ROOT EXPOSE 80 # Bundle COPY Gemfile /app/Gemfile COPY Gemfile.lock /app/Gemfile.lock RUN gem update bundler && bundle install --jobs 4 # Copy the rest of source COPY . /app Build image docker build -f Dockerfile.test -t house-service/test . List images docker images REPOSITORY | TAG | IMAGE ID | CREATED | SIZE house-service/test | latest | c9b0fe5b01d1 | 2 minutes ago | 985MB Run docker run -i -p 80:80 house-service/test bundle exec ruby service.rb 985 MB
  • 9. Dockerfile: Use Alpine linux FROM ruby:2.5.0-alpine # Pg RUN apk --update --upgrade add postgresql-dev git build-base ENV APP_ROOT /app RUN mkdir $APP_ROOT WORKDIR $APP_ROOT EXPOSE 80 # Bundle COPY Gemfile /app/Gemfile COPY Gemfile.lock /app/Gemfile.lock RUN gem update bundler && bundle install --jobs 4 # Copy the rest of source COPY . /app Build image docker build -f Dockerfile.test -t house-service/test . List images docker images REPOSITORY | TAG | IMAGE ID | CREATED | SIZE house-service/test | latest | ab58dd76e0d3 | 2 minutes ago | 320MB 320 MB
  • 10. Dockerfile: Multistage builds FROM ruby:2.5.0-alpine as bundler # CODE FROM PREVIOUS SLIDE # Stage 2 FROM ruby:2.5.0-alpine RUN apk --update --upgrade add postgresql-dev EXPOSE 80 ENV APP_ROOT /app RUN mkdir $APP_ROOT WORKDIR $APP_ROOT # Copy the rest of source COPY . /app COPY --from=bundler /usr/local/bundle /usr/local/bundle Build image docker build -f Dockerfile.test -t house-service/test . List images docker images REPOSITORY | TAG | IMAGE ID | CREATED | SIZE house-service/test | latest | 8f5a46611b7e | 2 minutes ago | 127MB 127 MB
  • 13. Docker Compose: Yml file Let's assume each service is placed in a separate folder ./house-service ./user-service ./device-service ... house-service: build: ../house-service command: bundle exec ruby service.rb networks: - my-network ports: - 80 volumes: - ../house-service/:/app environment: POSTGRES_USER: my_user POSTGRES_PASSWORD: my_pass POSTGRES_DB: my_db RACK_ENV: development stdin_open: true tty: true
  • 14. Docker Compose: Multiple services services: db: image: postgres:latest ports: - "5432:5432" environment: POSTGRES_USER: my_user POSTGRES_PASSWORD: my_pass POSTGRES_DB: my_db redis: image: redis:4.0.5 house-service: … user-service: … user-service: build: ../user-service command: bundle exec ruby service.rb networks: - my-network ports: - 80 volumes: - ../user-service/:/app environment: POSTGRES_USER: my_user POSTGRES_PASSWORD: my_pass POSTGRES_DB: my_db RACK_ENV: development stdin_open: true tty: true Run services: docker-compose up -d 16 lines
  • 15. Docker Compose: extension fields ● Yaml anchors and extend ● Docker Compose file version 3.4 ● “X-” sections (extension fields) x-base-service: &base-service command: bundle exec ruby service.rb networks: - my-network ports: - 80 environment: POSTGRES_USER: my_user POSTGRES_PASSWORD: my_pass POSTGRES_DB: my_db stdin_open: true tty: true users-service: << : *base-service build: ../users-service volumes: - ../users-service/:/app 5 lines
  • 16. Docker Compose: Production In production we want to do things differently: ● Use images instead of build ● Remove stdin and tty ● Remove volumes with app code ● Remove test containers x-base-service: &base-service command: bundle exec ruby service.rb networks: - my-network ports: - 80 environment: POSTGRES_USER: my_user POSTGRES_PASSWORD: my_pass POSTGRES_DB: my_db RACK_ENV: production users-service: << : *base-service image: myapp/users-service:latest
  • 17. Two options: ● Two separate docker-compose.yml files ● Overriding files Docker Compose: Multiple Files Run Development docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d # docker-compose.yml PRODUCTION house-service: image: myapp/house-service:latest command: bundle exec ruby service.rb networks: - my-network ports: - 80 environment: POSTGRES_USER: my_user POSTGRES_PASSWORD: my_pass POSTGRES_DB: my_db # docker-compose.dev.yml DEV house-service: build: ../user-service command: bundle exec ruby service.rb environment: RACK_ENV: development
  • 19. Logging ● View logs from multiple Docker containers ● Tracing data across multiple containers ● Tracing user action across multiple containers ● Aggregate logs ● Search logs View logs on a single container docker-compose -f docker-compose.yml -f docker-compose.dev.yml logs house-service
  • 21. Logging: ELK with Docker logstash: build: docker/logstash/ command: logstash -f /etc/logstash/conf.d/logstash.conf ports: - "12201:12201/udp" kibana: build: docker/kibana/ ports: - "5601:5601" elasticsearch: image: elasticsearch:latest command: elasticsearch -Enetwork.host=0.0.0.0 ports: - "9200:9200" - "9300:9300" environment: ES_JAVA_OPTS: "-Xms750m -Xmx750m" volumes: - /usr/share/elasticsearch/data
  • 22. Logging: ELK with Docker # kibana.yml port: 5601 host: "0.0.0.0" elasticsearch_url: "http://elasticsearch:9200" elasticsearch_preserve_host: true kibana_index: ".kibana" default_app_id: "discover" request_timeout: 300000 shard_timeout: 0 verify_ssl: true bundled_plugin_ids: - plugins/dashboard/index - ... // logstash.conf input { gelf {} } output { elasticsearch { hosts => "elasticsearch:9200" } }
  • 23. Logging: Gelf driver for Docker containers x-logging: &logging driver: gelf options: gelf-address: 'udp://localhost:12201' tag: '{{.Name}}' house-service: << : *logging user-service: << : *logging Template variable
  • 24. Logging: Add log messages to Ruby service class House < Sequel::Model(DB) class Create < Trailblazer::Operation step Model(House, :new) step :generate_key_and_secret step Contract::Persist() step :log_success failure :log_failure #... def log_success(options, params:, model:, **) LOGGER.info "[#{self.class}] Created house with params #{params.to_json}. House: #{House::Representer.new(model).to_json}" end def log_failure(options, params:, **) LOGGER.info "[#{self.class}] Failed to create house with params #{params.to_json}" end end
  • 27. Routing: first try house-service: ... ports: - 3000 user-service: ... ports: - 3001 device-service: ... ports: - 3002 # house-service/service.rb require 'sinatra' set :bind, '0.0.0.0' set :port, 3000 # user-service/service.rb require 'sinatra' set :bind, '0.0.0.0' set :port, 3001 http://localhost:3000 http://localhost:3001
  • 28. Routing: Docker haproxy lb: image: dockercloud/haproxy links: - house-service volumes: - /var/run/docker.sock:/var/run/docker.sock ports: - 80:80 house-service: ... environment: VIRTUAL_HOST: "*/houses*" VIRTUAL_HOST_WEIGHT: 102 http://samos-it.com/posts/docker-multi-website-single-ip-host-haproxy.html Docker Swarm Compatible
  • 29. Possible routers - Docker cloud proxy (Deprecated) - Traefik https://traefik.io/ - Caddy https://caddyserver.com/ - Zookeeper
  • 31. Conclusion ● All in one environment and tools for Ruby microservices ● Minimized Docker images ● Minimized Docker Compose file ● Central logging and tracing using ELK ● Routing (balancing) requests What’s next? ● Authorization layers? ● gRPC for inter communication? ● Message broker? ● Migrating monolith Rails app to Microservices? :)