Search code examples
rdockercontainers

Building a Docker Image a little more quickly


I plan on using a service to receive and grade student code submissions for a class I'll be teaching next semester.

For each assignment (there are many) a shell script runs to build a Docker image. I upload a zip file to the website, and among all the compressed files, there is this one:

#!/usr/bin/env bash

# these lines install R on the  virtual machine
apt-get install -y libxml2-dev libcurl4-openssl-dev libssl-dev
apt-get install -y r-base

# these lines install the packages that is needed both
# 1. the student code 
# 2. the autograding code

# Note that 
# a. devtools is for install_github This is temporary and will be changed once the updates to gradeR have made it to CRAN.
Rscript -e "install.packages('devtools')" 
Rscript -e "library(devtools); install_github('tbrown122387/gradeR')"

# These are packages that many students in the class will use
Rscript -e "install.packages('tidyverse')" 
Rscript -e "install.packages('stringr')" 

The problem though is that this takes about 20 minutes. How do I speed this up? I'm totally new to Docker containers.


Solution

  • First, I'd suggest building a base image containing all of the tools and packages that you think you'll need. There's no need to be picky, because you only need to do this once. That's kind of the whole point of Docker -- portability and reuse.

    FROM ubuntu:bionic
    
    RUN apt-get update && apt-get install -y libxml2-dev libcurl4-openssl-dev libssl-dev r-base
    
    RUN Rscript -e "install.packages('tidyverse')" 
    RUN Rscript -e "install.packages('stringr')" 
    ...
    

    Build that image and tag it as grader:1.0.0 or whatever.

    Then, when it's time to grade, just mount the assignments and grading code using the -v, --volume option to docker run. You don't need to alter the container to make files accessible within it.

    docker run \
      --rm \
      -it \
      -v /path/to/assignments:/data/assignments \
      -v /path/to/autograder:/data/autograder \
      grader:1.0.0 \
      /bin/bash
    

    If at some point you need to add some packages, you can rebuild it by modifying the original Dockerfile or extend it by using it as the base of your next image:

    FROM grader:1.0.0
    
    RUN apt-get update && apt-get install -y the-package-i-forgot
    

    Build it, tag it.