Skip to content

Commit 53ea9bb

Browse files
author
Your Name
committed
ascend-base-notebook
1 parent f5b5d0a commit 53ea9bb

12 files changed

+705
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
# Copyright (c) Jupyter Development Team.
3+
# Distributed under the terms of the Modified BSD License.
4+
5+
# This registers the initialization code for the conda shell code
6+
# It also activates default environment in the end, so we don't need to activate it manually
7+
# Documentation: https://docs.conda.io/projects/conda/en/latest/dev-guide/deep-dives/activation.html
8+
eval "$(conda shell.bash hook)"
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
ARG ROOT_CONTAINER=ubuntu:18.04
2+
3+
FROM $ROOT_CONTAINER
4+
5+
ARG NB_USER="HwHiAiUser"
6+
ARG NB_UID="1000"
7+
ARG NB_GID="1000"
8+
9+
# Fix: https://github.com/hadolint/hadolint/wiki/DL4006
10+
# Fix: https://github.com/koalaman/shellcheck/wiki/SC3014
11+
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
12+
13+
USER root
14+
15+
# Install all OS dependencies for the Server that starts
16+
# but lacks all features (e.g., download as all possible file formats)
17+
ENV DEBIAN_FRONTEND noninteractive
18+
RUN echo "deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports focal main universe" >> /etc/apt/sources.list
19+
RUN apt-get update --yes && \
20+
# - `apt-get upgrade` is run to patch known vulnerabilities in system packages
21+
# as the Ubuntu base image is rebuilt too seldom sometimes (less than once a month)
22+
apt-get upgrade --yes && \
23+
apt-get install --yes --no-install-recommends \
24+
# - bzip2 is necessary to extract the micromamba executable.
25+
bzip2 \
26+
ca-certificates \
27+
locales \
28+
sudo \
29+
# - Add necessary fonts for matplotlib/seaborn
30+
# See https://github.com/jupyter/docker-stacks/pull/380 for details
31+
fonts-liberation \
32+
# - `pandoc` is used to convert notebooks to html files
33+
# it's not present in the aarch64 Ubuntu image, so we install it here
34+
pandoc \
35+
# - `run-one` - a wrapper script that runs no more
36+
# than one unique instance of some command with a unique set of arguments,
37+
# we use `run-one-constantly` to support the `RESTARTABLE` option
38+
run-one \
39+
# - `tini` is installed as a helpful container entrypoint,
40+
# that reaps zombie processes and such of the actual executable we want to start
41+
# See https://github.com/krallin/tini#why-tini for details
42+
tini \
43+
wget && \
44+
apt-get clean && rm -rf /var/lib/apt/lists/* && \
45+
echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && \
46+
echo "C.UTF-8 UTF-8" >> /etc/locale.gen && \
47+
locale-gen
48+
49+
# Configure environment
50+
ENV CONDA_DIR=/opt/conda \
51+
SHELL=/bin/bash \
52+
NB_USER="${NB_USER}" \
53+
NB_UID=${NB_UID} \
54+
NB_GID=${NB_GID} \
55+
LC_ALL=C.UTF-8 \
56+
LANG=C.UTF-8 \
57+
LANGUAGE=C.UTF-8
58+
ENV PATH="${CONDA_DIR}/bin:${PATH}" \
59+
HOME="/home/${NB_USER}"
60+
61+
# Copy a script that we will use to correct permissions after running certain commands
62+
COPY fix-permissions /usr/local/bin/fix-permissions
63+
RUN chmod a+rx /usr/local/bin/fix-permissions
64+
65+
# Enable prompt color in the skeleton .bashrc before creating the default NB_USER
66+
# hadolint ignore=SC2016
67+
RUN sed -i 's/^#force_color_prompt=yes/force_color_prompt=yes/' /etc/skel/.bashrc && \
68+
# More information in: https://github.com/jupyter/docker-stacks/pull/2047
69+
# and docs: https://docs.conda.io/projects/conda/en/latest/dev-guide/deep-dives/activation.html
70+
echo 'eval "$(conda shell.bash hook)"' >> /etc/skel/.bashrc
71+
72+
# Create NB_USER with name jovyan user with UID=1000 and in the 'users' group
73+
# and make sure these dirs are writable by the `users` group.
74+
RUN echo "auth requisite pam_deny.so" >> /etc/pam.d/su && \
75+
sed -i.bak -e 's/^%admin/#%admin/' /etc/sudoers && \
76+
sed -i.bak -e 's/^%sudo/#%sudo/' /etc/sudoers && \
77+
useradd --no-log-init --create-home --shell /bin/bash --uid "${NB_UID}" --no-user-group "${NB_USER}" && \
78+
mkdir -p "${CONDA_DIR}" && \
79+
chown "${NB_USER}:${NB_GID}" "${CONDA_DIR}" && \
80+
chmod g+w /etc/passwd && \
81+
fix-permissions "${CONDA_DIR}" && \
82+
fix-permissions "/home/${NB_USER}"
83+
84+
USER ${NB_UID}
85+
86+
# Pin the Python version here, or set it to "default"
87+
ARG PYTHON_VERSION=3.7.5
88+
89+
# Setup work directory for backward-compatibility
90+
RUN mkdir "/home/${NB_USER}/work" && \
91+
fix-permissions "/home/${NB_USER}"
92+
93+
# Download and install Micromamba, and initialize the Conda prefix.
94+
# <https://github.com/mamba-org/mamba#micromamba>
95+
# Similar projects using Micromamba:
96+
# - Micromamba-Docker: <https://github.com/mamba-org/micromamba-docker>
97+
# - repo2docker: <https://github.com/jupyterhub/repo2docker>
98+
# Install Python, Mamba, and jupyter_core
99+
# Cleanup temporary files and remove Micromamba
100+
# Correct permissions
101+
# Do all this in a single RUN command to avoid duplicating all of the
102+
# files across image layers when the permissions change
103+
COPY --chown="${NB_UID}:${NB_GID}" initial-condarc "${CONDA_DIR}/.condarc"
104+
WORKDIR /tmp
105+
RUN set -x && \
106+
arch=$(uname -m) && \
107+
if [ "${arch}" = "x86_64" ]; then \
108+
# Should be simpler, see <https://github.com/mamba-org/mamba/issues/1437>
109+
arch="64"; \
110+
fi && \
111+
# https://mamba.readthedocs.io/en/latest/installation/micromamba-installation.html#linux-and-macos
112+
wget --progress=dot:giga -O - \
113+
"https://micro.mamba.pm/api/micromamba/linux-${arch}/latest" | tar -xvj bin/micromamba && \
114+
PYTHON_SPECIFIER="python=${PYTHON_VERSION}" && \
115+
if [[ "${PYTHON_VERSION}" == "default" ]]; then PYTHON_SPECIFIER="python"; fi && \
116+
# Install the packages
117+
./bin/micromamba install \
118+
--root-prefix="${CONDA_DIR}" \
119+
--prefix="${CONDA_DIR}" \
120+
--yes \
121+
"${PYTHON_SPECIFIER}" \
122+
'mamba' \
123+
'jupyter_core' && \
124+
rm -rf /tmp/bin/ && \
125+
# Pin major.minor version of python
126+
# https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-pkgs.html#preventing-packages-from-updating-pinning
127+
mamba list --full-name 'python' | tail -1 | tr -s ' ' | cut -d ' ' -f 1,2 | sed 's/\.[^.]*$/.*/' >> "${CONDA_DIR}/conda-meta/pinned" && \
128+
mamba install --yes \
129+
'jupyterlab' \
130+
'notebook' \
131+
'jupyterhub' \
132+
'nbclassic' && \
133+
jupyter server --generate-config && \
134+
mamba clean --all -f -y && \
135+
npm cache clean --force && \
136+
jupyter lab clean && \
137+
rm -rf "/home/${NB_USER}/.cache/yarn" && \
138+
fix-permissions "${CONDA_DIR}" && \
139+
fix-permissions "/home/${NB_USER}"
140+
141+
# Copy local files as late as possible to avoid cache busting
142+
COPY run-hooks.sh start.sh /usr/local/bin/
143+
144+
# Configure container entrypoint
145+
ENTRYPOINT ["tini", "-g", "--", "start.sh"]
146+
147+
ENV JUPYTER_PORT=8888
148+
EXPOSE $JUPYTER_PORT
149+
150+
# Configure container startup
151+
CMD ["start-notebook.py"]
152+
153+
# Copy local files as late as possible to avoid cache busting
154+
COPY start-notebook.py start-notebook.sh start-singleuser.py start-singleuser.sh /usr/local/bin/
155+
COPY jupyter_server_config.py docker_healthcheck.py /etc/jupyter/
156+
157+
USER root
158+
159+
RUN fix-permissions /etc/jupyter/
160+
161+
RUN chmod a+rx /usr/local/bin/start.sh && \
162+
chmod a+rx /usr/local/bin/run-hooks.sh
163+
164+
# Create dirs for startup hooks
165+
RUN mkdir /usr/local/bin/start-notebook.d && \
166+
mkdir /usr/local/bin/before-notebook.d
167+
168+
COPY 10activate-conda-env.sh /usr/local/bin/before-notebook.d/
169+
170+
# HEALTHCHECK documentation: https://docs.docker.com/engine/reference/builder/#healthcheck
171+
# This healtcheck works well for `lab`, `notebook`, `nbclassic`, `server`, and `retro` jupyter commands
172+
# https://github.com/jupyter/docker-stacks/issues/915#issuecomment-1068528799
173+
HEALTHCHECK --interval=3s --timeout=1s --start-period=3s --retries=3 \
174+
CMD /etc/jupyter/docker_healthcheck.py || exit 1
175+
176+
# Switch back to jovyan to avoid accidental container runs as root
177+
USER ${NB_UID}
178+
179+
WORKDIR "${HOME}"
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) Jupyter Development Team.
3+
# Distributed under the terms of the Modified BSD License.
4+
import json
5+
import os
6+
import subprocess
7+
from pathlib import Path
8+
9+
import requests
10+
11+
# Several operations below deliberately don't check for possible errors
12+
# As this is a health check, it should succeed or raise an exception on error
13+
14+
# Docker runs health checks using an exec
15+
# It uses the default user configured when running the image: root for the case of a custom NB_USER or jovyan for the case of the default image user.
16+
# We manually change HOME to make `jupyter --runtime-dir` report a correct path
17+
# More information: <https://github.com/jupyter/docker-stacks/pull/2074#issuecomment-1879778409>
18+
result = subprocess.run(
19+
["jupyter", "--runtime-dir"],
20+
check=True,
21+
capture_output=True,
22+
text=True,
23+
env=dict(os.environ) | {"HOME": "/home/" + os.environ["NB_USER"]},
24+
)
25+
runtime_dir = Path(result.stdout.rstrip())
26+
27+
json_file = next(runtime_dir.glob("*server-*.json"))
28+
29+
url = json.loads(json_file.read_bytes())["url"]
30+
url = url + "api"
31+
32+
proxies = {
33+
"http": "",
34+
"https": "",
35+
}
36+
37+
r = requests.get(url, proxies=proxies, verify=False) # request without SSL verification
38+
r.raise_for_status()
39+
print(r.content)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/bin/bash
2+
# Set permissions on a directory
3+
# After any installation, if a directory needs to be (human) user-writable, run this script on it.
4+
# It will make everything in the directory owned by the group ${NB_GID} and writable by that group.
5+
# Deployments that want to set a specific user id can preserve permissions
6+
# by adding the `--group-add users` line to `docker run`.
7+
8+
# Uses find to avoid touching files that already have the right permissions,
9+
# which would cause a massive image explosion
10+
11+
# Right permissions are:
12+
# group=${NB_GID}
13+
# AND permissions include group rwX (directory-execute)
14+
# AND directories have setuid,setgid bits set
15+
16+
set -e
17+
18+
for d in "$@"; do
19+
find "${d}" \
20+
! \( \
21+
-group "${NB_GID}" \
22+
-a -perm -g+rwX \
23+
\) \
24+
-exec chgrp "${NB_GID}" -- {} \+ \
25+
-exec chmod g+rwX -- {} \+
26+
# setuid, setgid *on directories only*
27+
find "${d}" \
28+
\( \
29+
-type d \
30+
-a ! -perm -6000 \
31+
\) \
32+
-exec chmod +6000 -- {} \+
33+
done
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Conda configuration see https://conda.io/projects/conda/en/latest/configuration.html
2+
3+
auto_update_conda: false
4+
show_channel_urls: true
5+
channels:
6+
- conda-forge
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Copyright (c) Jupyter Development Team.
2+
# Distributed under the terms of the Modified BSD License.
3+
# mypy: ignore-errors
4+
import os
5+
import stat
6+
import subprocess
7+
from pathlib import Path
8+
9+
from jupyter_core.paths import jupyter_data_dir
10+
11+
c = get_config() # noqa: F821
12+
c.ServerApp.ip = "0.0.0.0"
13+
c.ServerApp.open_browser = False
14+
15+
# to output both image/svg+xml and application/pdf plot formats in the notebook file
16+
c.InlineBackend.figure_formats = {"png", "jpeg", "svg", "pdf"}
17+
18+
# https://github.com/jupyter/notebook/issues/3130
19+
c.FileContentsManager.delete_to_trash = False
20+
21+
# Generate a self-signed certificate
22+
OPENSSL_CONFIG = """\
23+
[req]
24+
distinguished_name = req_distinguished_name
25+
[req_distinguished_name]
26+
"""
27+
if "GEN_CERT" in os.environ:
28+
dir_name = Path(jupyter_data_dir())
29+
dir_name.mkdir(parents=True, exist_ok=True)
30+
pem_file = dir_name / "notebook.pem"
31+
32+
# Generate an openssl.cnf file to set the distinguished name
33+
cnf_file = Path(os.getenv("CONDA_DIR", "/usr/lib")) / "ssl/openssl.cnf"
34+
if not cnf_file.exists():
35+
cnf_file.write_text(OPENSSL_CONFIG)
36+
37+
# Generate a certificate if one doesn't exist on a disk
38+
subprocess.check_call(
39+
[
40+
"openssl",
41+
"req",
42+
"-new",
43+
"-newkey=rsa:2048",
44+
"-days=365",
45+
"-nodes",
46+
"-x509",
47+
"-subj=/C=XX/ST=XX/L=XX/O=generated/CN=generated",
48+
f"-keyout={pem_file}",
49+
f"-out={pem_file}",
50+
]
51+
)
52+
# Restrict access to the file
53+
pem_file.chmod(stat.S_IRUSR | stat.S_IWUSR)
54+
c.ServerApp.certfile = str(pem_file)
55+
56+
# Change default umask for all subprocesses of the Server if set in the environment
57+
if "NB_UMASK" in os.environ:
58+
os.umask(int(os.environ["NB_UMASK"], 8))
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/bin/bash
2+
# Copyright (c) Jupyter Development Team.
3+
# Distributed under the terms of the Modified BSD License.
4+
5+
# The run-hooks.sh script looks for *.sh scripts to source
6+
# and executable files to run within a passed directory
7+
8+
if [ "$#" -ne 1 ]; then
9+
echo "Should pass exactly one directory"
10+
return 1
11+
fi
12+
13+
if [[ ! -d "${1}" ]]; then
14+
echo "Directory ${1} doesn't exist or is not a directory"
15+
return 1
16+
fi
17+
18+
echo "Running hooks in: ${1} as uid: $(id -u) gid: $(id -g)"
19+
for f in "${1}/"*; do
20+
# Handling a case when the directory is empty
21+
[ -e "${f}" ] || continue
22+
case "${f}" in
23+
*.sh)
24+
echo "Sourcing shell script: ${f}"
25+
# shellcheck disable=SC1090
26+
source "${f}"
27+
# shellcheck disable=SC2181
28+
if [ $? -ne 0 ]; then
29+
echo "${f} has failed, continuing execution"
30+
fi
31+
;;
32+
*)
33+
if [ -x "${f}" ]; then
34+
echo "Running executable: ${f}"
35+
"${f}"
36+
# shellcheck disable=SC2181
37+
if [ $? -ne 0 ]; then
38+
echo "${f} has failed, continuing execution"
39+
fi
40+
else
41+
echo "Ignoring non-executable: ${f}"
42+
fi
43+
;;
44+
esac
45+
done
46+
echo "Done running hooks in: ${1}"

0 commit comments

Comments
 (0)