Skip to content

Commit

Permalink
Merge pull request #140 from janpfeifer/docker
Browse files Browse the repository at this point in the history
Docker customization
  • Loading branch information
janpfeifer authored Oct 16, 2024
2 parents 78b21ef + 427c299 commit bed2f86
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 29 deletions.
43 changes: 32 additions & 11 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,44 @@
#######################################################################################################
# Base image from JupyterLab
#######################################################################################################
ARG BASE_IMAGE=jupyter/base-notebook
ARG BASE_IMAGE=quay.io/jupyter/base-notebook
ARG BASE_TAG=latest
FROM ${BASE_IMAGE}:${BASE_TAG}

# Update apt and install basic utils
# Update apt and install basic utils that may be helpful for users to install their own dependencies.
USER root
RUN apt update --yes
RUN apt install --yes --no-install-recommends wget git
RUN apt install --yes --no-install-recommends \
sudo wget git openssh-client rsync curl

# Give NB_USER sudo power for "/usr/bin/apt-get install/update" or "/usr/bin/apt install/update".
USER root
RUN groupadd apt-users
RUN usermod -aG apt-users $NB_USER
# Allow members of the apt-users group to execute only apt-get commands without a password
RUN echo "%apt-users ALL=(ALL) NOPASSWD: /usr/bin/apt-get update, /usr/bin/apt-get install *" >> /etc/sudoers
RUN echo "%apt-users ALL=(ALL) NOPASSWD: /usr/bin/apt update, /usr/bin/apt install *" >> /etc/sudoers

#######################################################################################################
# Go and GoNB Libraries
#######################################################################################################
ARG GO_VERSION=1.23.2
ENV GOROOT=/usr/local/go
ENV GOPATH=/opt/go
ENV GOPATH=$HOME/go
ENV PATH=$PATH:$GOROOT/bin:$GOPATH/bin

# Create Go directory for user -- that will not move if the user home directory is moved.
USER root
RUN mkdir ${GOPATH} && chown ${NB_USER}:users ${GOPATH}
# Add exported variables to $NB_USER .profile: notice we start the docker as root, and it executes
# JupyterLab with a `su -l $NB_USER`, so the environment variables are lost. We could use --preserve_environment
# for GOROOT and GOPATH, but it feels safer to add these to .profile, so the autostart.sh script can also
# execute `su -l $NB_USER -c "<some command>"` if it wants.
USER $NB_USER
WORKDIR ${HOME}
RUN <<EOF
echo "NB_USER=${NB_USER}" >> .profile
echo "export PATH=${PATH}" >> .profile
echo "export GOPATH=${GOPATH}" >> .profile
echo "export GOROOT=${GOROOT}" >> .profile
EOF

USER root
WORKDIR /usr/local
Expand All @@ -56,7 +74,7 @@ RUN export GOPROXY=direct && \
# Prepare directory where Jupyter Lab will run, with the notebooks we want to demo
####################################################################################################### \
USER root
ARG NOTEBOOKS=/notebooks
ENV NOTEBOOKS=/notebooks

# Create directory where notebooks will be stored, where Jupyter Lab will run by default.
RUN mkdir ${NOTEBOOKS} && chown ${NB_USER}:users ${NOTEBOOKS}
Expand All @@ -77,8 +95,11 @@ USER root
RUN apt-get clean && rm -rf /var/lib/apt/lists/*

# Start-up.
USER $NB_USER
USER root
WORKDIR ${NOTEBOOKS}

EXPOSE 8888
ENTRYPOINT ["tini", "-g", "--", "jupyter", "lab"]
# Script that checks for `autostart.sh` (and runs it if owned by root and present), and then starts
# JupyterLab.
COPY cmd/check_and_run_autostart.sh /usr/local/bin/

ENTRYPOINT ["tini", "-g", "--", "/usr/local/bin/check_and_run_autostart.sh"]
36 changes: 19 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# GoNB, A Modern Go Kernel for Jupyter Notebooks
# GoNB, A Modern Go Kernel for Jupyter 📓Notebooks📓

[![GoDev](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white)](https://pkg.go.dev/github.com/janpfeifer/gonb?tab=doc)
[![GitHub](https://img.shields.io/github/license/janpfeifer/gonb)](https://github.com/Kwynto/gosession/blob/master/LICENSE)
Expand All @@ -9,15 +9,12 @@



## For a quick start, see the [**tutorial**](examples/tutorial.ipynb)!
## For a quick start, see the [**tutorial** 🧭](examples/tutorial.ipynb)

## Highlights:
## Highlights:

<img align="right" width="480px" src="https://repository-images.githubusercontent.com/599714179/38d0328a-abdb-4f69-9617-6ef136390708">

* **NEW**: Now supported by [Jupytext](https://github.com/mwouts/jupytext): it allows one to write the notebook as a normal.
Go file, and use [Jupytext](https://github.com/mwouts/jupytext) to convert to a notebook (with markdown support, etc).
See [example](https://github.com/mwouts/jupytext/issues/1244#issuecomment-2202097837).
* Auto-complete and contextual help while coding.
* Rich content display: HTML, markdown (with latex), images, javascript, svg, videos, etc.
* Widgets (sliders, buttons) support: interact using HTML elements. Create your own widgets!
Expand All @@ -27,6 +24,9 @@
It also supports arbitrary Go compilation flags to be used when executing the cells.
* Faster execution than interpreted Go, used in other similar kernels -- at the cost of imperceptible increased
start up, since each cell is compiled.
* Supported by [Jupytext](https://github.com/mwouts/jupytext): it allows one to write the notebook as a normal.
Go file, and use [Jupytext](https://github.com/mwouts/jupytext) to convert to a notebook (with markdown support, etc).
See [example](https://github.com/mwouts/jupytext/issues/1244#issuecomment-2202097837).
* Run cell's `Test*` and `Benchmark*` functions with `go test`, simply adding `%test` to cell.
* Support for `go.mod` and `go.work`, to allow local development. Including importing specific versions of libraries.
* Debug using [gdlv](https://github.com/aarzilli/gdlv), a GUI for the [delve](https://github.com/go-delve/delve) debugger (see %help).
Expand All @@ -38,7 +38,7 @@
* Online help and much more, see `%help`.
* Compile and execute the Go code as WASM: allows one to do interactive widgets in notebooks. See `%wasm` (EXPERIMENTAL).

## Examples:
## 👁️‍🗨️ Examples:

### Auto-complete and Contextual Help

Expand All @@ -57,7 +57,7 @@ https://github.com/janpfeifer/gonb/assets/7460115/f1187dad-4c10-4d21-a73e-909001

<img src="docs/demo-browser.png" alt="Browser Screenshot Demo" width="50%" height="50%"/>

## Introduction
## 🌱 Introduction

Go is a compiled language, but with very fast compilation, that allows one to use
it in a REPL (Read-Eval-Print-Loop) fashion, by inserting a "Compile" step in the middle
Expand All @@ -84,15 +84,15 @@ There is also
that one can interact with (make a copy first) — if the link doesn't work (Google Drive sharing publicly
is odd), [download it from GitHub](examples/google_colab_demo.ipynb) and upload it to Google's Colab.

Finally, because it's compiled and not intepreted, it has a slightly different "semantic" than the Python kernels.
Finally, because it's compiled and not interpreted, it has a slightly different "semantic" than the Python kernels.
It's highly recommended quickly browsing through the [**tutorial**](examples/tutorial.ipynb).

## Installation
## 📦 Installation

**Only for Linux and macOS. In Windows, it works in WSL or inside a Docker**


### Docker
### 🐳 Docker

GoNB offers a [pre-built docker](https://hub.docker.com/r/janpfeifer/gonb_jupyterlab),
that includes JupyterLab and GoNB.
Expand All @@ -104,11 +104,13 @@ To start it:

```shell
docker pull janpfeifer/gonb_jupyterlab:latest
docker run -it --rm -p 8888:8888 -v "${PWD}":/notebooks/host janpfeifer/gonb_jupyterlab:latest
docker run -it --rm -p 8888:8888 -v "${PWD}":/notebooks janpfeifer/gonb_jupyterlab:latest
```

Then copy&paste the URL that it outputs in your browser.

**Note**: The docker allows for customization by running an arbitrary script at start up as `root`, which allows
one to install any planned dependencies. See [docker.md](docs/docker.md) for details.

### Linux and macOS Installation Using Standard Go Tools

Expand Down Expand Up @@ -149,7 +151,7 @@ Install there as if it were in a linux machine.

A pure Windows installation is not supported at this time — but contributions to add support for it would be welcome :)

## FAQ
## 🤔 FAQ

* Is there are reference documentation ?
* There is a help (run `%help` in a cell) and a [**tutorial**](examples/tutorial.ipynb), which is kept up-to-date and
Expand All @@ -163,15 +165,15 @@ A pure Windows installation is not supported at this time — but contributions
solutions to this. Often folks create a series of `Must()` functions, or simply use
[this trivial `must` package](https://github.com/janpfeifer/must).

## TODOs
## 📝 TODOs

Contributions are welcome!

* Windows version:
* Installation.
* Named-pipe implementation in `kernel/pipeexec.go`.

## Thanks
## 💖 Thanks

* [Go](golang.org)
* [Jupyter](https://jupyter.org/), what an awesome project.
Expand All @@ -180,7 +182,7 @@ Contributions are welcome!
(http://reneefrench.blogspot.com/), see Creative Commons 3.0 Attributions license in
[Wikimedia](https://commons.wikimedia.org/wiki/File:Go_gopher_favicon.svg).

## Contributing
## 🤝 Contributing

Contributions are very welcome. The code is generally well documented -- not always, but mostly. There are a also a couple of guides worth reading if contributing in the [`docs/`](https://github.com/janpfeifer/gonb/tree/main/docs) subdirectory.

Expand All @@ -189,6 +191,6 @@ There are two parts of the project:
1. The kernel itself: that builds the binary package. Most subpackages are under `internal/`.
2. The UI library in the packages under `github.com/janpfeifer/gonb/gonbui`.

## Star History
## 🌟 Star History

[![Star History Chart](https://api.star-history.com/svg?repos=janpfeifer/gonb&type=Date)](https://star-history.com/#janpfeifer/gonb&Date)
2 changes: 1 addition & 1 deletion binder/postBuild
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash
set -eu

GO_VERSION=1.20
GO_VERSION=1.23.2

curl -sfL https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz | tar -xz

Expand Down
28 changes: 28 additions & 0 deletions cmd/check_and_run_autostart.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

# This script is included in the Docker, and is executed at startup of the docker, allowing the user to write
# an arbitrary setup script in `autostart.sh` for the image -- things like installing databases, credentials, etc.
#
# Notice ${NOTEBOOKS} is /notebooks in the container, and is assumed to be mounted from the host directory that
# will have the users notebooks.

# Makes sure we are not using $NB_USER's GOPATH.
export GOPATH=/root/go

# Check if autostart.sh exists
if [[ -f "${NOTEBOOKS}/autostart.sh" ]]; then
# Check if it's owned by root and is executable
if [[ "$(stat -c '%U' "${NOTEBOOKS}/autostart.sh")" = "root" && -x "${NOTEBOOKS}/autostart.sh" ]]; then
# Run autostart.sh as root
echo "Running autostart.sh as root..."
"${NOTEBOOKS}/autostart.sh"
else
# Print a message indicating why it's not running
echo "autostart.sh exists but is not owned by root or not executable. Not running it."
fi
else
echo "No autostart.sh initialization script."
fi

# Run JupyterLab from $NOTEBOOKS as user $NB_USER.
su -l "${NB_USER}" -c "cd \"${NOTEBOOKS}\" ; jupyter lab"
9 changes: 9 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# GoNB Changelog

## Next

* Feature request #138
* Added openssh-client, rsync and curl, to allow users to install other dependencies.
* Added sudo for apt install and apt update.
* Added support for `autostart.sh` that if present in the mounted container `/notebooks` directory, and if root owned
and set as executable.
* Updated Dockerfile to latest version to JupyterLab -- now the base docker is served `quay.io/jupyter/base-notebook`

## v0.10.5, Added SendAsDownload

* Added `dom.SendAsDownload` to send data from cells to the client by triggering a browser download. #134
Expand Down
41 changes: 41 additions & 0 deletions docs/docker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Docker Customization

1. The docker runs _JupyterLab_ and _GoNB_ under the user `$NB_USER` (== "jovyan").
2. It has configured `sudo` privileges for `apt update` and `apt install *`. So a cell with
`!sudo apt install <my_package>` will work, and install your package.
3. One can always create another docker based on `janpfeifer/gonb_jupyterlab@latest`
4. Create an `autostart.sh` script, see next section.

## Customization with `autostart.sh`

If you create the file `autostart.sh` in the directory mounted under `/notebooks` in the container,
**owned by `root` and with executable permissions**, it will be executed at start up of the container by default
**as `root`**.

This allows you to download/install databases, or set up credentials, etc.

Example of an `autostart.sh` that:

- Sets the timezone
- Installs [`nats`](github.com/nats-io/natscli/) for the jupyer user (given by `$NB_USER`).

```
# Set the German timezone (so time.Now() returns German time)
apt-get install -y tzdata
ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime
# some locale magic to make "date" answer with German format
echo 'de_DE.UTF-8 UTF-8' >> /etc/locale.gen
locale-gen
echo 'LC_ALL="de_DE.utf8"' > /etc/default/locale
export LC_ALL="de_DE.UTF-8"
dpkg-reconfigure locales
# check that it works
date
# Installing Go tools for $NB_USER.
su -l "$NB_USER" -c "go install github.com/nats-io/natscli/nats@latest"
```

More details in the `Dockerfile` and in the small start script `cmd/check_and_run_autostart.sh`.

0 comments on commit bed2f86

Please sign in to comment.