R Docker: How to Run Your R Scripts in a Docker Container

Reading time:
time
min
By:
Dario Radečić
December 21, 2023

So, you've written this amazing R script, but your coworkers can't run it? It works on your machine, so they have to be doing something wrong, right? <b>Wrong</b>. It's all about isolating and managing R environments. And that's where R Docker comes in. Think of Docker as a program that allows you to run multiple operating systems (containers) on your machine, while also allowing you to share the blueprints for recreating the mentioned operating system. It's like a virtual machine, minus everything you don't need. Today you'll learn the basics of R Docker, why it's important in R programming language, and how to Dockerize your first R script. <blockquote>Is your R Shiny app slow? <a href="https://appsilon.com/scaling-and-infrastructure-why-is-my-shiny-app-slow/" target="_blank" rel="noopener">You might want to consider scaling it at the infrastructure level</a>.</blockquote> <h3>Table of Contents</h3><ul><li><strong><a href="#what-is-docker">What is Docker and Why is it Important in R Programming</a></strong></li><li><strong><a href="#install-docker">How to Install Docker</a></strong></li><li><strong><a href="#dockerize-r">How to Use R Docker to Run R Script in a Container</a></strong></li><li><strong><a href="#conclusion">Summing up R Docker</a></strong></li></ul> <hr /> <h2 id="what-is-docker">What is Docker and Why is it Important in R Programming</h2> Think of Docker as a platform for developing, shipping, and running applications in isolated environments called "containers". These are lightweight units that package applications and all of their dependencies (think system dependencies and R packages). In the context of R programming, Docker addresses the problem of <b>environment consistency</b>. Needless to say, you want your code running consistently across different environments, from your laptop to production servers. Docker containers can help here, as they encapsulate the environment, so you can rest assured the code and dependencies won't change as you change the development environment. Docker is also praised for the <b>reproducibility</b> aspect. They allow you not only to specify which R dependencies are needed but also specific versions of R itself and other system dependencies. This will ensure you don't run into any issues when sharing your code with others. If it works on your laptop (in a Docker container, of course), it will work with other developers as well. The previous two points also give you the idea that Docker containers benefit from <b>portability</b>. You can create a container on your laptop and then run it on any platform that supports Docker, such as your other laptop, a cloud server, or even a home NAS system. And, of course, Docker makes <b>scaling</b> R applications a breeze. You can create multiple containers with the same configuration and scale your application horizontally as the workload increases. There are other benefits of using R Docker, but we think these few are enough to convince you Docker is the correct way of creating and scaling R scripts and applications. But how can you <b>install Docker?</b> That's what we'll cover next. <h2 id="install-docker">How to Install Docker</h2> If you're working on a PC/laptop, we recommend installing <a href="https://www.docker.com/products/docker-desktop/" target="_blank" rel="noopener">Docker Desktop</a>: <img class="size-full wp-image-22545" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65aff992cadba2bec8c60cc1_Image-1-Docker-homepage-scaled.webp" alt="Image 1 - Docker homepage" width="2560" height="1257" /> Image 1 - Docker homepage Put simply, it's a single <code>.exe</code> file for Windows, <code>.dmg</code> file for Mac, and <code>.deb</code>/<code>.rpm</code> file for Linux you can download at the URL supplied earlier. Just download the file and install it with a double click (Windows and Mac), or by running the following shell commands on Linux: <pre><code class="language-bash">sudo apt-get update sudo apt-get install ./docker-desktop-&lt;version&gt;-&lt;arch&gt;.deb</code></pre> Installation on Mac and Windows is easier, so we feel there's no need to discuss it further. Linux might require some additional tweaking, so feel free to go over the <a href="https://docs.docker.com/desktop/install/linux-install/" target="_blank" rel="noopener">official installation instructions</a>. <h2 id="dockerize-r">How to Use R Docker to Run R Script in a Container</h2> This section will walk you through the process of writing a simple R script, and then automating its execution in a Docker container. <h3>Writing and Testing the R Script</h3> This is likely your first introduction to Docker, so let's not overcomplicate things where we don't have to. We'll keep the R portion fairly simple. Create a new R script file (ours is named <code>script.R</code>). It uses two external dependencies - <code>dplyr</code> and <code>gapminder</code> to load and summarize a dataset. To be more precise, the script gives us insights into average life expectancy and average GDP per capita for all European countries in 2007. The results are saved to a CSV file. Note the <b>save path</b>, this one is important for later: <pre><code class="language-r">library(dplyr) library(gapminder) <br># Statistics of Europe countries for 2007 eu_stats &lt;- gapminder %&gt;%  filter(    continent == "Europe",    year == 2007  ) %&gt;%  group_by(country) %&gt;%  summarise(    AvgLifeExp = mean(lifeExp),    AvgGdpPercap = mean(gdpPercap)  ) <br># Save the file as CSV write.csv(eu_stats, "home/r-environment/eu_stats.csv", row.names = FALSE)</code></pre> This is what you'll see once you run the script locally: <img class="size-full wp-image-22547" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65aff99450ab0e1953e75509_Image-2-The-resulting-CSV-file.webp" alt=" Image 2 - The resulting CSV file" width="2004" height="1744" /> Image 2 - The resulting CSV file Nothing fancy and nothing to write home about - but does the job. Running the script results in an output CSV file, which will be a verification to make sure things work properly when executed in a Docker container. Let's see how to approach this next. <h3>Writing the Dockerfile</h3> We'll leverage a <code>Dockerfile</code> to create our container for the R script. Create a new file in the same directory where your R script is, and name it <code>Dockerfile</code> - all one word, no extensions. This type of file uses a specific syntax to create a Docker container. Let's go over a couple of common keywords: <ul><li><code>FROM</code>: A command every <code>Dockerfile</code> starts with. It's used to describe what base image are we building our image from. For example, <code>rocker/r-ver</code> is built on Ubuntu LTS and installs a fixed version of R from source. You can specify the exact version of R by putting <code>:&lt;r-version&gt;</code> after <code>rocker/r-ver</code>. Feel free to explore the <a href="https://rocker-project.org/images/versioned/r-ver" target="_blank" rel="noopener">details of this image</a> further on your own.</li><li><code>RUN</code>: This command mimics command line commands, and we can use them to do things such as directory creation, dependency installation, and much more.</li><li><code>COPY</code>: A command used to copy the contents of your local machine to the container. Use the syntax <code>COPY &lt;path-tolocal-file&gt; &lt;path-in-container&gt;</code>, or replace <code>&lt;path-tolocal-file&gt;</code> with <code>.</code> to copy everything from the folder.</li><li><code>CMD</code>: This is the command that will be used every time you launch the container. For example, we can use it to run our R script.</li></ul> There are more keywords you can use, but these will be enough for today. Here are the <code>Dockerfile</code> contents, so feel free to copy-paste them: <pre><code class="language-dockerfile"># Base R image FROM rocker/r-ver <br># Make a directory in the container RUN mkdir /home/r-environment <br># Install R dependencies RUN R -e "install.packages(c('dplyr', 'gapminder'))" <br># Copy our R script to the container COPY script.R /home/r-environment/script.R <br># Run the R script CMD R -e "source('/home/r-environment/script.R')"</code></pre> In a nutshell, we're using the latest version of the <code>r-ver</code> image, creating a directory, installing R dependencies, copying the local script to the container, and running it. That's it! The syntax takes some time to get used to but is simple and readable. You'll have more trouble writing than reading <code>Dockerfile</code> if you're just starting out. <h3>Creating a Docker Container and Running the Script</h3> We're only two shell commands away from running our R script in a Docker container. The first shell command is used to build a container per your <code>Dockerfile</code> instructions. Open up a new Terminal window and navigate to where your code is located. Then, run the following command: <pre><code class="language-bash">docker build -t r-docker-demo .</code></pre> This will build a new image named <code>r-docker-demo</code>: <img class="size-full wp-image-22549" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65aff9967d3cd771dcf4b7d4_Image-3-Building-a-container-from-Dockerfile.webp" alt="Image 3 - Building a container from Dockerfile" width="2490" height="1342" /> Image 3 - Building a container from Dockerfile You'll see this message when the build finishes: <img class="size-full wp-image-22551" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65aff9979e721643db8680f9_Image-4-Container-build-finished.webp" alt="Image 4 - Container build finished" width="2490" height="1342" /> Image 4 - Container build finished And now, we can finally create a container from the newly created image and run it: <pre><code class="language-bash">docker run r-docker-demo</code></pre> This is the shell output you'll see: <img class="size-full wp-image-22553" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65aff999c85999cff0c4b8a5_Image-5-Launching-a-Docker-container.webp" alt="Image 5 - Launching a Docker container" width="2490" height="1922" /> Image 5 - Launching a Docker container You can see the runtime logs by opening Docker Desktop and monitoring container runs. You'll see the identical output as previously shown in Terminal: <img class="size-full wp-image-22555" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65aff9996f6804502a4b22d1_Image-6-Docker-container-log-output.webp" alt="Image 6 - Docker container log output" width="2540" height="1440" /> Image 6 - Docker container log output The <i>Files</i> tab is where things get interesting. Long story short, this tab provides you with an overview of the system file structure. If our R script finished successfully, we should see an <code>eu-stats.csv</code> file stored in <code>home/r-environment</code>: <img class="size-full wp-image-22557" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65aff99bc0c2c32303c54f7d_Image-7-Docker-container-system-files.webp" alt="Image 7 - Docker container system files" width="2540" height="1440" /> Image 7 - Docker container system files You can download this file locally to your system: <img class="size-full wp-image-22559" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65aff99bd2b14c5b71f8dea6_Image-8-Saving-the-container-file-locally.webp" alt="Image 8 - Saving the container file locally" width="860" height="390" /> Image 8 - Saving the container file locally And here's what it contains: <img class="size-full wp-image-22561" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65aff99db5ac9420fcd5747b_Image-9-Resulting-CSV-file-contents.webp" alt="Image 9 - Resulting CSV file contents" width="2218" height="1680" /> Image 9 - Resulting CSV file contents To conclude, we've successfully written and Dockerized a simple R script. You can share the script and Dockerfile with your colleagues, and they'll have no trouble reproducing your results. That's the whole point, after all. <hr /> <h2 id="conclusion">Summing up R Docker</h2> And there you have it - your first Dockerized R script. It takes some time to get used to writing <code>Dockerfile</code>s, but it's nothing you can't wrap your head around if you already understand more complex topics, such as programming. Today you've only Dockerized one R script, so the next step is to explore how to do the same (and more) with an entire R Shiny application. Make sure to stay tuned to <a href="https://appsilon.com/blog" target="_blank" rel="noopener">Appsilon Blog</a> if you want to learn more about deployment. <i>What's your preferred way of deploying and sharing R scripts and Shiny applications?</i> Let us know in the comment section below. <blockquote>Is your R Shiny application slow? <a href="https://appsilon.com/shiny-worker-package/" target="_blank" rel="noopener">Speed it up by offloading heavy calculations with shiny.worker</a>.</blockquote>

Have questions or insights?

Engage with experts, share ideas and take your data journey to the next level!

Is Your Software GxP Compliant?

Download a checklist designed for clinical managers in data departments to make sure that software meets requirements for FDA and EMA submissions.
Explore Possibilities

Share Your Data Goals with Us

From advanced analytics to platform development and pharma consulting, we craft solutions tailored to your needs.

Talk to our Experts
r
infrastructure
docker
tutorials