Skip to content

Commit

Permalink
update a bunch of stuff in docker development
Browse files Browse the repository at this point in the history
  • Loading branch information
firasm committed Jan 13, 2024
1 parent e7f0928 commit 77a4cc4
Show file tree
Hide file tree
Showing 19 changed files with 379 additions and 1 deletion.
2 changes: 1 addition & 1 deletion _toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ parts:
- file: content/authoring/randomizing_tips
- file: content/authoring/randomization_framework

- caption: 5. Local PrairieLearn question development with Docker
- caption: 5. Local PrairieLearn course development (Docker)
chapters:
- file: content/pl_docker/preparation
- file: content/pl_docker/opb_course_repo
Expand Down
1 change: 1 addition & 0 deletions content/authoring/creating_q.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
(authoring)=
# Creating a PrairieLearn question

There are three important files created for the PrairieLearn platform:
Expand Down
44 changes: 44 additions & 0 deletions content/pl_docker/custom_docker_images.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Creating Docker Images

## Step 1: Create a Dockerhub Account
[Create a docker hub account](https://hub.docker.com/signup) if you don’t have one already.

## Step 2: Create your DockerFile

Example:
```Dockerfile
# Dockerfile
FROM prairielearn/grader-r

# Install R packages
RUN Rscript -e "install.packages('openintro')"
```

## Step 3: Push your Docker image to DockerHub
`cd` into the directory containing your DockerFile, then run the following commands:
```sh
docker login
docker build -t <image-name> .
docker tag grader-r:latest <dockerusername>/<image-name>:latest
docker push <dockerusername>/<image-name>:latest
```

## Step 4: Add your image to your PraireLearn question

Ex. If you are using this Docker image for the external autograder, add the image to your markdown YAML header.
```yaml
gradingMethod: External
externalGradingOptions:
enabled: true
image: <dockerusername>/grader-r # made an image that has openstats installed, otherwise use prairielearn/grader-r
entrypoint: /r_autograder/run.sh
timeout: 60
```
## Step 5: Load Docker image into OPB 000
<img src="pl_images/opb000_docker_sync.png">
If your image shows up under "Docker Images", click the button under the "Actions" column
Otherwise, click "Sync all images from DockerHub to PrairieLearn"
If your image still doesn't show up under "Docker Images", try running your question first, then try syncing the image again.
241 changes: 241 additions & 0 deletions content/pl_docker/docker_course_dev.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
(prairielearn_docker)=
# PrairieLearn Course Development on Docker

This page describes the procedure to install and run your course locally within Docker.
The steps listed below **only need to be done once**, once you've got things setup correctly, you should refer to the [Question Development](authoring) page for subsequent questions.

## Step 1: Ensure Docker is installed on your machine

Before you start, make sure the Docker application is installed and running.

To confirm Docker is working, open a Terminal and run the following:

```bash
docker --version
```

You should get an output similar to:

```bash
Docker version y.y.y, build yyyyy
```

If this doesn't work, visit the Docker section in the setup guide for [macOS](page_install_ds_stack_macOS), or [Windows](page_install_ds_stack_windows).

<!-- #TODO: Add ubuntu page [Ubuntu](page_install_ds_stack_ubuntu) -->

## Step 2: Pull the PrairieLearn Docker container

Open a Terminal, and run the following to pull the PrairieLearn image:

```bash
docker pull prairielearn/prairielearn
```

On an M1/M2 Mac, you will probably get an error like,

> no matching manifest for linux/arm64/v8 in the manifest list entries
If so, set the platform to `linux/x86_64` (because there isn't an M1/M2 image yet) like this:

```bash
docker pull --platform linux/x86_64 prairielearn/prairielearn
```

It will take a few minutes to download (depending on your internet connection).

## Step 3: Run PrairieLearn using the example course

To Launch PrairieLearn locally, run the following command:

```bash
docker run -it --rm --pull=always -p 3000:3000 prairielearn/prairielearn
```

```{tip}
The PrairieLearn docker image is always being updated with new features and bug fixes. To ensure that you're always working with the latest PrairieLearn codebase, we add the `--pull=always` option to our Docker command.
```

Your Terminal will be occupied and while it's launching, the message in the Terminal will say "Starting PrairieLearn...".
Once it's launched, a message will print in the Terminal that says:

> info: Go to http://localhost:3000;
visit that webpage in a new browser.
Your Terminal will still be occupied and you should keep it running.
To interrupt and stop the container, press `Ctrl + C` in the Terminal (you may have to do this several times).

In a browser, here's what you should see:

<img src="pl_images/pl_server.png">

## Step 4: Load the Example Course

Every time you launch a PrairieLearn Docker container, you will need to load the list of courses.
By default, the PrairieLearn Docker image contains a directory named [`exampleCourse`](https://github.com/PrairieLearn/PrairieLearn/tree/master/exampleCourse).
First, click on "Load from disk" above and then click "PrairieLearn" in the top left corner to come back to this page.

Once you return to the PrairieLearn home page, here is what you should see:

<img src="pl_images/pl_server_courses.png">

## Step 5: Explore the Example Course

The example course contains many question and assessment types for you to explore.
You can experience the questions within Assessments (as students would see it), or browse questions from the Question Bank individually using tags and topics.

Here is what the Assessments will look like.

<img src="pl_images/pl_example_course.png">

For more details about the example course and how to author your own questions, [see this section here](https://prairielearn.readthedocs.io/en/latest/getStarted/).

## Step 6: Stop the Docker Container

Once you're done exploring, stop the Docker Container (using `Ctrl+C` in the Terminal).
Another way to stop the Docker container is to open Docker Desktop and press the stop (⏹️) button.

<img src="pl_images/docker_stop.png">

```{tip}
This step is sometimes a bit finicky - your Terminal may stop responding when trying to stop the Container using `Ctrl+C`.
If that happens, don't close the Terminal, and use the Docker Desktop to stop the container.
```

## Step 7: Fork the IND 100 sample PrairieLearn course

If you haven't already done this, follow the [steps outlined here](opb_course_repo).

<!--
## Step 6: Request your own course on PrairieLearn
Once you're ready to develop questions for your own course, you should first request a course through the appropriate PrairieLearn instance:
<img src="pl_images/pl_request_course.png">
Once you have a PrairieLearn course, you should clone it locally, and then add it to your local Docker container (see next step).
-->

## Step 8: Add your own course to the local PrairieLearn instance

To use your own course, bind the Docker `/course` directory with your own course repo directory using the `-v` flag.
In the command below, replace `local_path` with the path to where your course repo is cloned locally:

```bash
docker run -it --rm --pull=always -p 3000:3000 -v local_path:/course prairielearn/prairielearn
```

````{tip}
For staff working on the Open Problem Bank, your `local_path` should be the **absolute path** wherever you cloned the IND 100 (`pl-opb-ind100`) and the `instructor_subject_bank` repositories.
For example, the exact command for me is:
```bash
docker run -it --rm --pull=always -p 3000:3000 -v ~/Sync/EL/OPB/course_dev/pl-opb-ind100:/course prairielearn/prairielearn
```
````

```{tip}
If you are using Docker for Windows then you will need to first give Docker permission to access the `C:` drive (or whichever drive your course directory is cloned in).
This can be done by right-clicking on the Docker "whale" icon in the taskbar, choosing "Settings", and granting shared access to the `C:` drive.
```

To use multiple courses, add additional `-v` flags (e.g., -v /path/to/course:/course -v /path/to/course2:course2).
There are nine available mount points in the Docker: `/course`, `/course2`, `/course3`, `...`, `/course9`.

If you're in the root of your course directory already, you can substitute `%cd%` (on Windows) or `$PWD` (Linux and MacOS) for `/path/to/course`.

<!--
If you plan on running externally graded questions in local development, please see [this section](https://prairielearn.readthedocs.io/en/latest/externalGrading/#running-locally-on-docker) for a slightly different docker launch command.
**NOTE**: On MacOS with "Apple Silicon" (ARM64) hardware, the use of R is not currently supported.
-->

<!--
## Step 9: Run the script to move a question from the `instructor_subject_bank` to IND 100
Since we are writing questions for the OPB using MyST Markdown (more details about this later), there is an extra processing step to convert the `.md` file to the PrairieLearn format (`.html`, `.json`, and `.py` files).
This processing step is somewhat automated using GitHub Actions, but it's often helpful to do the processing locally since it takes much less time and is more efficient when troubleshooting.
Here are the steps to run the processing step on an `.md` question to create `.html`, `.json`, and `.py` files, and then move them over to the IND 100 and see how the question looks.
- Open a Terminal on your local machine, and change directory to where the `instructor_subject_bank` is cloned.
- `cd` into the `scripts` directory.
- Run the script on a particular question:
```bash
python checkq.py ../source/001.Math/Algebra/Smudge/Smudge.md --output_root=../../pl-opb-ind100/questions/FM
```
-->

## Step 9: Author your questions

Once you've tweaked your question within your course repository, you can view the question locally using these steps:

- Open the local instance of PrairieLearn in your browser (http://localhost:3000).
- Click "Load from Disk".
- Verify the question works as expected on PrairieLearn in the browser.

```{important}
When developing locally on PrairieLearn, you **must** click "Load from Disk" every time you make a change in your `questions` directory!
<img src="pl_images/pl_load_from_disk.png">
```

That's it!
You're ready to develop questions for the `OPB`!

## Setting up local autograder container

For development of questions that require an autograder, you will need to set up a local autograder container as well.

### Important! (Windows Only)

If you are using Windows, the following commands will need to be executed in Windows Subsystem for Linux (WSL). You can do this two ways:
1. Open a command prompt and type `wsl` to open a WSL terminal
1. Look for the Windows Subsystem for Linux application in the Start Menu
<img src="pl_images/wsl_icon_windows.png">

### Step 1: Create a local directory for the autograder

To run PrairieLearn locally with external grader and workspace support, create an empty directory to use to share job data between containers. This directory can live anywhere, but needs to be created first and referenced in the docker launch command. This directory only needs to be created once.

```bash
mkdir "$HOME/pl_ag_jobs"
```

### Step 2: Run the PrairieLearn Autograder container

Now, run PrairieLearn as usual, but with additional options. For example, if your course directory is in $HOME/pl-tam212 and the jobs directory created above is in $HOME/pl_ag_jobs, and you are using Linux or Mac OS X, the new command is as follows:

```bash
docker run -it --rm --pull=always -p 3000:3000 \
-v "$HOME/pl-opb-ind100:/course" `# Replace the path with your course directory` \
-v "$HOME/pl_ag_jobs:/jobs" `# Map jobs directory into /jobs` \
-e HOST_JOBS_DIR="$HOME/pl_ag_jobs" \
-v /var/run/docker.sock:/var/run/docker.sock `# Mount docker into itself so container can spawn others` \
prairielearn/prairielearn
```

If you are on Windows, you can use the following command on the WSL 2 shell:

```bash
docker run -it --rm --pull=always -p 3000:3000 \
-v "$HOME/pl-opb-ind100:/course" `# Replace the path with your course directory` \
-v "$HOME/pl_ag_jobs:/jobs" `# Map jobs directory into /jobs` \
-e HOST_JOBS_DIR="$HOME/pl_ag_jobs" \
-v /var/run/docker.sock:/var/run/docker.sock `# Mount docker into itself so container can spawn others` \
--add-host=host.docker.internal:172.17.0.1 \
prairielearn/prairielearn
```

*NOTE*: When replacing the path with your course directory on Windows, make sure to use a POSIX-style path (e.g. `/mnt/c/Users/username/pl-opb-ind100`) and __not__ the Windows path (e.g. `C:\Users\username\pl-opb-ind100`).

### Note: Grader images

When attempting a question with the autograder configured for the first time, the grader image will be automatically pulled by PrairieLearn. This may take a few minutes, but will only need to be done once. The grader image will be cached locally for future use. If PrairieLearn is unable to pull the grader image, it may be necessary to manually pull the image using the following command:

```bash
docker pull prairielearn/grader-python
```

*Note*: The above command is for the Python grader image. If you are using a different grader image, you will need to replace `prairielearn/grader-python` with the appropriate image name.
31 changes: 31 additions & 0 deletions content/pl_docker/opb_course_repo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Forking a PrairieLearn course for local development

It takes a lot of trial and error to get the hang of developing questions on PrairieLearn, particularly if you are algorithmically randomizing the questions.
From experience, the best way to develop questions is to have access to a demo course of your own so you can see exactly how the questions are rendered, and what tweaks need to be made to improve how the questions are displayed.

To get your own PrairieLearn course for local development, follow these steps:

## Step 1: Visit the [IND 100](https://github.com/open-resources/pl-opb-ind100) course repository.

<img src="pl_images/ind100.png">

## Step 2: Fork the IND 100 repo into your **personal GitHub account**.

<img src="pl_images/ind100_fork.png">

## Step 3: Clone your fork of the IND 100 repository locally

```{warning}
For best results, you should clone your `IND 100` course repository in the same directory your cloned `instructor_subject_bank`.
```

Open a Terminal, navigate to the directory you want to clone the IND 100 course and then run:

```
git clone git@github.com:firasm/pl-opb-ind100.git
```

<img src="pl_images/ind100_clone.png">

Once you've got the repository cloned locally, you can [use Docker to continue course development](prairielearn_docker).

Binary file added content/pl_docker/pl_images/docker_stop.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/pl_docker/pl_images/folder_setup.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/pl_docker/pl_images/ind100.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/pl_docker/pl_images/ind100_clone.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/pl_docker/pl_images/ind100_fork.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/pl_docker/pl_images/ind100_sync_fork.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/pl_docker/pl_images/pl_load_from_disk.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/pl_docker/pl_images/pl_server.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
61 changes: 61 additions & 0 deletions content/pl_docker/preparation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Preparation

Before you get started with authoring your first question, it's worth getting organized and setting up your working environment so that you can work efficiently, reliably, and reproducibly.

## Questions to consider before starting

Here are some questions you should answer in this section:

1. **What is the path of the directory you want to work in?** Below are some **suggestions** but select a path that makes sense to you. The examples below assume your computer username is `pixiedust`:
- On macOS:
- `/Users/pixiedust/Documents/Summer2023/`
- `/Users/pixiedust/Desktop/Summer2023/`
- `/Users/pixiedust/Documents/`
- `/Users/pixiedust/`

```{warning}
It is not recommended that you clone repositories in cloud-hosted folders (such as Dropbox, Box.com, or OneDrive). This is because most of these special folders make the contents available on demand and offload the content to the cloud (rather than having the files available locally).
```
1. **What is the Code Editor you want to use?** All of the instructions and demos will be using Visual Studio Code (and that's what we recommend), but you're welcome to use other interactive development environments (IDEs) if you like.
1. **Which Terminal do you intend to use?**
- On macOS and Ubuntu, we suggest using the built-in Terminal and/or the Terminal that is embedded into Visual Studio Code.
## Instructions
Now that you've answered all the prep questions, it's time to set up your working environment!
```{tip}
In the instructions below, replace `OPB` with the course like `CPSC210` and replace `instructor_subject_bank` with the course repository: `pl-ubc-cpsc210`.
```

1. Create a parent directory for this project called `OPB` wherever you decided to work locally on your machine.

1. Clone the `instructor_subject_bank` locally in the `OPB` directory, and then`cd`

```
git clone git@github.com:open-resources/instructor_physics_bank.git
```
1. Change directory to the parent directory:
```
/Users/pixiedust/Desktop/OPB/instructor_subject_bank
```
1. Run the command to install the pre-commit hooks locally in the `instructor_subject_bank` directory:
```
pre-commit install
```
Now you're ready to continue configuring and installing Docker!
```{tip}
Often we will want to hide certain files from the VS Code.
For example, the `.ipynb_checkpoints` directory.
To do this, follow the directions [here](https://www.w3schools.io/editor/vscode-hide-files-folder/).
```

0 comments on commit 77a4cc4

Please sign in to comment.