<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Pramod Shinde</title>
    <description>The latest articles on DEV Community by Pramod Shinde (@pramodshinde7).</description>
    <link>https://dev.to/pramodshinde7</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F614865%2F612b50c1-a8ce-454a-bc04-e082fe6b035c.jpeg</url>
      <title>DEV Community: Pramod Shinde</title>
      <link>https://dev.to/pramodshinde7</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pramodshinde7"/>
    <language>en</language>
    <item>
      <title>Rails: Searchable logs with Filebeat and Elastic Stack</title>
      <dc:creator>Pramod Shinde</dc:creator>
      <pubDate>Sat, 17 Apr 2021 15:17:16 +0000</pubDate>
      <link>https://dev.to/pramodshinde7/searchable-logs-with-filebeat-and-elastic-stack-2enc</link>
      <guid>https://dev.to/pramodshinde7/searchable-logs-with-filebeat-and-elastic-stack-2enc</guid>
      <description>&lt;p&gt;In a data sensitive application debugging is the most critical and time consuming especially if requests traffic is tremendously high, when it comes to debugging every developer’s last resort is application logs and debugging in large logs file is not an easy task.&lt;/p&gt;

&lt;p&gt;In this post I will brief you about how we can make rails logs searchable, Using &lt;a href="https://www.elastic.co/beats/filebeat" rel="noopener noreferrer"&gt;Filebeat&lt;/a&gt; and &lt;a href="https://dev.toElastic%20Stack"&gt;Elastic Stack&lt;/a&gt; for making debugging fast and easy via UI enabled log search. Wait…, Filebeat is not a separate entity it falls under an elastic stack only which is a lightweight log shipper which will not hoard your resources.&lt;/p&gt;

&lt;p&gt;This post will cover following&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Brief intro to Elastic Stack&lt;/li&gt;
&lt;li&gt;Filebeat configuration and setup&lt;/li&gt;
&lt;li&gt;Custom Index Template with rollover for application logs&lt;/li&gt;
&lt;li&gt;Lograge setup to output logs into JSON format&lt;/li&gt;
&lt;li&gt;Demo Rails application &lt;a href="https://github.com/pramodshinde/efk-rails" rel="noopener noreferrer"&gt;refer this repository&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Brief about Elastic Stack
&lt;/h2&gt;

&lt;p&gt;Elastic stack comprises of &lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html" rel="noopener noreferrer"&gt;Elasticsearch&lt;/a&gt;, &lt;a href="https://www.elastic.co/kibana" rel="noopener noreferrer"&gt;Kibana&lt;/a&gt;, &lt;a href="https://www.elastic.co/beats/" rel="noopener noreferrer"&gt;Beats&lt;/a&gt;, and &lt;a href="https://www.elastic.co/logstash" rel="noopener noreferrer"&gt;Logstash&lt;/a&gt; formerly known as the ELK Stack which is used to monitor, visualize, search and analyse the applications data in realtime and Filebeat is a lightweight data shipper belonging to the &lt;a href="https://www.elastic.co/beats/" rel="noopener noreferrer"&gt;Beats family&lt;/a&gt; which is mainly used to ship data from files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filebeat setup and configuration
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Installation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Installation of filebeat is dead simple. You can follow simple steps described in official &lt;a href="https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-installation.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sample filebeat.yml&lt;/strong&gt; – /usr/local/etc/filebeat/filebeat.yml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#---------- Filebeat inputs ----------
filebeat.inputs:
- type: log
  enabled: true
  json:
    message_key: message
    keys_under_root: true
    overwrite_keys: true
  paths:
    - /Users/pramod/projects/efk-rails/log/sync_development.log
#ElasticSearch template setting 
setup.ilm.enabled: false
setup.template.enabled: false
setup.template.name: "efk-rails-sync-dev"
setup.template.pattern: "efk-rails-sync-dev-*"
#---------- Kibana ----------
setup.kibana:
  host: "0.0.0.0:5601"
#---------- Elasticsearch output ----------
output.elasticsearch:
  # Array of hosts to connect to.
  hosts: ["0.0.0.0:9200"]
  index: "sync-log-dev"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In above configuration file we have configured following options&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;inputs – Used for specifying input for filebeat, here we have configured input as rails log file &lt;em&gt;/Users/pramod/projects/efk-rails/log/sync_development.log&lt;/em&gt; with JSON option which will decode logs structured as JSON messages&lt;/li&gt;
&lt;li&gt;output – Used to set the output for filebeat, here we will write to elasticsearch indexes.&lt;/li&gt;
&lt;li&gt;setup.kibana – the Kibana endpoint which will load the kibana dashboard&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Custom Index Template with rollover
&lt;/h2&gt;

&lt;p&gt;We off course can use the default &lt;a href="https://www.elastic.co/guide/en/beats/filebeat/current/configuration-template.html" rel="noopener noreferrer"&gt;template&lt;/a&gt; and &lt;a href="https://www.elastic.co/guide/en/beats/filebeat/current/ilm.html" rel="noopener noreferrer"&gt;rollover&lt;/a&gt; options but you cannot use the custom index template names, this is specially needed if you want the setup environment wise kibana dashboards on a single kibana and elasticsearch instances and this is what we needed in most of the Rails applications. &lt;/p&gt;

&lt;p&gt;Here we will use the custom template and index lifecycle management (ilm) for rotating our logs indexes as per different rails environments.&lt;/p&gt;

&lt;p&gt;To enable a custom index template name and &lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/7.8/set-up-lifecycle-policy.html" rel="noopener noreferrer"&gt;rollover policy&lt;/a&gt; you need to follow the following steps&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Setup a ilm enabled to false, add custom template name and pattern with following options
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setup.ilm.enabled: false
setup.template.enabled: false
setup.template.name: "efk-rails-sync-dev"
setup.template.pattern: "efk-rails-sync-dev-*"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above config will tell filebeat to use &lt;em&gt;efk-rails-sync-dev&lt;/em&gt; and &lt;em&gt;efk-rails-sync-dev-*&lt;/em&gt; name and index pattern respectively, It’s a common practice to specify the index pattern rather than using index name.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a life cycle policy using &lt;a href="https://www.elastic.co/guide/en/kibana/current/console-kibana.html" rel="noopener noreferrer"&gt;Kibana dev tool&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUT _ilm/policy/sync-log
{
  "policy": {
    "phases": {
      "hot": {
        "min_age": "0ms",
        "actions": {
          "rollover": {
            "max_age": "3d",
            "max_size": "100mb"
          }
        }
      },
      "delete": {
        "min_age": "2d",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above will create index lifecycle policy which will rollover indexes if its size reaches to 100mb or index age is 3 days whichever turns first true.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create template pattern using &lt;a href="https://www.elastic.co/guide/en/kibana/current/console-kibana.html" rel="noopener noreferrer"&gt;Kibana dev tool&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUT _template/efk-rails-sync-dev
{
  "index_patterns": ["efk-rails-sync-dev-*"], 
  "settings": {
    "number_of_shards": 1,
    "index.lifecycle.name": "sync-log", 
    "index.lifecycle.rollover_alias": "sync-log-dev"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a template &lt;code&gt;efk-rails-sync-dev&lt;/code&gt; with index alias &lt;code&gt;sync-log-dev&lt;/code&gt; and attach lifecycle policy &lt;code&gt;sync-log&lt;/code&gt; that created in step 2.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In last step we will create the first index managed by a policy that uses the rollover action and designate it as the write index
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUT efk-rails-sync-dev-000001 
{
  "aliases": {
    "sync-log-dev":{
      "is_write_index": true
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create initial index &lt;code&gt;efk-rails-sync-dev-000001&lt;/code&gt; which will be used by filebeat to write output of application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Application logs in JSON format
&lt;/h2&gt;

&lt;p&gt;Once you create index life cycle policy, template and first rollover index which will capture logs from filebeat harvester. You need make your application logs to output in JSON format.&lt;/p&gt;

&lt;p&gt;To output rails logs into JSON format, we are using &lt;a href="https://github.com/roidrage/lograge" rel="noopener noreferrer"&gt;lograge&lt;/a&gt; gem once you add it in Gemfile and bundle install it will be available to use in you application.&lt;/p&gt;

&lt;p&gt;For demo purpose, We will be logging only single controller actions into JSON and search via Kibana.&lt;/p&gt;

&lt;p&gt;Following lograge configuration will output logs in JSON for SyncContoller#index and SyncController#Create action&lt;/p&gt;

&lt;p&gt;$config/initializers/lograge.rb&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Rails.application.configure do
  config.lograge.enabled = true
  config.lograge.keep_original_rails_log = true
  config.lograge.base_controller_class = 'ActionController::API'
  config.lograge.logger = ActiveSupport::Logger.new "#{Rails.root}/log/sync_#{Rails.env}.log"
  config.lograge.formatter = Lograge::Formatters::Json.new
  config.lograge.ignore_custom = lambda do |event|
    # return true here if you want to ignore based on the event
    return false if event.payload[:controller].include?("SyncController") &amp;amp;&amp;amp;
     ['index', 'create'].include?(event.payload[:action])
    return true
  end
  config.lograge.custom_payload do |controller|
    if controller.class.name.include?('SyncController')
      SyncLogger.new(controller).log_data
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SyncLogger service to add some meta data to logger file&lt;br&gt;
$app/services/sync_logger.rb&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class SyncLogger
  def initialize(controller)
    @controller = controller
  end
  def log_data
    request_type = @controller.request.method
    username = @controller.current_user.try(:username) || 'guest'
    r_data = request_type == 'GET' ? JSON.parse(@controller.response.body) : @controller.request.parameters
    log_data = {
      u_agent: @controller.request.user_agent,
      request_time: Time.now.to_s(:number),
      search_key: "#{request_type}_#{username}_#{Time.zone.now.to_s(:number)}",
      ip: @controller.request.ip,
      user_id: @controller.current_user.try(:id),
      username: username,
      data: r_data
    }
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above service will create JSON output for SyncContoller#index and SyncController#Create action in following format&lt;/p&gt;

&lt;p&gt;$log/sync_development.log&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"method":"GET","path":"/sync","format":"*/*","controller":"SyncController","action":"index","status":200,"duration":16.64,"view":1.18,"db":0.2,"u_agent":"PostmanRuntime/7.26.1","request_time":"20200818210529","search_key":"GET_pramod_20200818153529","ip":"127.0.0.1","user_id":1,"username":"pramod","data":[{"username":"pramod"},{"username":"pramdo1"}]}
{"method":"GET","path":"/sync","format":"*/*","controller":"SyncController","action":"index","status":200,"duration":15.82,"view":0.48,"db":0.93,"u_agent":"PostmanRuntime/7.26.1","request_time":"20200818210647","search_key":"GET_pramod_20200818153647","ip":"127.0.0.1","user_id":1,"username":"pramod","data":[{"username":"pramod"},{"username":"pramdo1"}]}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-starting.html" rel="noopener noreferrer"&gt;Starting filebeat&lt;/a&gt; to ship above logs to elasticsearch by executing following command from the root of the filebeat if you have downloaded the tar and extracted it or if you have installed filebeat as a service you can start filebeat as a service&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./filebeat -e
or 
sudo service filebeat start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see following filebeat logs on successful&lt;br&gt;

  logs output
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INFO    registrar/registrar.go:152  States Loaded from registrar: 2
2020-08-18T21:46:30.722+0530    INFO    crawler/crawler.go:72   Loading Inputs: 1
2020-08-18T21:46:30.723+0530    INFO    log/input.go:152    Configured paths: [/Users/pramod/projects/efk-rails/log/sync_development.log]
2020-08-18T21:46:30.723+0530    INFO    input/input.go:114  Starting input of type: log; ID: 15918551478222648142
2020-08-18T21:46:30.723+0530    INFO    crawler/crawler.go:106  Loading and starting Inputs completed. Enabled inputs: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;/p&gt;

&lt;h2&gt;
  
  
  Kibana in Action
&lt;/h2&gt;

&lt;p&gt;If above all is set correctly, We can search logs via Kibana by creating index pattern. You should see &lt;code&gt;efk-rails-sync-dev-000001&lt;/code&gt; index in kibana index management, Using same index you can create index pattern for search.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ficp2apsyycu5mw96r4dc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ficp2apsyycu5mw96r4dc.png" alt="Kibana Index"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Searching via Kibana Discover&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F77jhfmatrdj7o8uufp9l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F77jhfmatrdj7o8uufp9l.png" alt="Kibana Discover"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes, We are done! if you follow above mentioned steps you should be able to do similar setup in your application. If you have any doubts or suggestions let me know in comments section.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>elasticsearch</category>
      <category>rails</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Creating {legacy} static build via docker and deploying with mina-scp</title>
      <dc:creator>Pramod Shinde</dc:creator>
      <pubDate>Thu, 15 Apr 2021 16:03:16 +0000</pubDate>
      <link>https://dev.to/pramodshinde7/creating-legacy-static-build-via-docker-and-deploying-with-mina-scp-3hde</link>
      <guid>https://dev.to/pramodshinde7/creating-legacy-static-build-via-docker-and-deploying-with-mina-scp-3hde</guid>
      <description>&lt;p&gt;I am sure! Many of our applications have turned into a legacy codebase, such applications might have some outdated scripts or build process that might need frequent maintenance and updates. &lt;/p&gt;

&lt;p&gt;In this post, I will walk you through the steps with which we can move our frontend build creation script into the docker container and deploy through &lt;a href="http://nadarei.co/mina/"&gt;mina&lt;/a&gt; and &lt;a href="https://github.com/adie/mina-scp"&gt;mian-scp&lt;/a&gt; gems seamlessly. &lt;/p&gt;

&lt;p&gt;Even if your code is not a legacy codebase it is always better to build your application into a docker container because &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need to create build in a production like environments &lt;/li&gt;
&lt;li&gt;If you want to do a production system upgrades, it's lot more easier to test build creation in docker containers in advance &lt;/li&gt;
&lt;li&gt;Avoid any package missing or mis-match issues at runtime, specially on older node versions &amp;lt; 6.x.x. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Brief background
&lt;/h2&gt;

&lt;p&gt;I had a &lt;code&gt;angular 1.x&lt;/code&gt; application running with node 6.x.x, things were all good until we noticed following&lt;br&gt;
 &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First issue was previously on servers node-modules and bower packages were moved on servers manually&lt;/li&gt;
&lt;li&gt;We were having two(production/staging) servers with different node &lt;code&gt;5.x.x&lt;/code&gt; and &lt;code&gt;6.x.x&lt;/code&gt; setup receptively. &lt;/li&gt;
&lt;li&gt;In older &lt;code&gt;node &amp;lt;= 5.x.x&lt;/code&gt;, &lt;code&gt;npm install&lt;/code&gt; does not support &lt;code&gt;package.json&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Package addition and updates were a nightmare&lt;/li&gt;
&lt;li&gt;We were frequently facing package related issues because of lack of proper &lt;code&gt;package.json&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We resolved all above issues one by one after deciding to fix the node version and upgraded to version &lt;code&gt;6.x.x&lt;/code&gt; and moved the build creation process into a docker container to have a standard build creation and deployment process.&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating a build in docker container via docker compose
&lt;/h2&gt;

&lt;p&gt;If you are new to docker and docker-compose, I would advise you to get your hands dirty in docker concepts by referring it &lt;a href="https://www.docker.com/"&gt;here&lt;/a&gt; and &lt;a href="https://docs.docker.com/compose/"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Dockerfile
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;Dockerfile&lt;/code&gt;&lt;/strong&gt;: In this file we are only specifying required ubuntu, node, npm and yarn versions that are required for application and before that we are installing few dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM ubuntu:18.04
SHELL ["/bin/bash", "-l", "-c"]

RUN mkdir /usr/local/nvm
ENV NVM_DIR /usr/local/nvm
ENV NODE_VERSION 6.13.0
ENV NVM_INSTALL_PATH $NVM_DIR/versions/node/v$NODE_VERSION

# install ubuntu related dependencies
RUN apt-get update -q &amp;amp;&amp;amp; \
    apt-get install -qy curl ca-certificates gnupg2 build-essential --no-install-recommends &amp;amp;&amp;amp; apt-get clean
RUN apt-get install -y git zip

# install nvm
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash

# install node version 6.13.0
RUN source $NVM_DIR/nvm.sh \
    &amp;amp;&amp;amp; nvm install $NODE_VERSION \
    &amp;amp;&amp;amp; nvm alias default $NODE_VERSION \
    &amp;amp;&amp;amp; nvm use default

WORKDIR /usr/bullet

# copy dependencies json file to docker container
COPY package.json $WORKDIR
COPY yarn.lock $WORKDIR
COPY bower.json $WORKDIR

# install package manager
RUN source $NVM_DIR/nvm.sh &amp;amp;&amp;amp; npm install -g yarn@1.17.0
RUN source $NVM_DIR/nvm.sh &amp;amp;&amp;amp; npm install -g bower@1.8.0

RUN source $NVM_DIR/nvm.sh &amp;amp;&amp;amp; npm install -g gulp@3.9.1

RUN source $NVM_DIR/nvm.sh &amp;amp;&amp;amp; yarn install --quiet
RUN source $NVM_DIR/nvm.sh &amp;amp;&amp;amp; bower install --quiet --allow-root

COPY . $WORKDIR
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the dockerfile is ready we can use this in docker-compose with following docker-compose.yml file to create multiple services&lt;/p&gt;

&lt;h3&gt;
  
  
  docker-compose.yml
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3.4'

services:  
  frontend-app: &amp;amp;frontend-app
    build:
      context: .
      dockerfile: ./Dockerfile
    image: my-frontend-app:0.0.1
    volumes:
      - ./:/usr/frontend-app/
      - ./static_build:/usr/frontend-app/static_build
      - nodemodules:/usr/frontend-app/node_modules  
      - bowercomponents:/usr/frontend-app/bower_components
  start:
    &amp;lt;&amp;lt;: *frontend-app   
    ports:
      - '8000:8000'
    command: bash -c "source /usr/local/nvm/nvm.sh &amp;amp;&amp;amp; gulp dev"

  create_build:
    &amp;lt;&amp;lt;: *frontend-app 
    command: bash -c "source /usr/local/nvm/nvm.sh &amp;amp;&amp;amp; gulp prod &amp;amp;&amp;amp; rm -f static_build/build.zip &amp;amp;&amp;amp; zip -rq static_build/build.zip build/"

volumes: 
  nodemodules: {}
  bowercomponents: {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In docker-compose file we are creating &lt;code&gt;start&lt;/code&gt; and &lt;code&gt;create_build&lt;/code&gt; services, &lt;code&gt;start&lt;/code&gt; is to start the application inside the docker container with following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#Running build on port 8080
source /usr/local/nvm/nvm.sh &amp;amp;&amp;amp; gulp dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;create_build&lt;/code&gt; is to create and compress a build with following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#Creating prod build, removing old build and creating new build
source /usr/local/nvm/nvm.sh &amp;amp;&amp;amp; gulp prod &amp;amp;&amp;amp; rm -f static_build/build.zip &amp;amp;&amp;amp; zip -rq static_build/build.zip build/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Important to note that we have created shared volumes and folders between host and container, So that we can have &lt;code&gt;build.zip&lt;/code&gt; to be created on host and node modules can be shared across the builds if no changes to package.json  &lt;/p&gt;

&lt;p&gt;Once above setup is done we can easily create or start the build using following commands&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#Starting a build
docker-compose up start
#Creating a build
docker-compose up create_build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After above setup is verified we can deploy this build via mina and mina-scp gem as following&lt;/p&gt;

&lt;p&gt;Note: Hope you have done basic setup which is needed for mina deployment.(Let me know if you need any help!)&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying static build to servers
&lt;/h2&gt;

&lt;p&gt;Following is the sample mina deployment script which is copying and zipping build to the server. &lt;/p&gt;

&lt;h3&gt;
  
  
  config/deploy.rb
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#Mina, version v0.3.8
require 'mina/scp'

# Basic settings like branch, server repo settings goes here
# set :branch, staging
# gem install mina -v 0.3.8 (you can use latest mina version)
# gem install mina-scp -v 0.1.2

# Put any custom mkdir's in here for when `mina setup` is ran.
# all releases.
task :setup =&amp;gt; :environment do
end

desc "create a build on the local"
task :create_build =&amp;gt; :environment do
  to :before_hook do
    # Put things to run locally before ssh
    queue! %[echo "-----&amp;gt; creating static build..."]
    queue! %[sudo docker-compose up create_build]
  end
end

desc "Deploys the current version to the server."
task :deploy =&amp;gt; :environment do

  deploy do
    # Put things that will set up an empty directory into a fully set-up
    # instance of your project.
    invoke :'deploy:link_shared_paths'
    queue! %[echo "-----&amp;gt; uploading build domain: #{domain} branch: #{branch}, deploy_to: #{deploy_to}"]
    scp_upload('./static_build/build.zip', "#{deploy_to}/build.zip", verbose: true) 
    invoke :'deploy:cleanup'

    to :launch do
      queue "echo '-----&amp;gt; Unziping build...'"
      queue "cp #{deploy_to}/build.zip #{deploy_to}/current/build.zip" 
      queue "unzip -q #{deploy_to}/current/build.zip"
      queue "echo '-----&amp;gt; Unzip completed'"
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are creating and deploying build via&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mina create_build
mina deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have noticed we are copying build &lt;code&gt;./static_build/build.zip&lt;/code&gt; created in docker via mina-scp's &lt;code&gt;scp_upload&lt;/code&gt; command and unzipping in deploy task.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scp_upload('./static_build/build.zip', "#{deploy_to}/build.zip", verbose: true)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it, We have successfully created and deployed static build with the help of docker and mina. If you have reached here and have any suggestions or thoughts let me know in comments section. &lt;/p&gt;

</description>
      <category>rails</category>
      <category>docker</category>
      <category>angular</category>
      <category>ruby</category>
    </item>
    <item>
      <title>10 Signs of a good Ruby on Rails Developer</title>
      <dc:creator>Pramod Shinde</dc:creator>
      <pubDate>Thu, 15 Apr 2021 08:02:38 +0000</pubDate>
      <link>https://dev.to/pramodshinde7/10-signs-of-a-good-ruby-on-rails-developer-2nc4</link>
      <guid>https://dev.to/pramodshinde7/10-signs-of-a-good-ruby-on-rails-developer-2nc4</guid>
      <description>&lt;p&gt;I have been working as Ruby on Rails developer since last five years with Josh Software, I felt that I should write down my learnings about the best practices followed by the RoR developer. How I learned …? of course to learn something you need to commit the mistakes, thats how we learn right?&lt;/p&gt;

&lt;p&gt;Let’s see, What all you should follow to be a ‘Good’ Ruby on Rails developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Your migrations are “thoughtful” …
&lt;/h2&gt;

&lt;p&gt;Whenever you come across database table schema design do you think through all the aspects like&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The table which is being designed where its going to be used? How much it might grow in terms of the data size? (Imagine the worst future of your design)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Have I kept correct data types, defaults, constraints if any? Most of the times we really don’t need integer columns, We can use &lt;code&gt;smallint&lt;/code&gt; instead for smaller set of &lt;code&gt;integers&lt;/code&gt;, similarly &lt;code&gt;varchar(10)&lt;/code&gt; vs &lt;code&gt;varchar(255)&lt;/code&gt; vs &lt;code&gt;text&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Have I added indexes wherever necessary? Thinking through What kind of the queries this table is going to handle?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;A special point&lt;/strong&gt;…Do you write multiple migrations for same table? if yes, it's a bad habit.&lt;/p&gt;

&lt;p&gt;Often we don’t think through all the points mentioned above and end up creating multiple migrations for same table which causes codebase to look scary.&lt;/p&gt;

&lt;p&gt;Instead you should use &lt;code&gt;up&lt;/code&gt; and &lt;code&gt;down&lt;/code&gt; on the migration to fix or alter the table, change in the requirement is an exception to this.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. You always follow the single responsibility principle
&lt;/h2&gt;

&lt;p&gt;We all know a convention of “&lt;strong&gt;&lt;em&gt;skinny controller and fat model&lt;/em&gt;&lt;/strong&gt;”, some of us already follow this but do we follow it wisely.&lt;/p&gt;

&lt;p&gt;We are living in the Rails 5 era, so Why overload models?&lt;/p&gt;

&lt;p&gt;Why not to follow “&lt;strong&gt;&lt;em&gt;keep everything skinny move extra fat to concerns or service objects from the models&lt;/em&gt;&lt;/strong&gt;”, the classes in the codebase should be designed to handle single responsibility.&lt;/p&gt;

&lt;p&gt;I came across the following posts about how to organise controllers and using service objects in Rails.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;a href="http://jeromedalbert.com/how-dhh-organizes-his-rails-controllers/"&gt;How DHH Organizes His Rails Controllers&lt;/a&gt; &lt;/li&gt;
&lt;li&gt; &lt;a href="https://www.netguru.co/blog/service-objects-in-rails-will-help"&gt;Service objects in Rails&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. You write test cases to test the “code”
&lt;/h2&gt;

&lt;p&gt;I have seen many applications whose CI builds takes ages to finish, &lt;em&gt;What exactly they are testing&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;Your test cases should be testing the “code” not the machine performance, better test suits&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Share objects between different examples.&lt;/li&gt;
&lt;li&gt;Uses method stubs and avoid the repetitive calls to the methods.&lt;/li&gt;
&lt;li&gt;Don’t test same code twice, if you have sharable piece of code and used at multiple places then don’t write test cases in multiple places.&lt;/li&gt;
&lt;li&gt;Does not creates unnecessary test records, unknowingly many developers end up creating unnecessary test records.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your are using gems like  &lt;a href="https://github.com/stympy/faker"&gt;faker&lt;/a&gt; ,  &lt;a href="https://github.com/thoughtbot/factory_bot_rails"&gt;factory_bot_rails&lt;/a&gt;  and &lt;a href="https://github.com/DatabaseCleaner/database_cleaner"&gt;database_cleaner&lt;/a&gt; to create and clean test records then creating unnecessary records can cost you time and speed.&lt;/p&gt;

&lt;p&gt;Simple example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  create_list(:user, 10)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Much better will be reduce the list size, if you are not doing anything special with 10 users.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  create_list(:user, 2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. You keep production environment healthy
&lt;/h2&gt;

&lt;p&gt;If you are an engineer and reduce efforts of others, then you use the utilities of other engineers to reduce your efforts.&lt;/p&gt;

&lt;p&gt;A healthy Rails production environment always have&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://mmonit.com/monit/"&gt;Monit&lt;/a&gt;  – Is everything up and running? if not get notified.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.systutorials.com/docs/linux/man/5-logrotate.conf/"&gt;logrotate&lt;/a&gt; – rotates, compresses, and mails system logs.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://crontab.guru/"&gt;crontabs&lt;/a&gt; with &lt;a href="https://github.com/javan/whenever"&gt;whenever&lt;/a&gt;, schedules work for you.&lt;/li&gt;
&lt;li&gt;Database backup scripts running in maintenance window.&lt;/li&gt;
&lt;li&gt;Exception notifiers like &lt;a href="https://sentry.io/welcome/"&gt;Sentry&lt;/a&gt; or &lt;a href="http://rollbar.com/"&gt;Rollbar&lt;/a&gt; or ‘anything that suits you’.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. You follow basic git etiquettes
&lt;/h2&gt;

&lt;p&gt;If you are working in a team and using git then you follow the git etiquettes like&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don’t commit untracked files – we often keep git untracked files like &lt;code&gt;something.swp&lt;/code&gt;, &lt;code&gt;backup.sql&lt;/code&gt;, ‘schema.rb&lt;code&gt;or&lt;/code&gt;structure.sql backups&lt;code&gt;,&lt;/code&gt;some.test.script`, you should not commit such files.&lt;/li&gt;
&lt;li&gt;Branch naming – naming something is always difficult but you have to do it, the feature branches should have sensible names, don’t use names like &lt;code&gt;something-wip&lt;/code&gt;, &lt;code&gt;somthing-test&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Delete the feature branches after merge – no explanation required.&lt;/li&gt;
&lt;li&gt;Commit messages – your commit messages must have &lt;code&gt;Github issue number&lt;/code&gt; or &lt;code&gt;any project management story number/link&lt;/code&gt;,  &lt;code&gt;brief description about feature/task&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. You don’t ignore README.md
&lt;/h2&gt;

&lt;p&gt;Remember you are not the only one who is going to work on particular application for your lifetime. Someone will takeover you and he should not waste his time in figuring out that how to setup things.&lt;/p&gt;

&lt;p&gt;Your application repository must have updated &lt;code&gt;README.md&lt;/code&gt; with detail steps about setting up an application for the first time.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Secrets are “really” secrets for you
&lt;/h2&gt;

&lt;p&gt;We often use credentials for database configs, secrets.yml, third party api’s like AWS, payment gateway, sentry etc.&lt;/p&gt;

&lt;p&gt;You should not commit such credentials/secrets/environment variables to the Github instead you keep them secure with gems like &lt;a href="https://github.com/bkeepers/dotenv"&gt;dotenv-rails&lt;/a&gt;, &lt;a href="https://github.com/laserlemon/figaro"&gt;figaro&lt;/a&gt; or simple dot files that are not committed to the repository.&lt;/p&gt;

&lt;p&gt;A sample file of such credentials should be committed and updated regularly.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. You do code reviews and discuss feature with team
&lt;/h2&gt;

&lt;p&gt;While working in a team you should get your feature reviewed from another team mate or before starting on any feature discuss it with the team thoroughly, advantages of the code reviews or feature discussion are you will come across many scenarios that are not thought of.&lt;/p&gt;

&lt;p&gt;If you are the only one who is working on a application then you must criticise your own code and cover all the scenarios in test cases.   &lt;/p&gt;

&lt;h2&gt;
  
  
  9. You are up-to-date and keep updating
&lt;/h2&gt;

&lt;p&gt;In open source community we get frequent updates or releases for ruby, rails and gems, you must keep yourself aware and informed by subscribing to the repositories or mailing lists and update your application libraries.&lt;/p&gt;

&lt;p&gt;Also you should stay alert on security fixes about the production operating system, database so you can take necessary action on time.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Need not to say…
&lt;/h2&gt;

&lt;p&gt;You write clean and maintainable code and your codebase is&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Properly indented&lt;/li&gt;
&lt;li&gt;Only 80 columns wide&lt;/li&gt;
&lt;li&gt;Maintainable with smaller methods, less complexity – To know more on this make a habit of using code analyzer like &lt;a href="https://github.com/bbatsov/rubocop"&gt;rubocop&lt;/a&gt;, &lt;a href="https://codeclimate.com/"&gt;Code Climate&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Codebase follows &lt;a href="https://github.com/bbatsov/ruby-style-guide"&gt;Ruby best practices and style guide&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Well there are many more points that can be included in this list but I feel these are the most important to fill in first into this list, If you find that I have missed anything more important then you can comment on this post.&lt;/p&gt;

&lt;p&gt;Thanks for the reading upto here, hope this will help you to become a ‘Good’ developer.&lt;/p&gt;

&lt;p&gt;PS: I am moving out of wordpress this is a cross post. &lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
