Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

of

Ruby microservices with Docker -  Sergii Koba Slide 1 Ruby microservices with Docker -  Sergii Koba Slide 2 Ruby microservices with Docker -  Sergii Koba Slide 3 Ruby microservices with Docker -  Sergii Koba Slide 4 Ruby microservices with Docker -  Sergii Koba Slide 5 Ruby microservices with Docker -  Sergii Koba Slide 6 Ruby microservices with Docker -  Sergii Koba Slide 7 Ruby microservices with Docker -  Sergii Koba Slide 8 Ruby microservices with Docker -  Sergii Koba Slide 9 Ruby microservices with Docker -  Sergii Koba Slide 10 Ruby microservices with Docker -  Sergii Koba Slide 11 Ruby microservices with Docker -  Sergii Koba Slide 12 Ruby microservices with Docker -  Sergii Koba Slide 13 Ruby microservices with Docker -  Sergii Koba Slide 14 Ruby microservices with Docker -  Sergii Koba Slide 15 Ruby microservices with Docker -  Sergii Koba Slide 16 Ruby microservices with Docker -  Sergii Koba Slide 17 Ruby microservices with Docker -  Sergii Koba Slide 18 Ruby microservices with Docker -  Sergii Koba Slide 19 Ruby microservices with Docker -  Sergii Koba Slide 20 Ruby microservices with Docker -  Sergii Koba Slide 21 Ruby microservices with Docker -  Sergii Koba Slide 22 Ruby microservices with Docker -  Sergii Koba Slide 23 Ruby microservices with Docker -  Sergii Koba Slide 24 Ruby microservices with Docker -  Sergii Koba Slide 25 Ruby microservices with Docker -  Sergii Koba Slide 26 Ruby microservices with Docker -  Sergii Koba Slide 27 Ruby microservices with Docker -  Sergii Koba Slide 28 Ruby microservices with Docker -  Sergii Koba Slide 29 Ruby microservices with Docker -  Sergii Koba Slide 30 Ruby microservices with Docker -  Sergii Koba Slide 31
Upcoming SlideShare
What to Upload to SlideShare
Next
Download to read offline and view in fullscreen.

0 Likes

Share

Download to read offline

Ruby microservices with Docker - Sergii Koba

Download to read offline

Ruby Meditation #21
April 14, 2018
Kharkiv

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all
  • Be the first to like this

Ruby microservices with Docker - Sergii Koba

  1. 1. Ruby microservices With Docker
  2. 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. 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. 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
  5. 5. Docker
  6. 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. 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. 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. 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. 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
  11. 11. Dockerfile: Results 8x
  12. 12. Docker Compose
  13. 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. 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. 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. 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. 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
  18. 18. Central Logging
  19. 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
  20. 20. Logging: ELK stack
  21. 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. 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. 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. 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
  25. 25. Logging: Kibana
  26. 26. Routing
  27. 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. 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. 29. Possible routers - Docker cloud proxy (Deprecated) - Traefik https://traefik.io/ - Caddy https://caddyserver.com/ - Zookeeper
  30. 30. Conclusion
  31. 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? :)

Ruby Meditation #21 April 14, 2018 Kharkiv

Views

Total views

3,085

On Slideshare

0

From embeds

0

Number of embeds

1,764

Actions

Downloads

14

Shares

0

Comments

0

Likes

0

×