init
This commit is contained in:
75
spawnerdockerfile/Dockerfile
Normal file
75
spawnerdockerfile/Dockerfile
Normal file
@@ -0,0 +1,75 @@
|
||||
# Copyright (c) Jupyter Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
ARG REGISTRY=quay.io
|
||||
ARG OWNER=jupyter
|
||||
ARG BASE_CONTAINER=$REGISTRY/$OWNER/docker-stacks-foundation
|
||||
FROM $BASE_CONTAINER
|
||||
|
||||
LABEL maintainer="Jupyter Project <jupyter@googlegroups.com>"
|
||||
|
||||
# Fix: https://github.com/hadolint/hadolint/wiki/DL4006
|
||||
# Fix: https://github.com/koalaman/shellcheck/wiki/SC3014
|
||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
|
||||
USER root
|
||||
|
||||
# Install all OS dependencies for the Server that starts but lacks all
|
||||
# features (e.g., download as all possible file formats)
|
||||
RUN apt-get update --yes && \
|
||||
apt-get install --yes --no-install-recommends \
|
||||
fonts-liberation \
|
||||
# - pandoc is used to convert notebooks to html files
|
||||
# it's not present in the aarch64 Ubuntu image, so we install it here
|
||||
pandoc \
|
||||
# - run-one - a wrapper script that runs no more
|
||||
# than one unique instance of some command with a unique set of arguments,
|
||||
# we use `run-one-constantly` to support the `RESTARTABLE` option
|
||||
run-one && \
|
||||
apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
USER ${NB_UID}
|
||||
|
||||
# Install JupyterLab, Jupyter Notebook, JupyterHub and NBClassic
|
||||
# Generate a Jupyter Server config
|
||||
# Cleanup temporary files
|
||||
# Correct permissions
|
||||
# Do all this in a single RUN command to avoid duplicating all of the
|
||||
# files across image layers when the permissions change
|
||||
WORKDIR /tmp
|
||||
RUN mamba install --yes \
|
||||
'jupyterlab' \
|
||||
'notebook' \
|
||||
'jupyterhub' \
|
||||
'nbclassic' && \
|
||||
jupyter server --generate-config && \
|
||||
mamba clean --all -f -y && \
|
||||
npm cache clean --force && \
|
||||
jupyter lab clean && \
|
||||
rm -rf "/home/${NB_USER}/.cache/yarn" && \
|
||||
fix-permissions "${CONDA_DIR}" && \
|
||||
fix-permissions "/home/${NB_USER}"
|
||||
|
||||
ENV JUPYTER_PORT=8888
|
||||
EXPOSE $JUPYTER_PORT
|
||||
|
||||
# Configure container startup
|
||||
CMD ["start-notebook.py"]
|
||||
|
||||
# Copy local files as late as possible to avoid cache busting
|
||||
COPY start-notebook.py start-notebook.sh start-singleuser.py start-singleuser.sh /usr/local/bin/
|
||||
COPY jupyter_server_config.py docker_healthcheck.py /etc/jupyter/
|
||||
|
||||
# Fix permissions on /etc/jupyter as root
|
||||
USER root
|
||||
RUN fix-permissions /etc/jupyter/
|
||||
|
||||
# HEALTHCHECK documentation: https://docs.docker.com/engine/reference/builder/#healthcheck
|
||||
# This healtcheck works well for `lab`, `notebook`, `nbclassic`, `server`, and `retro` jupyter commands
|
||||
# https://github.com/jupyter/docker-stacks/issues/915#issuecomment-1068528799
|
||||
HEALTHCHECK --interval=5s --timeout=3s --start-period=5s --retries=3 \
|
||||
CMD /etc/jupyter/docker_healthcheck.py || exit 1
|
||||
|
||||
# Switch back to jovyan to avoid accidental container runs as root
|
||||
USER ${NB_UID}
|
||||
|
||||
WORKDIR "${HOME}"
|
||||
141
spawnerdockerfile/Dockerfile.base-notebook
Normal file
141
spawnerdockerfile/Dockerfile.base-notebook
Normal file
@@ -0,0 +1,141 @@
|
||||
# Copyright (c) Jupyter Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
# https://github.com/jupyter/docker-stacks/blob/main/images/base-notebook/Dockerfile
|
||||
ARG REGISTRY=quay.io
|
||||
ARG OWNER=jupyter
|
||||
ARG BASE_CONTAINER=$REGISTRY/$OWNER/docker-stacks-foundation
|
||||
FROM $BASE_CONTAINER
|
||||
|
||||
LABEL maintainer="Jupyter Project <jupyter@googlegroups.com>"
|
||||
|
||||
# Fix: https://github.com/hadolint/hadolint/wiki/DL4006
|
||||
# Fix: https://github.com/koalaman/shellcheck/wiki/SC3014
|
||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
|
||||
USER root
|
||||
|
||||
# Install all OS dependencies for the Server that starts but lacks all
|
||||
# features (e.g., download as all possible file formats)
|
||||
RUN apt-get update --yes && \
|
||||
apt-get install --yes --no-install-recommends \
|
||||
fonts-liberation \
|
||||
# - pandoc is used to convert notebooks to html files
|
||||
# it's not present in the aarch64 Ubuntu image, so we install it here
|
||||
pandoc \
|
||||
# - run-one - a wrapper script that runs no more
|
||||
# than one unique instance of some command with a unique set of arguments,
|
||||
# we use `run-one-constantly` to support the `RESTARTABLE` option
|
||||
run-one && \
|
||||
apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
USER ${NB_UID}
|
||||
|
||||
# Install JupyterLab, Jupyter Notebook, JupyterHub and NBClassic
|
||||
# Generate a Jupyter Server config
|
||||
# Cleanup temporary files
|
||||
# Correct permissions
|
||||
# Do all this in a single RUN command to avoid duplicating all of the
|
||||
# files across image layers when the permissions change
|
||||
WORKDIR /tmp
|
||||
RUN mamba install --yes \
|
||||
'jupyterlab' \
|
||||
'notebook' \
|
||||
'jupyterhub' \
|
||||
'nbclassic' && \
|
||||
jupyter server --generate-config && \
|
||||
mamba clean --all -f -y && \
|
||||
npm cache clean --force && \
|
||||
jupyter lab clean && \
|
||||
rm -rf "/home/${NB_USER}/.cache/yarn" && \
|
||||
fix-permissions "${CONDA_DIR}" && \
|
||||
fix-permissions "/home/${NB_USER}"
|
||||
|
||||
ENV JUPYTER_PORT=8888
|
||||
EXPOSE $JUPYTER_PORT
|
||||
|
||||
# Configure container startup
|
||||
CMD ["start-notebook.py"]
|
||||
|
||||
# Copy local files as late as possible to avoid cache busting
|
||||
COPY start-notebook.py start-notebook.sh start-singleuser.py start-singleuser.sh /usr/local/bin/
|
||||
COPY jupyter_server_config.py docker_healthcheck.py /etc/jupyter/
|
||||
|
||||
# Fix permissions on /etc/jupyter as root
|
||||
USER root
|
||||
RUN fix-permissions /etc/jupyter/
|
||||
|
||||
# HEALTHCHECK documentation: https://docs.docker.com/engine/reference/builder/#healthcheck
|
||||
# This healtcheck works well for `lab`, `notebook`, `nbclassic`, `server`, and `retro` jupyter commands
|
||||
# https://github.com/jupyter/docker-stacks/issues/915#issuecomment-1068528799
|
||||
HEALTHCHECK --interval=5s --timeout=3s --start-period=5s --retries=3 \
|
||||
CMD /etc/jupyter/docker_healthcheck.py || exit 1
|
||||
|
||||
# here add
|
||||
ARG CREATE_USER="jovyan"
|
||||
ARG CREATE_USER_PASSWD="password"
|
||||
ARG ROOT_PASSWD="password"
|
||||
ARG HOME="/home/${CREATE_USER}"
|
||||
ARG DEBIAN_FRONTEND="noninteractive"
|
||||
ENV DEBIAN_FRONTEND=${DEBIAN_FRONTEND}
|
||||
|
||||
RUN <<EOT
|
||||
#!/bin/bash
|
||||
# 更新软件源
|
||||
apt-get update
|
||||
# 安装时区数据包并设置时区
|
||||
apt-get install -y tzdata
|
||||
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
||||
echo 'Asia/Shanghai' > /etc/timezone
|
||||
dpkg-reconfigure -f noninteractive tzdata
|
||||
# 安装所需的软件包
|
||||
apt-get install -y python3 python3-pip gcc g++ build-essential nodejs npm gdebi-core curl wget openssh-server vim lrzsz net-tools sudo git
|
||||
# 创建新用户
|
||||
useradd -m -s /bin/bash ${CREATE_USER}
|
||||
echo "${CREATE_USER}:${CREATE_USER_PASSWD}" | chpasswd
|
||||
echo "${CREATE_USER} ALL=(ALL:ALL) NOPASSWD:ALL" >> /etc/sudoers
|
||||
EOT
|
||||
|
||||
# jupyter-nbextension enable nglview --py --sys-prefix
|
||||
# jupyter nbextension enable --py --sys-prefix widgetsnbextension
|
||||
|
||||
# conda install Rstudio
|
||||
RUN <<EOT
|
||||
#!/bin/bash
|
||||
apt update -qq
|
||||
apt install -y --no-install-recommends software-properties-common dirmngr
|
||||
wget -qO- https://cloud.r-project.org/bin/linux/ubuntu/marutter_pubkey.asc | sudo tee -a /etc/apt/trusted.gpg.d/cran_ubuntu_key.asc
|
||||
sudo add-apt-repository "deb https://cloud.r-project.org/bin/linux/ubuntu $(lsb_release -cs)-cran40/"
|
||||
apt-get update
|
||||
apt install --no-install-recommends r-base
|
||||
sudo wget "https://download2.rstudio.org/server/$(lsb_release -cs)/amd64/rstudio-server-2023.06.1-524-amd64.deb" -O /tmp/rstudio-server.deb
|
||||
sudo chmod +x /tmp/rstudio-server.deb
|
||||
sudo gdebi -n /tmp/rstudio-server.deb
|
||||
sudo rm -rf /tmp/rstudio-server.deb
|
||||
EOT
|
||||
|
||||
RUN <<EOT
|
||||
#!/bin/bash
|
||||
# 安装micromamba
|
||||
echo "1" | bash <(curl -s https://raw.githubusercontent.com/hotwa/MicroMamba_Installer/main/install.sh)
|
||||
EOT
|
||||
|
||||
RUN <<EOT
|
||||
#!/bin/bash
|
||||
# 安装 Jupyter 和相关软件
|
||||
npm install -g configurable-http-proxy
|
||||
python3 -m pip install jupyterhub jupyterlab notebook radian pycurl jupyter-rsession-proxy ipykernel jupyterlab-language-pack-zh-CN jupyterlab-git jupyterlab-system-monitor jupyter_nbextensions_configurator jupyter_contrib_nbextensions jupyterlab_widgets jupyterlab-drawio jupyterlab-spreadsheet-editor jupyterlab-cell-flash jedi-language-server jupyterlab_code_formatter jupyterlab-spellchecker jupyterlab_vim nbresuse ipydrawio jedi ipympl black isort theme-darcula ipywidgets tensorboard jupyterlab_latex jupyter_bokeh autopep8 xeus-python jupyterlab-lsp python-lsp-server nglview dockerspawner jupyterhub-nativeauthenticator lckr_jupyterlab_variableinspector
|
||||
EOT
|
||||
|
||||
RUN <<EOT
|
||||
#!/bin/bash
|
||||
# 清理和减小镜像大小
|
||||
apt-get clean
|
||||
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/man/?? /usr/share/man/??_*
|
||||
EOT
|
||||
|
||||
|
||||
|
||||
# Switch back to jovyan to avoid accidental container runs as root
|
||||
USER ${NB_UID}
|
||||
|
||||
WORKDIR "${HOME}"
|
||||
23
spawnerdockerfile/README.md
Normal file
23
spawnerdockerfile/README.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Base Jupyter Notebook Stack
|
||||
|
||||
> **Images hosted on Docker Hub are no longer updated. Please, use [quay.io image](https://quay.io/repository/jupyter/base-notebook)**
|
||||
|
||||
[](https://hub.docker.com/r/jupyter/base-notebook/)
|
||||
[](https://hub.docker.com/r/jupyter/base-notebook/)
|
||||
[](https://hub.docker.com/r/jupyter/base-notebook/ "jupyter/base-notebook image size")
|
||||
|
||||
GitHub Actions in the <https://github.com/jupyter/docker-stacks> project builds and pushes this image to the Registry.
|
||||
|
||||
Please visit the project documentation site for help to use and contribute to this image and others.
|
||||
|
||||
- [Jupyter Docker Stacks on ReadTheDocs](https://jupyter-docker-stacks.readthedocs.io/en/latest/index.html)
|
||||
- [Selecting an Image :: Core Stacks :: jupyter/base-notebook](https://jupyter-docker-stacks.readthedocs.io/en/latest/using/selecting.html#jupyter-base-notebook)
|
||||
|
||||
# 构建docker-compose spawner镜像的Dockerfile
|
||||
|
||||
构建基[础镜像参考](https://github.com/jupyter/docker-stacks)
|
||||
|
||||
```shell
|
||||
cp docker-stacks/images/base-notebook/* ./spawnerdockerfile/
|
||||
docker buildx build -t hotwa/notebook:latest . -f Dockerfile.base-notebook --load
|
||||
```
|
||||
26
spawnerdockerfile/docker_healthcheck.py
Executable file
26
spawnerdockerfile/docker_healthcheck.py
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) Jupyter Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
import requests
|
||||
|
||||
# Several operations below deliberately don't check for possible errors
|
||||
# As this is a healthcheck, it should succeed or raise an exception on error
|
||||
|
||||
runtime_dir = Path("/home/") / os.environ["NB_USER"] / ".local/share/jupyter/runtime/"
|
||||
json_file = next(runtime_dir.glob("*server-*.json"))
|
||||
|
||||
url = json.loads(json_file.read_bytes())["url"]
|
||||
url = url + "api"
|
||||
|
||||
proxies = {
|
||||
"http": "",
|
||||
"https": "",
|
||||
}
|
||||
|
||||
r = requests.get(url, proxies=proxies, verify=False) # request without SSL verification
|
||||
r.raise_for_status()
|
||||
print(r.content)
|
||||
58
spawnerdockerfile/jupyter_server_config.py
Normal file
58
spawnerdockerfile/jupyter_server_config.py
Normal file
@@ -0,0 +1,58 @@
|
||||
# Copyright (c) Jupyter Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
# mypy: ignore-errors
|
||||
import os
|
||||
import stat
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
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 = Path(jupyter_data_dir())
|
||||
dir_name.mkdir(parents=True, exist_ok=True)
|
||||
pem_file = dir_name / "notebook.pem"
|
||||
|
||||
# Generate an openssl.cnf file to set the distinguished name
|
||||
cnf_file = Path(os.getenv("CONDA_DIR", "/usr/lib")) / "ssl/openssl.cnf"
|
||||
if not cnf_file.exists():
|
||||
cnf_file.write_text(OPENSSL_CONFIG)
|
||||
|
||||
# Generate a certificate if one doesn't exist on a 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
|
||||
pem_file.chmod(stat.S_IRUSR | stat.S_IWUSR)
|
||||
c.ServerApp.certfile = str(pem_file)
|
||||
|
||||
# Change default umask for all subprocesses of the Server if set in the environment
|
||||
if "NB_UMASK" in os.environ:
|
||||
os.umask(int(os.environ["NB_UMASK"], 8))
|
||||
41
spawnerdockerfile/start-notebook.py
Executable file
41
spawnerdockerfile/start-notebook.py
Executable file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) Jupyter Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
import os
|
||||
import shlex
|
||||
import sys
|
||||
|
||||
# If we are in a JupyterHub, we pass on to `start-singleuser.py` instead so it does the right thing
|
||||
if "JUPYTERHUB_API_TOKEN" in os.environ:
|
||||
print(
|
||||
"WARNING: using start-singleuser.py instead of start-notebook.py to start a server associated with JupyterHub."
|
||||
)
|
||||
command = ["/usr/local/bin/start-singleuser.py"] + sys.argv[1:]
|
||||
os.execvp(command[0], command)
|
||||
|
||||
|
||||
# Wrap everything in start.sh, no matter what
|
||||
command = ["/usr/local/bin/start.sh"]
|
||||
|
||||
# If we want to survive restarts, tell that to start.sh
|
||||
if os.environ.get("RESTARTABLE") == "yes":
|
||||
command.append("run-one-constantly")
|
||||
|
||||
# We always launch a jupyter subcommand from this script
|
||||
command.append("jupyter")
|
||||
|
||||
# Launch the configured subcommand. Note that this should be a single string, so we don't split it
|
||||
# We default to lab
|
||||
jupyter_command = os.environ.get("DOCKER_STACKS_JUPYTER_CMD", "lab")
|
||||
command.append(jupyter_command)
|
||||
|
||||
# Append any optional NOTEBOOK_ARGS we were passed in. This is supposed to be multiple args passed
|
||||
# on to the notebook command, so we split it correctly with shlex
|
||||
if "NOTEBOOK_ARGS" in os.environ:
|
||||
command += shlex.split(os.environ["NOTEBOOK_ARGS"])
|
||||
|
||||
# Pass through any other args we were passed on the command line
|
||||
command += sys.argv[1:]
|
||||
|
||||
# Execute the command!
|
||||
os.execvp(command[0], command)
|
||||
5
spawnerdockerfile/start-notebook.sh
Executable file
5
spawnerdockerfile/start-notebook.sh
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
# Shim to emit warning and call start-notebook.py
|
||||
echo "WARNING: Use start-notebook.py instead"
|
||||
|
||||
exec /usr/local/bin/start-notebook.py "$@"
|
||||
23
spawnerdockerfile/start-singleuser.py
Executable file
23
spawnerdockerfile/start-singleuser.py
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) Jupyter Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
import os
|
||||
import shlex
|
||||
import sys
|
||||
|
||||
command = ["/usr/local/bin/start.sh", "jupyterhub-singleuser"]
|
||||
|
||||
# set default ip to 0.0.0.0
|
||||
if "--ip=" not in os.environ.get("NOTEBOOK_ARGS", ""):
|
||||
command.append("--ip=0.0.0.0")
|
||||
|
||||
# Append any optional NOTEBOOK_ARGS we were passed in. This is supposed to be multiple args passed
|
||||
# on to the notebook command, so we split it correctly with shlex
|
||||
if "NOTEBOOK_ARGS" in os.environ:
|
||||
command += shlex.split(os.environ["NOTEBOOK_ARGS"])
|
||||
|
||||
# Pass any other args we have been passed through
|
||||
command += sys.argv[1:]
|
||||
|
||||
# Execute the command!
|
||||
os.execvp(command[0], command)
|
||||
5
spawnerdockerfile/start-singleuser.sh
Executable file
5
spawnerdockerfile/start-singleuser.sh
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
# Shim to emit warning and call start-singleuser.py
|
||||
echo "WARNING: Use start-singleuser.py instead"
|
||||
|
||||
exec /usr/local/bin/start-singleuser.py "$@"
|
||||
Reference in New Issue
Block a user