Showing posts with label Docker. Show all posts
Showing posts with label Docker. Show all posts

Friday, August 29, 2025

New Feature in Ruby on Rails 8

 

What’s New in Ruby on Rails 8?

Ruby on Rails has always been about developer happiness and productivity. With the release of Rails 8, the framework takes another giant leap forward, making it easier than ever to build, deploy, and scale modern web applications.

In this post, we’ll explore the most exciting new features in Rails 8 and why it matters for developers and businesses.


🌟 1. Built-in Deployment with Kamal (No PaaS Needed)

Traditionally, deploying Rails apps required third-party services like Heroku or custom DevOps pipelines. Rails 8 changes this with Kamal (formerly “MRSK”), a first-class deployment tool included in Rails.

  • 🚀 Deploy Rails apps to any cloud or VPS (AWS, GCP, DigitalOcean, etc.).

  • 🐳 Uses Docker under the hood for consistent environments.

  • 🔄 Rollbacks and zero-downtime deploys out-of-the-box.

👉 This means you can go from development to production without needing a PaaS provider.


🌟 2. Propshaft: The Next-Gen Asset Pipeline

Rails 8 introduces Propshaft, a modern replacement for Sprockets.

  • Simpler, faster, and more reliable.

  • Designed for modern JS & CSS tooling (ESBuild, Vite, Tailwind).

  • No more config-heavy asset management headaches.

👉 With Propshaft, assets are leaner and the pipeline plays nicely with today’s frontend workflows.


🌟 3. Solid Queue: Built-in Background Jobs

Rails has had Active Job for years, but you still needed a backend like Sidekiq or Resque. Rails 8 introduces Solid Queue — a native, database-backed job queue system.

  • 📦 No Redis required — works with just your database.

  • ✅ Great for small to medium apps that don’t need a dedicated queue.

  • 🔄 Still works with external job processors if you want.

👉 Background processing is now easier to set up and manage in any Rails app.


🌟 4. Solid Cache: Smarter Caching with Active Record

Caching has been supercharged in Rails 8 with Solid Cache:

  • Stores cache entries directly in the database.

  • Works well with horizontal scaling (multiple servers).

  • Provides visibility and management through ActiveRecord.

👉 Caching is now simpler and more reliable without needing extra infrastructure.


🌟 5. Rails Defaults 8.0

Every major release updates Rails defaults to modern best practices. In Rails 8, new apps come pre-configured with:

  • Latest security defaults.

  • Zeitwerk mode as the standard.

  • Propshaft instead of Sprockets.

  • Optimized configs for production-ready apps.

👉 Less time tweaking configs, more time building features.


🌟 6. General Improvements & Enhancements

  • Action Mailer improvements → better async delivery.

  • Stronger ActiveRecord performance optimizations.

  • Better support for Hotwire & Turbo out of the box.

  • Minor DX (developer experience) improvements across generators, configs, and logs.


🎯 Why Rails 8 Matters

Rails 8 isn’t just an upgrade — it’s a statement:

  • Developers get full-stack power without extra tools.

  • Small teams can ship production apps without DevOps complexity.

  • Rails remains one of the fastest ways to build modern web apps.

With Kamal, Propshaft, Solid Queue, and Solid Cache, Rails 8 gives developers the full power of a modern framework + deployment + infrastructure in one package.


✅ Final Thoughts

Rails 8 is all about simplicity, productivity, and independence. It removes external dependencies, makes deployment first-class, and improves the developer experience.

If you’re starting a new project, Rails 8.0.2.1 (latest stable) is the version you should be using. And if you’re on Rails 7, now’s the perfect time to plan an upgrade.

💡 In short: Rails 8 makes it easier than ever to go from idea → production with minimal friction.

Thursday, July 6, 2017

Intro to Docker for Developers: How to Run your Rails App on Docker

Docker in a Nutshell First of all what is Docker? Let’s chew on the Wikipedia definition to start: 

“Docker is an open-source project that automates the deployment of applications inside software containers, by providing an additional layer of abstraction and automation of operating-system-level virtualization on Linux.[2] Docker uses resource isolation features of the Linux kernel such ascgroups and kernel namespaces to allow independent "containers" to run within a single Linux instance, avoiding the overhead of starting and maintaining virtual machines.[3]”

From a developer perspective Docker promises us the opportunity to forget about the “it works in my local environment but not in production” problem as well as the “it works on my Ubuntu machine but not on my buddy’s Mac three feet away” scenario. 

Now, with the magic of a definition file, it is super easy to port an app between environments: from local to lab, and later to production. Docker is incredibly fast and thanks to the use of some linux kernel features like namespaces, we have isolation for filesystem, networks and processes. 


This consistency is an incredible opportunity for developers, but it’s an especially big win for our users: with Docker we can reduce highly disruptive “environmental issues” to almost zero percent. 

Did I just say the word disruptive? Oh right, container revolution, blah blah. :)

Step #1: Prepare Your Infrastructure / Server Environment



Let’s “dockerize” a basic Rails app.This is what the app looks like. It was created using “Rails new Rails-App” (if you don’t have Rails you can just follow the installation instructions here) 

First, you need to have Docker running. To do so, you can just check the docker documentation, which is really quite easy to follow. Choose your platform, follow the instructions, and voilà! 

Once installed, check that the Docker daemon is running properly by typing:

$ docker -v

Docker version 1.7.0, build 0baf609 (this will probably change based on the installation type/platform you have chosen)

Step #2: Build Your Image


Next up we need to build our Rails image. Docker uses a definition file to describe what the environment will contain. Usually it’s named Dockerfile (you can use a different name also), so for simplicity let’s create a file in our app directory called “Dockerfile” and add a few lines in there (gist):

# Base image FROM ruby:latest 
ENV HOME /home/rails/webapp 

# Install PGsql dependencies and js engine 
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs 

WORKDIR $HOME 

# Install gems 
ADD Gemfile* $HOME/ 
RUN bundle install 

# Add the app code 
ADD . $HOME 

# Default command 
CMD ["rails", "server", "--binding", "0.0.0.0”]

Okay...so what’s a “Docker image” for real? 

An image is a read-only template that Docker uses to run your code through a container. It contains a complete environment definition: it has the OS binaries, libraries, dependencies and all the applications that you need to run your code or application. All the magic is stuffed into it, so pay attention! 

Images contain layers (I won’t explain much about them here, since it’s a big topic that requires its own blog post). Every instruction creates a new layer in the filesystem. And thanks to the use of a union filesystem, those layers are “combined” into a single filesystem. Neat and tidy. 

An image can be built and pushed into a registry, like Docker Hub, or Quay.io (or even a custom one), just like you would do with GitHub. You can even have public or private repositories, so others can leverage your image / template, or you can re-use for other purposes.

Digging into your Dockerfile


To help us understand how this all works, let’s examine our freshly baked Rails Dockerfile.

FROM ruby:latest - This is the first instruction you have to have in your Dockerfile, with this instruction we are defining the base image. In our case, it will use this base image https://registry.hub.docker.com/u/library/ruby/, which actually has an interesting hierarchy:

  • Ruby is based on buildpack-deps:jessie which is based on buildpack-deps:jessie-scm which is based on buildpack-deps:jessie-curl, which is finally (!) based on debian:jessie.

  • As you can see, between images there exist some kind of “inheritance” concept where you can “extend” your images from others. It’s a great thing since you can build your environments based on trusted/stable (if you find them! and still be careful) images.

ENV HOME /home/rails/webapp - Just defining an environment variable.
RUN apt-get update -qq && apt-get install -y build-essential nodejs

  • The RUN instruction executes a command in the docker container. So the “apt-get …” command will update the OS packages list and will install some libraries among nodejs.
WORKDIR $HOME - The WORKDIR instruction sets the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD instructions.
ADD Gemfile* $HOME
/RUN bundle install

  • Copy all the gem files definitions into the filesystem in the container and execute the command to install the gems. (I’ll explain why I’m doing this, in the next “Using Cache in Docker” post :) )

ADD . $HOME - Copy all the website files into the container.

CMD ["rails", "server", "--binding", "0.0.0.0"] - Specify the default command for when the container runs.

Step #3 - Build and Run Your Web App


Now that we have a better idea of our Dockerfile, let’s get our hands dirty! We need to build and run the web app:

$ docker build -t ruby-app .

Since we don’t have a Ruby image downloaded yet, it will pull the latest from Docker Hub and then run all the instructions from the Dockerfile. You should end up with something like this:

Later we can check the image using:

$ docker images

Let’s create a container and run the app.

$ docker run -d -p 3000:3000 rails-app

The command above will create a docker container using the “ruby-app” image you created in Step #2. The “-d” flag tells docker daemon to run this container in “daemon mode”.


Remember our CMD instruction in the Dockerfile? Well that is what’s running in the container “rails server --binding 0.0.0.0”

You can just open your browser at: http://localhost:3000 or you can get the container IP:

docker inspect 8f4fec2497f5 | grep IPAddress

(you can also run docker inspect --format '{{.NetworkSettings.IPAddress}}' 8f4fec2497f5 )

In my case it is: "IPAddress": "172.17.0.2"

So, just open the browser and point it to http://172.17.0.2:3000 and you will see the rails app running :)

One last interesting command about the run command we used is the -p flag.

docker run -d -p 3000:3000 ruby-app

When using the -p flag docker let us choose a port binding between the host and the container. Without this flag we could get into the rails app from outside the container. We could even choose a different port like: 

docker run -d -p 5000:3000 ruby-app

Or let docker choose a random port like
docker run -d -p 3000 ruby-app
To see what port docker has chosen, we can run “docker ps”

Or let docker choose a random port like docker run -d -p 3000 ruby-app To see what port docker has chosen, we can run “docker ps”


And in the port column you will see that the assigned port is 32769.
Also you could do:

$docker port 284bb5e37f44
Result: 3000/tcp -> 0.0.0.0:32769

And in the port column you will see that the assigned port is 32769. Also you could do: $docker port 284bb5e37f44 Result: 3000/tcp -> 0.0.0.0:32769


Thursday, February 7, 2013

Plugin to upload video to YouTube directly from your site


Source code and sample available at: https://github.com/prabgupt/youtube_video_upload_plugin
Usage: Please note that sample is available for RoR3 but it can be easily converted for any underlying platform. Refer README in git repo above to know how to run it in RoR3. To see how to tweak code to use it for any other platform, keep reading the post.
Purpose of this Utility: It will upload end user’s video directly to youtube and is easily integratable within your website.
Few Advantage:
  • No need to have storage on server machine as you can now dump/use all videos directly to/from youtube.
  • In case you have youtube channel, can directly organize video uploaded through your site to youtube channel.
  • NO need for end user to login to youtube first to upload video through your site.
Flow to upload video on YouTube
  1. Website requests  token and upload URL from youtube for every new video request. This is needed to avoid having end user logging into his/her YouTube account.
  2. Post your video to URL received in step#1 with parameter ‘nexturl’. ‘nexturl’ is callback url to be called by YouTube with status and video_id once upload operation is completed with failure or success. You need to send token received in step#1 too along with.
  3. Youtube invokes ‘nexturl’ with status and video_id, if upload is successful. Process/store this video_id as this will be key from now onwards based on which you can perform operations on this video directly in YouTube.
Source code contains of following things that you need to know:
youtubeUtilAPIs.py- Python script that uses Google Data Python client library.  This script contains few methods performing certain operation on youtube.
Usage: py [-t <comma separated title and description>] [-u <video_id>] [-s <video_id>] [-d <video_id>]
-t => to get token and url. Input required is comma separated video title and video description
-u => to get youtube URL for that video. Input required is video_id
-s => to get upload status of the video. Input required is video_id
-d => to delete video from youtube. Input required is video_id
Prerequisite:
    • Please refer Getting Started guide. In nutshell, you need to install Python and then google Data Library as specified in the link.
    • Replace following senstive data inside python script; like developer key, password, etc. with that of yours. You will need to sign in for YouTube developer key. Once signed in, register you product and get values for below attributes. ‘source’ and ‘client_id’   will be the name of the product you registered before.
yt_service.developer_key = ‘xxxxxxx’
yt_service.client_id = ‘xxxxxxx’
yt_service.email = ‘xxxxxxx’
yt_service.password = ‘xxxxxxxx’
yt_service.source = ‘xxxxxxxxxx’
  • Since above utility contains some sensitive data, hence for security reasons you would need to introduce a server side handler that will execute above script on client request and can send the required details back to client. In our case, we have introduced method ‘uploadToken’ inside multimedia controller which execute python script and returns back token and url needed to upload video on youtube.
1234567891011
def uploadToken
cmd = Rails.root.to_s + '/public/scripts/youtubeUtilAPIs.py'
title = "Test Video"
description = "Test Video description"
resp = `#{cmd} -t "#{title},#{description}"`
resp = resp.split('::')
response = (resp.length == 2) ? {:uploadUrl => resp[0], :token => resp[1]} : ""
respond_to do |format|
format.js {render :js => response.to_json}
end
end
  • Below is the HTML code you’ll plug into your website to let end user select the video and upload it to youtube. Code just contains a form to have end use select the video and has action, token value blank at render time. If you have already noticed, there is async ajax request present at end of code which fetches upload URL and token from server at time page is loading and populate it inside form once ajax request gets completed.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
<div id="upload_video">
<div class="field">
<form action='' id="youtube_video_upload" method="post" enctype="multipart/form-data">
<input name="file" type="file" class="multimedia_file"/>
<div class="errMsg" style="display:none;color:red">
You need to specify a file.
</div>
<div class="errMsg2" style="display:none;color:red">
Video cannot be uploaded this time. Please try again after sometime.
</div>
<input class= "token" name="token" type="hidden" value=""/>
<input value="Upload Video File" class="upload_button" type="submit" />
</form>
</div><br/>
</div>
<script>
$(document).ready(function(){
$(' #youtube_video_upload .multimedia_file').click(function(){
$(this).siblings('.errMsg').css("display", "none");
$(this).children('.errMsg2').css("display", "none");
});
$('#youtube_video_upload').submit(function(){
if ($(this).children('.multimedia_file').val() == null || $(this).children('.multimedia_file').val() == ""){
$(this).children('.errMsg').css("display", "");
return false;
}else if ($(this).children('.token').val() == null || $(this).children('.token').val() == ""){
$(this).children('.errMsg2').css("display", "");
return false;
}
$('#youtube_video_upload').children('.upload_button').attr('disabled', 'true');
});
$('#video_link').click(function(){
$("#add_link").css("display", "none");
$("#upload_video").css("display","");
});
$('#youtube_link').click(function(){
$("#upload_video").css("display","none");
$("#add_link").css("display", "");
$('.errMsg').css("display", "none");
$('.errMsg2').css("display", "none");
});
// asyn ajax request to fetch upload URL and token from youtube
$.get('<%= url_for(:action => "uploadToken", :controller => "multimedias", :only_path => false)%>',function(data){
if(data != ""){
$('#youtube_video_upload').attr('action', data.uploadUrl + '?nexturl=<%= url_for(:action => "new", :controller => "multimedias", :only_path => false)%>');
$('#youtube_video_upload').children('.token').val(data.token);
$('#youtube_video_upload').children('.errMsg2').css("display", "none");
}else{
}
}, "json");
});
</script>

FastAPI: The Modern Python Web Framework

  Introduction to FastAPI: The Modern Python Web Framework The world of web frameworks has always been competitive — from Django and Flask ...