Creating a JRuby fat jar with bundler inside a docker container
In this blog post I'll demonstrate how to create a JRuby fat jar that will include all gem dependencies inside of it. The dependencies themselves will be handled by Bundler.
1. Let's create a CentOS container to run our tests in:
docker run -dt --name=centos --hostname=centos --net=host centos:7 bash
2. Enter the container:
docker exec -it centos bash
3. Install the OpenJDK:
yum -y install java-1.8.0-openjdk-headless
4. Download Jruby, untar it, move it under /opt and symlink it:
cd /tmp
curl -LO https://repo1.maven.org/maven2/org/jruby/jruby-dist/9.2.11.1/jruby-dist-9.2.11.1-bin.tar.gz
tar -xzf jruby*.tar.gz -C /opt/
ln -s /opt/jruby-* /opt/jruby
5. Add jruby to your path and test it:
export PATH=/opt/jruby/bin:$PATH
jruby -v
The output should look like this:
jruby 9.2.11.1 (2.5.7) 2020-03-25 b1f55b1a40 OpenJDK 64-Bit Server VM 25.252-b09 on 1.8.0_252-b09 +jit [linux-x86_64]
6. Write a one-line Ruby script to test that everything works:
echo 'puts "hello world"' > ~/ruby_hello_world.rb
7. Run the script using JRuby:
jruby ~/ruby_hello_world.rb
8. Now we're going to install the warbler gem which allows us to build all-inclusive jar files (fat Jar):
jruby -S gem install warbler
9. Warbler needs the script to be in a directory with a subdirectory called bin. So let's create those next:
mkdir ~/ruby_hello_world
mkdir ~/ruby_hello_world/bin
10. Copy our ruby_hello_world.rb script in the bin subdirectory:
cp ~/ruby_hello_world.rb ~/ruby_hello_world/bin
11. Now go into that directory and build the jar:
cd ~/ruby_hello_world
warble jar
12. Run the newly created jar - Warbler uses the the name of the directory as the filename.
java -jar ruby_hello_world.jar
13. Now let's try with a new script that will be using Bundler as well - like before let's create the directories Warbler expects:
mkdir ~/ruby_bundler
mkdir ~/ruby_bundler/bin
14. Install the Bundler gem:
jruby -S gem install bundler
15. Add a Gemfile:
cat << EOF > ~/ruby_bundler/Gemfile
source 'https://rubygems.org'
gem 'randomstring'
gem 'colorize'
EOF
16. Go to that directory and install the bundled gems first:
cd ~/ruby_bundler
jruby -S bundle install
17. Add a script:
cat << EOF > ~/ruby_bundler/bin/a_script_that_uses_bundler
require 'rubygems'
require 'bundler/setup'
require 'colorize'
require 'randomstring'
puts "Hello, I'm using the colorize gem!".colorize(:red)
puts "I'll print some random text for you using the randomstring gem:"
(1..5).each do |n|
puts Randomstring.generate(10)
end
EOF
18. Try running the script:
jruby bin/a_script_that_uses_bundler
The output should look something like this:
Hello, I'm using the colorize gem!
I'll print some random text for you using the randomstring gem:
7J4x7UTJJU
ngzGaxAqdi
qnN8oSdPem
EOLuYv8WpI
rAYEGViUKa
19. Now let's create a fat jar:
cd ~/ruby_bundler
warble jar
20. And let's test that this works as well:
java -jar ~/ruby_bundler/ruby_bundler.jar
Expected output:
Hello, I'm using the colorize gem!
I'll print some random text for you too using the randomstring gem:
RIdkALvbBI
jB5KSSl18Z
BpmoJAPIOX
Sb2YjlqehA
kDphaHAt0x
21. Exit the docker container:
exit
22. On the docker host, copy the jar out:
docker cp centos:/root/ruby_bundler/ruby_bundler.jar ~/
23. Create an Oracle Linux container (I'm using a different Linux distro to demonstrate that the jar still works) :
docker run -dt --name oraclelinux --hostname oraclelinux --net host oraclelinux:7-slim bash
24. Copy the jar from the host to the Oracle Linux container:
docker cp ~/ruby_bundler.jar oraclelinux:/root/
25. Enter the Oracle Linux container:
docker exec -it oraclelinux bash
26. Install the OpenJDK, but this time we won't install Jruby:
yum -y install java-1.8.0-openjdk-headless
27. Test the jar and make sure it works - as you have noticed, we didn't install JRuby or Bundler etc - we're just using the jar we created:
java -jar /root/ruby_bundler.jar
Expected output:
Hello, I'm using the colorize gem!
I'll print some random text for you too using the randomstring gem:
XRtK2K6Ozl
T07ATaUqsg
LxpBvA2C6Q
BZgfOvbxdG
21v2Sh0Szj