updated Ganymede and python images

This commit is contained in:
2024-05-25 19:36:19 +08:00
parent 2c9db69064
commit 875acc9d94
6 changed files with 205 additions and 33 deletions

View File

@@ -1,31 +1,43 @@
FROM alpine:3.19 AS build
RUN --mount=type=cache,target=/var/cache/apk/,sharing=locked \
apk update &&\
apk add python3 python3-dev pipx gcc musl-dev linux-headers
RUN adduser luser --system -s /bin/sh -h /var/lib/jupyter
USER luser
WORKDIR /var/lib/jupyter
RUN pipx install jupyter-core
RUN pipx inject jupyter-core jupyterlab
RUN pipx inject jupyter-core ipywidgets
RUN pipx inject jupyter-core jupyterlab-lsp
RUN pipx inject jupyter-core python-lsp-server[yapf,rope,pyflakes]
RUN pipx inject jupyter-core pylsp-mypy
RUN pipx inject jupyter-core matplotlib
RUN pipx inject jupyter-core numpy
apk add python3 python3-dev pipx gcc g++ musl-dev linux-headers libffi-dev
RUN adduser jovyan -u 1000 --system -s /bin/sh -h /home/jovyan
USER jovyan
WORKDIR /home/jovyan
RUN python -m venv venv
RUN venv/bin/pip install numpy
RUN venv/bin/pip install matplotlib
RUN venv/bin/pip install jupyter-core
RUN venv/bin/pip install jupyterhub
RUN venv/bin/pip install jupyterlab
RUN venv/bin/pip install notebook
RUN venv/bin/pip install ipywidgets
RUN venv/bin/pip install jupyterlab-lsp
RUN venv/bin/pip install python-lsp-server[yapf,rope,pyflakes]
RUN venv/bin/pip install pylsp-mypy
RUN venv/bin/pip install solders
RUN venv/bin/pip install solana
ENV PATH="/home/jovyan/venv/bin/:$PATH"
FROM alpine:3.19
RUN --mount=type=cache,target=/var/cache/apk/,sharing=locked \
apk update &&\
apk add python3 texlive texlive-xetex texlive-full
RUN adduser luser --system -s /bin/sh -h /var/lib/jupyter
USER luser
WORKDIR /var/lib/jupyter
COPY --from=build /var/lib/jupyter /var/lib/jupyter
ENV PATH="/var/lib/jupyter/.local/bin/:$PATH"
ENTRYPOINT ["jupyter", "lab", "--no-browser", "--ip=0.0.0.0"]
EXPOSE 8888/tcp
apk add python3
RUN adduser jovyan -u 1000 --system -s /bin/sh -h /home/jovyan
USER jovyan
COPY --from=build /home/jovyan /home/jovyan
COPY jupyter_server_config.py docker_healthcheck.py /etc/jupyter/
COPY start-notebook.py start-singleuser.py /usr/local/bin/
RUN mkdir /home/jovyan/work
WORKDIR /home/jovyan/work
ENV JUPYTER_PORT=8888
EXPOSE $JUPYTER_PORT
ENV PATH="/home/jovyan/venv/bin/:$PATH"
CMD ["start-notebook.py"]
# 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=3s --timeout=1s --start-period=3s --retries=3 \
CMD /etc/jupyter/docker_healthcheck.py || exit 1

View File

@@ -0,0 +1,39 @@
#!/usr/bin/env python3
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
import json
import os
import subprocess
from pathlib import Path
import requests
# Several operations below deliberately don't check for possible errors
# As this is a health check, it should succeed or raise an exception on error
# Docker runs health checks using an exec
# 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.
# We manually change HOME to make `jupyter --runtime-dir` report a correct path
# More information: <https://github.com/jupyter/docker-stacks/pull/2074#issuecomment-1879778409>
result = subprocess.run(
["jupyter", "--runtime-dir"],
check=True,
capture_output=True,
text=True,
env=dict(os.environ) | {"HOME": "/home/" + os.environ["NB_USER"]},
)
runtime_dir = Path(result.stdout.rstrip())
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)

View 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))

View File

@@ -0,0 +1,44 @@
#!/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)
# Entrypoint is start.sh
command = []
# If we want to survive restarts, launch the command using `run-one-constantly`
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!
print("Executing: " + " ".join(command))
os.execvp(command[0], command)

View File

@@ -0,0 +1,26 @@
#!/usr/bin/env python
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
import os
import shlex
import sys
# Entrypoint is start.sh
command = ["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!
print("Executing: " + " ".join(command))
os.execvp(command[0], command)