Skip to content

Commit

Permalink
Added jupyter base image
Browse files Browse the repository at this point in the history
  • Loading branch information
kbegiedza committed Jun 17, 2023
1 parent a9e6d38 commit 8514c49
Show file tree
Hide file tree
Showing 9 changed files with 550 additions and 0 deletions.
82 changes: 82 additions & 0 deletions .github/workflows/jupyter.base.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Build and push

on:
workflow_dispatch:
inputs:
py_version:
type: string
required: true
description: "Python version (default = 3.11)"

push:
branches:
- master
paths:
- "base/**"

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository_owner }}/jupyter

jobs:
build-and-push:
runs-on: ubuntu-22.04
permissions:
contents: read
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
id-token: write

steps:
- name: Setup environment
run: |
echo "PY_VERSION=${PY_VERSION:-3.11}" >> $GITHUB_ENV
- name: Checkout repository
uses: actions/checkout@v3

# Install the cosign tool except on PR
# https://github.com/sigstore/cosign-installer
- name: Install cosign
if: github.event_name != 'pull_request'
uses: sigstore/cosign-installer@d6a3abf1bdea83574e28d40543793018b6035605
with:
cosign-release: "v1.7.1"

# Workaround: https://github.com/docker/build-push-action/issues/461
- name: Setup Docker buildx
uses: docker/setup-buildx-action@79abd3f86f79a9d68a23c75a09a9a85889262adf

# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
with:
file: Dockerfile
context: base
push: ${{ github.event_name != 'pull_request' }}
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:base-py${{ env.PY_VERSION }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
PY_VERSION=${{ env.PY_VERSION }}
Empty file added base/.dockerignore
Empty file.
84 changes: 84 additions & 0 deletions base/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
ARG PY_VERSION=3.11
FROM mcr.microsoft.com/devcontainers/python:${PY_VERSION}

LABEL maintainer="Krzysztof Begiedza <[email protected]>"

ARG NB_USER="jovyan"
ARG NB_UID="1000"
ARG NB_GID="100"

# Fix: https://github.com/hadolint/hadolint/wiki/DL4006
# Fix: https://github.com/koalaman/shellcheck/wiki/SC3014
SHELL ["/bin/bash", "-o", "pipefail", "-c"]

# Configure environment variables
ENV SHELL=/bin/bash \
NB_USER="${NB_USER}" \
NB_UID=${NB_UID} \
NB_GID=${NB_GID} \
LC_ALL=en_US.UTF-8 \
LANG=en_US.UTF-8 \
LANGUAGE=en_US.UTF-8
ENV HOME="/home/${NB_USER}"
ENV DEBIAN_FRONTEND noninteract
ENV NVIDIA_VISIBLE_DEVICES all
ENV NVIDIA_DRIVER_CAPABILITIES compute,utility
ENV LD_LIBRARY_PATH /usr/local/nvidia/lib:/usr/local/nvidia/lib64

# Rename vscode user to ${NB_USER} (jovyan)
RUN usermod -l ${NB_USER} vscode \
&& usermod -d /home/${NB_USER} -m ${NB_USER} \
&& chown -R ${NB_USER}:${NB_GID} /home/${NB_USER}

RUN apt-get update --yes && \
apt-get upgrade --yes && \
apt-get install --yes --no-install-recommends \
bzip2 \
ca-certificates \
locales \
sudo \
tini \
wget && \
apt-get clean && rm -rf /var/lib/apt/lists/* && \
echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && \
locale-gen

# Copy a script to fix permissions
COPY fix-permissions.sh /usr/local/bin/fix-permissions.sh
RUN chmod a+rx /usr/local/bin/fix-permissions.sh

RUN echo "auth requisite pam_deny.so" >> /etc/pam.d/su && \
sed -i.bak -e 's/^%admin/#%admin/' /etc/sudoers && \
sed -i.bak -e 's/^%sudo/#%sudo/' /etc/sudoers && \
chmod g+w /etc/passwd && \
fix-permissions.sh "${HOME}"

# Install jupyter
RUN python3 -m pip install --upgrade pip && \
python3 -m pip install \
notebook \
jupyterhub \
jupyterlab && \
jupyter notebook --generate-config && \
jupyter lab clean && \
rm -rf "/home/${NB_USER}/.cache/yarn" && \
fix-permissions.sh "/home/${NB_USER}"

ENV JUPYTER_PORT=8888
EXPOSE $JUPYTER_PORT

ENTRYPOINT [ "tini", "-g", "--" ]

CMD [ "start-notebook-frozen.sh" ]

COPY start.sh start-notebook-frozen.sh /usr/local/bin/
COPY jupyter_server_config.py /etc/jupyter/

# Legacy for Jupyter Notebook Server, see: [#1205](https://github.com/jupyter/docker-stacks/issues/1205)
RUN sed -re "s/c.ServerApp/c.NotebookApp/g" \
/etc/jupyter/jupyter_server_config.py > /etc/jupyter/jupyter_notebook_config.py && \
fix-permissions.sh /etc/jupyter/

USER ${NB_UID}

WORKDIR "${HOME}"
35 changes: 35 additions & 0 deletions base/fix-permissions.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/bin/bash
# set permissions on a directory
# after any installation, if a directory needs to be (human) user-writable,
# run this script on it.
# It will make everything in the directory owned by the group ${NB_GID}
# and writable by that group.
# Deployments that want to set a specific user id can preserve permissions
# by adding the `--group-add users` line to `docker run`.

# uses find to avoid touching files that already have the right permissions,
# which would cause massive image explosion

# right permissions are:
# group=${NB_GID}
# AND permissions include group rwX (directory-execute)
# AND directories have setuid,setgid bits set

set -e

for d in "$@"; do
find "${d}" \
! \( \
-group "${NB_GID}" \
-a -perm -g+rwX \
\) \
-exec chgrp "${NB_GID}" -- {} \+ \
-exec chmod g+rwX -- {} \+
# setuid, setgid *on directories only*
find "${d}" \
\( \
-type d \
-a ! -perm -6000 \
\) \
-exec chmod +6000 -- {} \+
done
60 changes: 60 additions & 0 deletions base/jupyter_server_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
# mypy: ignore-errors

import os
import stat
import subprocess

from jupyter_core.paths import jupyter_data_dir

c = get_config() # noqa: F821
c.ServerApp.ip = "0.0.0.0"
c.ServerApp.open_browser = False

# to output both image/svg+xml and application/pdf plot formats in the notebook file
c.InlineBackend.figure_formats = {"png", "jpeg", "svg", "pdf"}

# https://github.com/jupyter/notebook/issues/3130
c.FileContentsManager.delete_to_trash = False

# Generate a self-signed certificate
OPENSSL_CONFIG = """\
[req]
distinguished_name = req_distinguished_name
[req_distinguished_name]
"""
if "GEN_CERT" in os.environ:
dir_name = jupyter_data_dir()
pem_file = os.path.join(dir_name, "notebook.pem")
os.makedirs(dir_name, exist_ok=True)

# Generate an openssl.cnf file to set the distinguished name
cnf_file = os.path.join(os.getenv("CONDA_DIR", "/usr/lib"), "ssl", "openssl.cnf")
if not os.path.isfile(cnf_file):
with open(cnf_file, "w") as fh:
fh.write(OPENSSL_CONFIG)

# Generate a certificate if one doesn't exist on disk
subprocess.check_call(
[
"openssl",
"req",
"-new",
"-newkey=rsa:2048",
"-days=365",
"-nodes",
"-x509",
"-subj=/C=XX/ST=XX/L=XX/O=generated/CN=generated",
f"-keyout={pem_file}",
f"-out={pem_file}",
]
)
# Restrict access to the file
os.chmod(pem_file, stat.S_IRUSR | stat.S_IWUSR)
c.ServerApp.certfile = pem_file

# Change default umask for all subprocesses of the notebook server if set in
# the environment
if "NB_UMASK" in os.environ:
os.umask(int(os.environ["NB_UMASK"], 8))
7 changes: 7 additions & 0 deletions base/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

set -e

docker build -f Dockerfile -t surveily.developer.ai.jupyter:test .
docker run --rm -it --gpus all -p 8888:8888 surveily.developer.ai.jupyter:test
# docker run --rm -it surveily.developer.ai.jupyter:test bash
20 changes: 20 additions & 0 deletions base/start-notebook.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/bash

set -e

# The Jupyter command to launch
# JupyterLab by default
DOCKER_STACKS_JUPYTER_CMD="${DOCKER_STACKS_JUPYTER_CMD:=lab}"

if [[ -n "${JUPYTERHUB_API_TOKEN}" ]]; then
echo "WARNING: using start-singleuser.sh instead of start-notebook.sh to start a server associated with JupyterHub."
exec /usr/local/bin/start-singleuser.sh "$@"
fi

wrapper=""
if [[ "${RESTARTABLE}" == "yes" ]]; then
wrapper="run-one-constantly"
fi

# shellcheck disable=SC1091,SC2086
exec /usr/local/bin/start.sh ${wrapper} python3 -m jupyter ${DOCKER_STACKS_JUPYTER_CMD} ${NOTEBOOK_ARGS} "$@"
Loading

0 comments on commit 8514c49

Please sign in to comment.