The common course container makes it possible for multiple courses to reusue the same container. It uses ccc
and direnv
to automatically download packages, set up environment variables in way that avoids conflicts between different courses.
Why have a common container?
There has been a significant shift in the CS department. More and more students prefer developing locally rather than on department machines. As a result, many courses now provide their own local development solutions, requiring students to use containers (i.e. Docker and Podman) to develop, build, and compile their code. This provides both the ergonomics associated with developing locally, and also the practicality of having a standard development environment.
However, containers across the department are not unified. Specifically, courses tend to require a different image and container for their course, despite the fact that the majority runs on the same operating system with very similar packages.
This presents several problems:
- Courses which use containers have long “setting up” assignments. This involves, but is not limited to: installing docker/podman, building containers, setting up XQuartz, and connecting with an editor-of-choice. While instructions only differ slightly, they nevertheless must be repeated for each course.
- Students run into technical limitations with running multiple containers at the same time. Docker and Podman cannot be attached at the same time in VSCode. Containers that map to the same port cannot be run at the same time. This makes it inconvenient for students to switch between working on two different courses with different containers.
- Containers take a lot of storage on students’ computers. Of the 44 active undergraduate CS courses surveyed in Summer 2025, one-fourth (11 courses) required containers. Because each course has different images and containers, they do not benefit from shared resources, despite the fact that courses have very similar operating systems and packages.
- Students often need additional support with containers. Because containers are run on many different operating systems and environments, container issues can be complex and time-consuming. TA bandwidth is already stretched thin. While they are trained in course material, they can use more support with gritty container issues. Having a standardized container enables broader support from SPOCs, Sunlab Consultants, and TStaff.
Usage
Users can install the common course container here.
To start the container, run the command ./run-podman
. This will build the image and start the container. Note that the folder courses
will be mounted inside of the container, which means that any changes to that folder inside of the container will be reflected outside of the container. Users can exit out of the running container with the command exit
and reattach by running ./run-podman
again.
Inside of the container, users can manage courses with the ccc
tool. Run ccc install <course>
to install a specific course in the folder courses
.
Porting to the common container
Courses often already have custom containerfiles and bash scripts. We have identified that these scripts accomplish three main tasks:
- Downloading packages
- Loading environment variables
- Defining symlinks
Replicating this behavior in the common container is quick and simple. First, create a course repository. This directory will serve as an isolated environment for the course. At the root of the directory, create a setup.sh file, a .envrc dotfile, and a bin/ directory.
- setup.sh is used to download packages from the apt registry. The
ccc
tool looks for this file when it is setting up the course and automatically runs it. Note thatccc
automatically runsapt
andapt-get
withsudo
permissons. We do not recommend that you run any other command that requires sudo. - .envrc is used to set up environment variables.
direnv
automatically loads the environment variables when users enter the directory and unloads them when users exit the directory. - bin/ is used to set up local commands that would have otherwise been aliased or symlinked. For example, suppose that you want the command
gcc
to refer to/usr/bin/x86_64-linux-gnu-gcc-11
. You can create a binary in /bin/gcc which only calls/usr/bin/x86_64-linux-gnu-gcc-11
. Then addexport=$PWD/bin:$PATH
to the .envrc so that the shell knows to look in this directory for gcc.
After you have set up the course repository, make sure to email problem@cs.brown.edu with the remote URL of the course repository and the course name so we can add it to the list of known courses.
If your course has other requirements outside of downloading packages and loading environment variables, email problem@cs.brown.edu.