Lampros - Weird Bricks

Creating a JRuby fat jar with bundler inside a docker container

24 June, 2020 | Jruby

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