
December 24, 2025
Ruby 4 introduces one of the most important runtime features in the history of the language: Ruby::BOX. It allows Ruby to execute multiple isolated class worlds inside the same process, finally making it possible to load conflicting libraries, plugins, and user code safely.
In this guide we will build a lightweight Alpine-based Docker image running Ruby 4.0.0-preview3 and demonstrate how Ruby::BOX enables true code isolation.
What is Ruby::BOX?

Ruby::BOX creates independent class universes inside a single Ruby VM.
Each Box has its own:
- classes
- modules
- constants
- $LOAD_PATH
- require state
But they all share:
- memory
- threads
- garbage collector
- the same Ruby process
This means two Boxes can load two different implementations of the same class name without collisions.
That was impossible in Ruby before 4.0.
Advertise on RubyStackNews
RubyStackNews is a niche publication read by Ruby and Rails developers worldwide. Our audience includes senior engineers, tech leads, and decision-makers from the US, Europe, and Asia.
Sponsorship Options
Your brand featured inside a technical article (clearly marked as sponsored).
Highlighted sponsor section embedded within an article.
Logo + link displayed site-wide in the sidebar.
- Highly targeted Ruby / Rails audience
- Organic traffic from search and developer communities
- No ad networks — direct sponsorships only
Interested in sponsoring RubyStackNews?
Contact via WhatsAppWhy this matters
Historically, Ruby has one global class space:
class User; end
Every gem, framework, and application defines into the same world. If two libraries define User, one overwrites the other.
With Ruby::BOX, each piece of code can live in its own isolated universe.
This unlocks:
- plugin systems
- multi-tenant Ruby runtimes
- marketplaces of Ruby extensions
- safe execution of third-party code
- loading multiple versions of the same library
Ruby 4 in Docker (Alpine)

We use Alpine to keep the image small and compile Ruby 4 from source.
FROM alpine:3.20
RUN apk add --no-cache \
build-base \
linux-headers \
bison \
openssl-dev \
yaml-dev \
readline-dev \
zlib-dev \
ncurses-dev \
libffi-dev \
gdbm-dev \
db-dev \
wget \
ca-certificates \
tar \
autoconf
WORKDIR /usr/src
RUN wget https://cache.ruby-lang.org/pub/ruby/4.0/ruby-4.0.0-preview3.tar.gz \
&& tar -xzf ruby-4.0.0-preview3.tar.gz
WORKDIR /usr/src/ruby-4.0.0-preview3
RUN ./configure \
--disable-install-doc \
--enable-shared \
&& make -j$(nproc) \
&& make install
WORKDIR /app
Enabling Ruby::BOX
Ruby::BOX is activated through an environment variable.
In Docker Compose:
version: "3.9"
services:
ruby4:
build: .
container_name: ruby4_preview
volumes:
- .:/app
environment:
RUBY_BOX: 1
This tells Ruby 4 to run with Box support enabled.
Two libraries, same name, different behavior
We will create two libraries that define the same class but behave differently.
lib/v1/logger.rb
class Logger
def format(msg)
"[V1] #{msg.upcase}"
end
end
lib/v2/logger.rb
class Logger
def format(msg)
"[V2] #{msg.upcase}"
end
end
Both define Logger, but their behavior is different.
Running them inside two Boxes
b1 = Ruby::Box.new
b1.eval <<~R
$LOAD_PATH.unshift "/app/lib/v1"
require "logger"
class Foo
def hello
l = Logger.new
l.format("Hello Ruby")
end
end
R
b2 = Ruby::Box.new
b2.eval <<~R
$LOAD_PATH.unshift "/app/lib/v2"
require "logger"
class Foo
def hello
l = Logger.new
l.format("Hello Ruby")
end
end
R
puts b1::Foo.new.hello
puts b2::Foo.new.hello
Run it:
docker compose run --rm ruby4 ruby main.rb
Output:
[V1] HELLO RUBY
[V2] HELLO RUBY
Even though both define Logger and Foo, they live in completely separate worlds.
What just happened?
Inside a single Ruby process:
Ruby VM
├── Box 1 → Logger (v1), Foo
├── Box 2 → Logger (v2), Foo
└── Global
The classes do not collide. They do not overwrite each other. They do not even know the other exists.
This is a true class loader inside Ruby.
Why this changes Ruby forever
With Ruby::BOX, Ruby becomes a platform, not just a language.
You can now build:
- plugin marketplaces
- Rails engines running side-by-side
- SaaS multi-tenant runtimes
- safe execution of user-supplied Ruby
- isolated extensions for frameworks
All inside one Ruby process.
Ruby has crossed the boundary into modular runtime architecture.
🚀 Ruby 4 Docker Sandbox — Ruby::Box
This repository contains a lightweight Alpine + Docker environment for testing Ruby 4.0 and the new Ruby::Box runtime feature. It demonstrates how multiple isolated class worlds can run inside a single Ruby process.
Ruby::Box enables plugin systems, safe user code execution, and side-by-side loading of conflicting libraries — something Ruby has never been able to do before.
Download the Ruby 4 Docker SandboxIncludes Dockerfile, docker-compose.yml, and a working Ruby::Box example.
