GraalVM and ChromeDriver in a Docker image for Render.com

This should work on Heroku or in any Docker-based deployment as well.

Adding Chrome and ChromeDriver into a GraalVM Docker image isn't as straightforward as I thought. The main complication originates from the fact that GraalVM is lean. There are 2 problems from being lean: (1) microdnf as the main package manager and (2) unwritable home directory, and Chrome needs a writable home directory.

I didn't even know what microdnf (or dnf) was before this. I was initially surprised that I couldn't find a package manager at all until I randomly landed on this GraalVM Community Edition page that mentioned microdnf here.

The first problem is microdnf doesn't support installing Chrome nor ChromeDriver. I was researching how to install those 2 programs manually. While installing ChromeDriver is simple, installing Chrome manually looks extremely complex.

Eventually, I've found a feasible path where I'd install yum first with microdnf install yum and then use yum to install Chrome (through a Chrome rpm). That works out pretty well.

The second problem is that Chrome wouldn't start at all. After hours of debugging, I've figured it out that the home directory of the user daemon (which is apparently the user that we use inside the docker image) is set to /sbin and isn't writable. Chrome and Selenium seems to utilise the home directory for caching and myriad of other things.

After solving these 2 problems, the headless Chrome, ChromeDriver, and Play Framework all work together like a charm.

Here's the Dockerfile that sets everything up:

 FROM container-registry.oracle.com/graalvm/jdk:21
 
 RUN microdnf install yum

 # Install Chrome
 RUN yum install wget unzip
 RUN wget https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm
 RUN yum install google-chrome-stable_current_x86_64.rpm

 # Install ChromeDriver
 RUN wget https://storage.googleapis.com/chrome-for-testing-public/131.0.6778.85/linux64/chromedriver-linux64.zip
 RUN unzip chromedriver-linux64.zip
 RUN chmod 755 chromedriver-linux64/chromedriver
 RUN mv chromedriver-linux64/chromedriver /usr/local/bin/chromedriver
 
 # Change the home directory to /home/daemon.
 RUN mkdir -p /home/daemon
 RUN usermod -d /home/daemon daemon
 RUN chown daemon:daemon /home/daemon

Edit: This person on Reddit shares this cool Docker trick that we'll apply to our Dockerfile.

Subscribe to tanin

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe