Skip to content

Commit

Permalink
Merge pull request #132 from nmfs-opensci/main
Browse files Browse the repository at this point in the history
update from main
  • Loading branch information
eeholmes authored Nov 1, 2024
2 parents 725fb4c + 16d1013 commit 0d562e5
Show file tree
Hide file tree
Showing 16 changed files with 626 additions and 520 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ on:
branches:
- dev
paths:
- 'apt.txt'
- 'apt2.txt'
- 'environment.yml'
- 'start'
- 'postBuild'
- 'appendix'
- 'desktop.sh'
- 'rocker.sh'
- 'install_R_source.sh'
- '.github/workflows/build-dev.yaml'

jobs:
Expand Down
53 changes: 9 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,71 +1,36 @@
# py-rocket-base: JupyterHub base image

[![Build and push container image](https://github.com/nmfs-opensci/py-rocket-base/actions/workflows/build.yaml/badge.svg)](https://github.com/nmfs-opensci/py-rocket-base/actions/workflows/build.yaml)[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.13942617.svg)](https://doi.org/10.5281/zenodo.13942617)
[![Build and push container image](https://github.com/nmfs-opensci/py-rocket-base/actions/workflows/build.yaml/badge.svg)](https://github.com/nmfs-opensci/py-rocket-base/actions/workflows/build.yaml)[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.13942617.svg)](https://doi.org/10.5281/zenodo.13942617)[![GitHub Release](https://img.shields.io/github/v/release/nmfs-opensci/py-rocket-base)](https://github.com/nmfs-opensci/py-rocket-base/releases)

The py-rocket-base image is a base image for the JupyterHubs with Python and RStudio. The py-rocket-base image is designed to install the Jupyter and JupyterHub environment with [repo2docker](https://repo2docker.readthedocs.io) and the R environment with [Rocker](https://rocker-project.org/) installation scripts. You can scroll through the Rocker [installation scripts](https://github.com/rocker-org/rocker-versioned2/blob/master/scripts/install_rstudio.sh) to see how the environment is set up.

*There are many ways to install R and RStudio into an image designed for JupyterHubs.* The objective of py-rocket-base is to create a JupyterHub (or binder) image such when you click the RStudio button in the JupyterLab UI to enter the RStudio UI (`/rstudio`), you **enter an environment that is the same as if you had used a Rocker image** but if you are in the JupyterLab UI (`/lab`), the **environment is the same as if you had used repo2docker** to create the environment. There are many other ways to install R and RStudio in a JupyterHub image. See History below for other approaches we have used.
image url
```
ghcr.io/nmfs-opensci/py-rocket-base:latest
```

The base image has the following support:

* Python + JupyterLab with mamba handling package installation
* R + RStudio with the rocker scripts and other functions available
* Desktop VNC ready for installing applications, including Java-based applications
* Desktop ready for installing applications, including Java-based applications
* VSCode

## Where are the images

The `.github/workflows/build.yaml` is a GitHub Action to build the image with [repo2docker-action](https://github.com/jupyterhub/repo2docker-action). It builds to GitHub packages and you will find it in the [packages for the repo](https://github.com/orgs/nmfs-opensci/packages?repo_name=py-rocket-base). The URL will look like
Your image URL in your repo will look like one of these
```
ghcr.io/nmfs-opensci/repo-name/image-name:latest
ghcr.io/nmfs-opensci/image-name:latest
```
For example, for this repo the image is `ghcr.io/nmfs-opensci/py-rocket-base:latest`.
*There are many ways to install R and RStudio into an image designed for JupyterHubs.* The objective of py-rocket-base is to create a JupyterHub (or binder) image such when you click the RStudio button in the JupyterLab UI to enter the RStudio UI (`/rstudio`), you **enter an environment that is the same as if you had used a Rocker image** but if you are in the JupyterLab UI (`/lab`), the **environment is the same as if you had used repo2docker** to create the environment. There are many other ways to install R and RStudio in a JupyterHub image. See History below for other approaches we have used.

## Using this in a JupyterHub

If the JupyterHub has the **Bring your own image** feature, then you can paste in `ghcr.io/nmfs-opensci/py-rocket-base:latest` to the image and a server with your image will spin up.

<img width="772" alt="image" src="https://github.com/user-attachments/assets/13f1d200-b8a6-44e1-a9db-537260b21ec4">

<!--
## Using this as a base image

Create a repo with a Dockerfile that looks like the example below. Include the following files depending on your needs. The py-rocket-geospatial repo shows an example and includes a GitHub Action to build the image.
* R packages: Include `install.R`
* Python packages: `environment.yml`
* Desktop applications: `*.desktop` files + entry in `mime` directory if application should be associated with specific file types.
* root installs: `app.sh` file.
Your Dockerfile in your repo will look like
py-rocket-base is designed like the Pangeo base-image. Your docker file in your repo will look like
```
FROM ghcr.io/nmfs-opensci/py-rocket-base:latest
# If needed to do a root install of software
USER root
COPY app.sh app.sh
RUN chmod +x app.sh && ./app.sh && rm app.sh
USER ${NB_USER}
# install R packages
COPY install.R install.R
RUN Rscript install.R && rm install.R
# install the Python libraries
COPY environment.yml environment.yml
RUN conda env update -n notebook -f environment.yml \
&& conda clean --all \
&& rm environment.yml
# Add a Desktop application
COPY *.desktop ${REPO_DIR}/*.desktop
COPY mime/*.xml ${REPO_DIR}/mime/*.xml
USER ${NB_USER}
```
-->
Then add `environment.yml`, `apt.txt` or `install.R` to the repo and those will be installed. Read the [documentation](https://nmfs-opensci.github.io/py-rocket-base/) for more examples. The behavior with files like `environment.yml` is triggered by `ONBUILD` statements in py-rocket-base. If you want to prevent this behavior, you will need to avoid the specific configuration file names.

## History and motivation

Expand Down
3 changes: 3 additions & 0 deletions book/configuration_files.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ USER ${NB_USER}

## apt.txt

Standard format. You can have comments.

```
# Some useful stuff
tk-dev
Expand All @@ -54,6 +56,7 @@ cmocean

This is a script that will be run after all the other commands. This script is run as jovyan not as root. If you need commands run as root, you will need to add these to the Docker file.

postBuild
```
#!/bin/bash -l
set -e
Expand Down
14 changes: 13 additions & 1 deletion book/customizing.qmd
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Using py-rocket-base

py-rocket-base is designed to be used in the FROM line of a Dockerfile. It behaves like repo2docker in that it looks for special files and will
install Python package or R packages if those special files are present. You do not need to add anything to the Dockerfile to have it process these files. py-rocker-base does this automatically for you.
install Python packages or R packages if those special files are present. You do not need to add anything to the Dockerfile to have it process these files. py-rocker-base does this automatically for you (via ONBUILD commands).

If you don't want it to do this then do not name your files one of these names:

Expand Down Expand Up @@ -62,6 +62,17 @@ dependencies:

Add an R script to install packages. **Important**: packages that have linux dependencies (e.g. all the spatial packages depend on GDAL) will not work if you use `install.packages()`. GDAL will not be installed.

```
your-repo/
├── Dockerfile
├── install.R
```

Dockerfile
```
FROM ghcr.io/nmfs-opensci/py-rocket-base:latest
```

install.R
```
# to match rocker/verse:4.4 used in py-rocker-base
Expand All @@ -75,6 +86,7 @@ install.packages(list.of.packages, repos=repo)

Geospatial packages require some linux packages. To get this working in your Docker image add this to your Docker file:

Dockerfile
```
FROM ghcr.io/nmfs-opensci/py-rocket-base:latest
Expand Down
52 changes: 34 additions & 18 deletions book/desktop.qmd
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
# Desktop

py-rocket-base includes the [xfce4 Desktop UI](https://www.xfce.org/) where you can run applications. A common application is to run QGIS or java-based applications. py-rocket-base
looks for files with the ending `.desktop`, `.xml` (optional), and `.png` (optional) associated with an application in a directory called Desktop in your repo.
py-rocket-base includes the [xfce4 Desktop UI](https://www.xfce.org/) where you can run applications. It is built off [freedesktop](https://www.freedesktop.org/wiki/Software/) (which is helpful to know if you are debugging and configuring). A common application is to run QGIS or java-based applications. py-rocket-base
looks for files with the ending `.desktop`, `.xml` (optional), and `.png` or `.svg` (optional) associated with an application in a directory called Desktop in your repo.

To add new desktop applications[^1],

* Install the application. See examples below.
* Add a `.desktop` file to `${HOME}/.local/share/applications/`.
* To have an icon on the Desktop, you create a folder Desktop in the `${HOME}` and create a soft link to the `.desktop` files in `${HOME}/.local/share/applications/`.

py-rocket-base does these steps automatically (via the start script) so that the user only has to put files into a Desktop directory in the docker build repo.

[^1]: See this [Medium article](https://medium.com/@zoldin/how-to-add-new-application-to-xfce-menu-list-d90955e101d5) for a description.
py-rocket-base puts these `.desktop` files in `/usr/share/Desktop`. Typically these desktop files are in `~/Desktop`. But in a JupyterHub, the home directory is often persistent and py-rocket-base tries not to alter the user home directory. Also there might be orphaned desktop files in `~/Desktop` and so the user desktop UI would be inconsistent between users. Using `/usr/share/Desktop` does mean that users cannot add their own persistent applications to xfce4 Desktop but this would be difficult anyhow without root access in many cases.


## Adding an application in your child docker image

### Create the Desktop directory

Create the directory and add the .desktop and optional .png and .xml files.
Create the directory and add the .desktop and optional .png and .xml files. py-rocket-base will move them to the correct places (`/usr/share/applications` and `/usr/share/Desktop`, `/usr/share/mime/packages` and icon locations).

```
your-repo/
Expand All @@ -33,8 +25,9 @@ your-repo/

#### .desktop file

Example `.desktop` file is a configuration file that describes how an application is launched. The required parts are Name, Exec and Type. MimeType specifies what types of files the application can use (optional).
The `.desktop` file is a configuration file that describes how an application is launched. The required parts are Name, Exec and Type. MimeType specifies what types of files the application can use (optional).

cdat.desktop
```
[Desktop Entry]
Type=Application
Expand All @@ -53,9 +46,19 @@ Keywords=map;globe;

You can specify the mime types via xml.

#### .png
#### icons

You can include a png or svg for the icon. py-rocket-base will place this in `/usr/share/icons/packages`. If you put your icon file in the Desktop directory in your repo, then in your desktop file, use the file name without the extension.

```
Icon=cdat
```

You can also use an absolute file path.

You can include a png for the icon. py-rocket-base will place this in `/srv/repo/Desktop/` so use a location like `/srv/repo/Desktop/my.png` for your png that you include in your Desktop folder.
```
Icon=/srv/conda/envs/notebook/share/qgis/images/icons/qgis-icon-512x512.png
```


### Install the application
Expand All @@ -66,7 +69,9 @@ How you install the application really varies. Here are 2 examples.

* add `qgis` to `environment.yml`
* add `libgl1-mesa-glx` to `apt.txt`
* .desktop file
* add the .desktop file to Desktop directory

qgis.desktop
```
# From: https://github.com/qgis/QGIS/blob/ltr-3_28/linux/org.qgis.qgis.desktop.in
[Desktop Entry]
Expand All @@ -86,7 +91,7 @@ StartupWMClass=QGIS3

**CoastWatch Utilities**

Add this to the docker file
Add this to the docker file to install
```
USER root
# Install cwutils
Expand Down Expand Up @@ -115,4 +120,15 @@ Categories=Qt;Education;Science;Geography;
Keywords=map;globe;
```

Add `cdat.png` icon to Desktop directory.
Add `cdat.png` icon to Desktop directory.

## What's happening

To add new desktop applications, one needs to do the following. py-rocket-base does these steps automatically (via the start script) so that the user only has to put files into a Desktop directory in the docker build repo.

* Install the application. See examples.
* Add a `.desktop` file to an application directory. py-rocket-base puts these in `/usr/share/applications` but you will also see `${HOME}/.local/share/applications/`.
* To have an icon on the Desktop, you create a folder Desktop and tell XDG what directory to use. The directory is specified in `~/.config/user-dirs.dirs` which XDG sets. By default (XDG), this folder is `~/Desktop` but you can set it to something else. py-rocket-base sets a default value in `/etc/xdg/user-dirs.defaults`. This updates `~/.config/user-dirs.dirs` when the `/etc/xdg/xfce4/xinitrc` start script is run (when the `/desktop` button is clicked).
* XDG looks for .desktop files in the Desktop directory. py-rocket-base creates a soft link to the `.desktop` files in `/usr/share/applications/` in `/usr/share/Desktop`.

See this [Medium article](https://medium.com/@zoldin/how-to-add-new-application-to-xfce-menu-list-d90955e101d5) for a description.
Loading

0 comments on commit 0d562e5

Please sign in to comment.