| 
 | 1 | +ARG BASE_IMAGE=debian  | 
 | 2 | +ARG BASE_IMAGE_TAG=12  | 
 | 3 | +ARG BUILD_ON_IMAGE=glcr.b-data.ch/python/ver  | 
 | 4 | +ARG PYTHON_VERSION=3.13.6  | 
 | 5 | +ARG CUDA_IMAGE_FLAVOR  | 
 | 6 | + | 
 | 7 | +ARG NB_USER=jovyan  | 
 | 8 | +ARG NB_UID=1000  | 
 | 9 | +ARG JUPYTERHUB_VERSION=5.3.0  | 
 | 10 | +ARG JUPYTERLAB_VERSION=4.4.5  | 
 | 11 | +ARG CODE_BUILTIN_EXTENSIONS_DIR=/opt/code-server/lib/vscode/extensions  | 
 | 12 | +ARG CODE_SERVER_VERSION=4.103.0  | 
 | 13 | +ARG NEOVIM_VERSION=0.11.3  | 
 | 14 | +ARG GIT_VERSION=2.50.1  | 
 | 15 | +ARG GIT_LFS_VERSION=3.7.0  | 
 | 16 | +ARG PANDOC_VERSION=3.6.3  | 
 | 17 | + | 
 | 18 | +FROM ${BUILD_ON_IMAGE}${PYTHON_VERSION:+:}${PYTHON_VERSION}${CUDA_IMAGE_FLAVOR:+-}${CUDA_IMAGE_FLAVOR} AS files  | 
 | 19 | + | 
 | 20 | +ARG NB_UID  | 
 | 21 | +ENV NB_GID=100  | 
 | 22 | + | 
 | 23 | +RUN mkdir /files  | 
 | 24 | + | 
 | 25 | +COPY assets /files  | 
 | 26 | +COPY conf/ipython /files  | 
 | 27 | +COPY conf/jupyter /files  | 
 | 28 | +COPY conf/jupyterlab /files  | 
 | 29 | +COPY conf/shell /files  | 
 | 30 | +COPY conf${CUDA_IMAGE:+/cuda}/shell /files  | 
 | 31 | +COPY conf/user /files  | 
 | 32 | +COPY scripts /files  | 
 | 33 | + | 
 | 34 | + ## Copy content of skel directory to backup  | 
 | 35 | +RUN cp -a /files/etc/skel/. /files/var/backups/skel \  | 
 | 36 | + && chown -R ${NB_UID}:${NB_GID} /files/var/backups/skel \  | 
 | 37 | + ## Copy custom fonts  | 
 | 38 | + && mkdir -p /files/usr/local/share/jupyter/lab/static/assets \  | 
 | 39 | + && cp -a /files/opt/code-server/src/browser/media/css \  | 
 | 40 | + /files/usr/local/share/jupyter/lab/static/assets \  | 
 | 41 | + && cp -a /files/opt/code-server/src/browser/media/fonts \  | 
 | 42 | + /files/usr/local/share/jupyter/lab/static/assets \  | 
 | 43 | + && if [ -n "${CUDA_VERSION}" ]; then \  | 
 | 44 | + ## Use entrypoint of CUDA image  | 
 | 45 | + mv /opt/nvidia/entrypoint.d /opt/nvidia/nvidia_entrypoint.sh \  | 
 | 46 | + /files/usr/local/bin; \  | 
 | 47 | + mv /files/usr/local/bin/start.sh \  | 
 | 48 | + /files/usr/local/bin/entrypoint.d/99-start.sh; \  | 
 | 49 | + mv /files/usr/local/bin/nvidia_entrypoint.sh \  | 
 | 50 | + /files/usr/local/bin/start.sh; \  | 
 | 51 | + fi \  | 
 | 52 | + ## Ensure file modes are correct when using CI  | 
 | 53 | + ## Otherwise set to 777 in the target image  | 
 | 54 | + && find /files -type d -exec chmod 755 {} \; \  | 
 | 55 | + && find /files -type f -exec chmod 644 {} \; \  | 
 | 56 | + && find /files/usr/local/bin -type f -exec chmod 755 {} \; \  | 
 | 57 | + && find /files/etc/profile.d -type f -exec chmod 755 {} \;  | 
 | 58 | + | 
 | 59 | +FROM glcr.b-data.ch/neovim/nvsi:${NEOVIM_VERSION} AS nvsi  | 
 | 60 | +FROM glcr.b-data.ch/git/gsi/${GIT_VERSION}/${BASE_IMAGE}:${BASE_IMAGE_TAG} AS gsi  | 
 | 61 | +FROM glcr.b-data.ch/git-lfs/glfsi:${GIT_LFS_VERSION} AS glfsi  | 
 | 62 | + | 
 | 63 | +FROM ${BUILD_ON_IMAGE}${PYTHON_VERSION:+:}${PYTHON_VERSION}${CUDA_IMAGE_FLAVOR:+-}${CUDA_IMAGE_FLAVOR}  | 
 | 64 | + | 
 | 65 | +ARG DEBIAN_FRONTEND=noninteractive  | 
 | 66 | + | 
 | 67 | +ARG BUILD_ON_IMAGE  | 
 | 68 | +ARG CUDA_IMAGE_FLAVOR  | 
 | 69 | +ARG NB_USER  | 
 | 70 | +ARG NB_UID  | 
 | 71 | +ARG JUPYTERHUB_VERSION  | 
 | 72 | +ARG JUPYTERLAB_VERSION  | 
 | 73 | +ARG CODE_BUILTIN_EXTENSIONS_DIR  | 
 | 74 | +ARG CODE_SERVER_VERSION  | 
 | 75 | +ARG NEOVIM_VERSION  | 
 | 76 | +ARG GIT_VERSION  | 
 | 77 | +ARG GIT_LFS_VERSION  | 
 | 78 | +ARG PANDOC_VERSION  | 
 | 79 | +ARG BUILD_START  | 
 | 80 | + | 
 | 81 | +ARG CODE_WORKDIR  | 
 | 82 | + | 
 | 83 | +ARG CUDA_IMAGE_LICENSE=${CUDA_VERSION:+"NVIDIA Deep Learning Container License"}  | 
 | 84 | +ARG IMAGE_LICENSE=${CUDA_IMAGE_LICENSE:-"MIT"}  | 
 | 85 | +ARG IMAGE_SOURCE=https://gitlab.b-data.ch/jupyterlab/python/docker-stack  | 
 | 86 | +ARG IMAGE_VENDOR="b-data GmbH"  | 
 | 87 | +ARG IMAGE_AUTHORS="Olivier Benz <olivier.benz@b-data.ch>"  | 
 | 88 | + | 
 | 89 | +LABEL org.opencontainers.image.licenses="$IMAGE_LICENSE" \  | 
 | 90 | + org.opencontainers.image.source="$IMAGE_SOURCE" \  | 
 | 91 | + org.opencontainers.image.vendor="$IMAGE_VENDOR" \  | 
 | 92 | + org.opencontainers.image.authors="$IMAGE_AUTHORS"  | 
 | 93 | + | 
 | 94 | +ENV PARENT_IMAGE=${BUILD_ON_IMAGE}${PYTHON_VERSION:+:}${PYTHON_VERSION}${CUDA_IMAGE_FLAVOR:+-}${CUDA_IMAGE_FLAVOR} \  | 
 | 95 | + NB_USER=${NB_USER} \  | 
 | 96 | + NB_UID=${NB_UID} \  | 
 | 97 | + JUPYTERHUB_VERSION=${JUPYTERHUB_VERSION} \  | 
 | 98 | + JUPYTERLAB_VERSION=${JUPYTERLAB_VERSION} \  | 
 | 99 | + CODE_SERVER_VERSION=${CODE_SERVER_VERSION} \  | 
 | 100 | + NEOVIM_VERSION=${NEOVIM_VERSION} \  | 
 | 101 | + GIT_VERSION=${GIT_VERSION} \  | 
 | 102 | + GIT_LFS_VERSION=${GIT_LFS_VERSION} \  | 
 | 103 | + PANDOC_VERSION=${PANDOC_VERSION} \  | 
 | 104 | + BUILD_DATE=${BUILD_START}  | 
 | 105 | + | 
 | 106 | +ENV NB_GID=100  | 
 | 107 | + | 
 | 108 | +## Install Neovim  | 
 | 109 | +COPY --from=nvsi /usr/local /usr/local  | 
 | 110 | +## Install Git  | 
 | 111 | +COPY --from=gsi /usr/local /usr/local  | 
 | 112 | +## Install Git LFS  | 
 | 113 | +COPY --from=glfsi /usr/local /usr/local  | 
 | 114 | + | 
 | 115 | +USER root  | 
 | 116 | + | 
 | 117 | +RUN dpkgArch="$(dpkg --print-architecture)" \  | 
 | 118 | + ## Unminimise if the system has been minimised  | 
 | 119 | + && if [ $(command -v unminimize) ]; then \  | 
 | 120 | + yes | unminimize; \  | 
 | 121 | + fi \  | 
 | 122 | + && apt-get update \  | 
 | 123 | + && apt-get -y install --no-install-recommends \  | 
 | 124 | + bash-completion \  | 
 | 125 | + build-essential \  | 
 | 126 | + curl \  | 
 | 127 | + file \  | 
 | 128 | + fontconfig \  | 
 | 129 | + g++ \  | 
 | 130 | + gcc \  | 
 | 131 | + gfortran \  | 
 | 132 | + gnupg \  | 
 | 133 | + htop \  | 
 | 134 | + info \  | 
 | 135 | + jq \  | 
 | 136 | + libclang-dev \  | 
 | 137 | + man-db \  | 
 | 138 | + nano \  | 
 | 139 | + ncdu \  | 
 | 140 | + procps \  | 
 | 141 | + psmisc \  | 
 | 142 | + screen \  | 
 | 143 | + sudo \  | 
 | 144 | + swig \  | 
 | 145 | + tmux \  | 
 | 146 | + vim-tiny \  | 
 | 147 | + wget \  | 
 | 148 | + zsh \  | 
 | 149 | + ## Neovim: Additional runtime recommendations  | 
 | 150 | + ripgrep \  | 
 | 151 | + ## Git: Additional runtime dependencies  | 
 | 152 | + libcurl3-gnutls \  | 
 | 153 | + liberror-perl \  | 
 | 154 | + ## Git: Additional runtime recommendations  | 
 | 155 | + less \  | 
 | 156 | + ssh-client \  | 
 | 157 | + ## Python: Additional dev dependencies  | 
 | 158 | + && if [ -z "$PYTHON_VERSION" ]; then \  | 
 | 159 | + apt-get -y install --no-install-recommends \  | 
 | 160 | + python3-dev \  | 
 | 161 | + ## Install Python package installer  | 
 | 162 | + ## (dep: python3-distutils, python3-setuptools and python3-wheel)  | 
 | 163 | + python3-pip \  | 
 | 164 | + ## Install venv module for python3  | 
 | 165 | + python3-venv; \  | 
 | 166 | + ## make some useful symlinks that are expected to exist  | 
 | 167 | + ## ("/usr/bin/python" and friends)  | 
 | 168 | + for src in pydoc3 python3 python3-config; do \  | 
 | 169 | + dst="$(echo "$src" | tr -d 3)"; \  | 
 | 170 | + if [ -s "/usr/bin/$src" ] && [ ! -e "/usr/bin/$dst" ]; then \  | 
 | 171 | + ln -svT "$src" "/usr/bin/$dst"; \  | 
 | 172 | + fi \  | 
 | 173 | + done; \  | 
 | 174 | + else \  | 
 | 175 | + ## Force update pip, setuptools and wheel  | 
 | 176 | + pip install --upgrade --force-reinstall pip; \  | 
 | 177 | + fi \  | 
 | 178 | + ## Install font MesloLGS NF  | 
 | 179 | + && mkdir -p /usr/share/fonts/truetype/meslo \  | 
 | 180 | + && curl -sL https://raw.githubusercontent.com/romkatv/powerlevel10k-media/master/MesloLGS%20NF%20Regular.ttf -o "/usr/share/fonts/truetype/meslo/MesloLGS NF Regular.ttf" \  | 
 | 181 | + && curl -sL https://raw.githubusercontent.com/romkatv/powerlevel10k-media/master/MesloLGS%20NF%20Bold.ttf -o "/usr/share/fonts/truetype/meslo/MesloLGS NF Bold.ttf" \  | 
 | 182 | + && curl -sL https://raw.githubusercontent.com/romkatv/powerlevel10k-media/master/MesloLGS%20NF%20Italic.ttf -o "/usr/share/fonts/truetype/meslo/MesloLGS NF Italic.ttf" \  | 
 | 183 | + && curl -sL https://raw.githubusercontent.com/romkatv/powerlevel10k-media/master/MesloLGS%20NF%20Bold%20Italic.ttf -o "/usr/share/fonts/truetype/meslo/MesloLGS NF Bold Italic.ttf" \  | 
 | 184 | + && fc-cache -fsv \  | 
 | 185 | + ## Git: Set default branch name to main  | 
 | 186 | + && git config --system init.defaultBranch main \  | 
 | 187 | + ## Git: Store passwords for one hour in memory  | 
 | 188 | + && git config --system credential.helper "cache --timeout=3600" \  | 
 | 189 | + ## Git: Merge the default branch from the default remote when "git pull" is run  | 
 | 190 | + && git config --system pull.rebase false \  | 
 | 191 | + ## Install pandoc  | 
 | 192 | + && curl -sLO https://github.com/jgm/pandoc/releases/download/${PANDOC_VERSION}/pandoc-${PANDOC_VERSION}-1-${dpkgArch}.deb \  | 
 | 193 | + && dpkg -i pandoc-${PANDOC_VERSION}-1-${dpkgArch}.deb \  | 
 | 194 | + && rm pandoc-${PANDOC_VERSION}-1-${dpkgArch}.deb \  | 
 | 195 | + ## Delete potential user with UID 1000  | 
 | 196 | + && if grep -q 1000 /etc/passwd; then \  | 
 | 197 | + userdel --remove $(id -un 1000); \  | 
 | 198 | + fi \  | 
 | 199 | + ## Do not set user limits for sudo/sudo-i  | 
 | 200 | + && sed -i 's/.*pam_limits.so/#&/g' /etc/pam.d/sudo \  | 
 | 201 | + && if [ -f "/etc/pam.d/sudo-i" ]; then \  | 
 | 202 | + sed -i 's/.*pam_limits.so/#&/g' /etc/pam.d/sudo-i; \  | 
 | 203 | + fi \  | 
 | 204 | + ## Add user  | 
 | 205 | + && useradd -l -m -s $(which zsh) -N -u ${NB_UID} ${NB_USER} \  | 
 | 206 | + ## Mark home directory as populated  | 
 | 207 | + && touch /home/${NB_USER}/.populated \  | 
 | 208 | + && chown ${NB_UID}:${NB_GID} /home/${NB_USER}/.populated \  | 
 | 209 | + && chmod go+w /home/${NB_USER}/.populated \  | 
 | 210 | + ## Create backup directory for home directory  | 
 | 211 | + && mkdir -p /var/backups/skel \  | 
 | 212 | + && chown ${NB_UID}:${NB_GID} /var/backups/skel \  | 
 | 213 | + ## Install Tini  | 
 | 214 | + && curl -sL https://github.com/krallin/tini/releases/download/v0.19.0/tini-${dpkgArch} -o /usr/local/bin/tini \  | 
 | 215 | + && chmod +x /usr/local/bin/tini \  | 
 | 216 | + ## Clean up  | 
 | 217 | + && rm -rf /tmp/* \  | 
 | 218 | + && rm -rf /var/lib/apt/lists/* \  | 
 | 219 | + ${HOME}/.cache  | 
 | 220 | + | 
 | 221 | +ENV PATH=/opt/code-server/bin:$PATH \  | 
 | 222 | + CS_DISABLE_GETTING_STARTED_OVERRIDE=1  | 
 | 223 | + | 
 | 224 | +## Install code-server  | 
 | 225 | +RUN mkdir /opt/code-server \  | 
 | 226 | + && cd /opt/code-server \  | 
 | 227 | + && curl -sL https://github.com/coder/code-server/releases/download/v${CODE_SERVER_VERSION}/code-server-${CODE_SERVER_VERSION}-linux-$(dpkg --print-architecture).tar.gz | tar zxf - --no-same-owner --strip-components=1 \  | 
 | 228 | + ## Exempt code-server from address space limit  | 
 | 229 | + && sed -i 's/exec/exec prlimit --as=unlimited:/g' \  | 
 | 230 | + /opt/code-server/bin/code-server \  | 
 | 231 | + ## Copy custom fonts  | 
 | 232 | + && mkdir -p /opt/code-server/src/browser/media/fonts \  | 
 | 233 | + && cp -a /usr/share/fonts/truetype/meslo/*.ttf /opt/code-server/src/browser/media/fonts \  | 
 | 234 | + ## Include custom fonts  | 
 | 235 | + && sed -i 's|</head>|	<link rel="preload" href="{{BASE}}/_static/src/browser/media/fonts/MesloLGS NF Regular.woff2" as="font" type="font/woff2" crossorigin="anonymous">\n</head>|g' /opt/code-server/lib/vscode/out/vs/code/browser/workbench/workbench.html \  | 
 | 236 | + && sed -i 's|</head>|	<link rel="preload" href="{{BASE}}/_static/src/browser/media/fonts/MesloLGS NF Italic.woff2" as="font" type="font/woff2" crossorigin="anonymous">\n</head>|g' /opt/code-server/lib/vscode/out/vs/code/browser/workbench/workbench.html \  | 
 | 237 | + && sed -i 's|</head>|	<link rel="preload" href="{{BASE}}/_static/src/browser/media/fonts/MesloLGS NF Bold.woff2" as="font" type="font/woff2" crossorigin="anonymous">\n</head>|g' /opt/code-server/lib/vscode/out/vs/code/browser/workbench/workbench.html \  | 
 | 238 | + && sed -i 's|</head>|	<link rel="preload" href="{{BASE}}/_static/src/browser/media/fonts/MesloLGS NF Bold Italic.woff2" as="font" type="font/woff2" crossorigin="anonymous">\n</head>|g' /opt/code-server/lib/vscode/out/vs/code/browser/workbench/workbench.html \  | 
 | 239 | + && sed -i 's|</head>|	<link rel="stylesheet" type="text/css" href="{{BASE}}/_static/src/browser/media/css/fonts.css">\n</head>|g' /opt/code-server/lib/vscode/out/vs/code/browser/workbench/workbench.html \  | 
 | 240 | + ## Install code-server extensions  | 
 | 241 | + && cd /tmp \  | 
 | 242 | + && curl -sLO https://dl.b-data.ch/vsix/mutantdino.resourcemonitor-1.0.7.vsix \  | 
 | 243 | + && code-server --extensions-dir ${CODE_BUILTIN_EXTENSIONS_DIR} --install-extension mutantdino.resourcemonitor-1.0.7.vsix \  | 
 | 244 | + && code-server --extensions-dir ${CODE_BUILTIN_EXTENSIONS_DIR} --install-extension alefragnani.project-manager \  | 
 | 245 | + && code-server --extensions-dir ${CODE_BUILTIN_EXTENSIONS_DIR} --install-extension GitHub.vscode-pull-request-github \  | 
 | 246 | + && code-server --extensions-dir ${CODE_BUILTIN_EXTENSIONS_DIR} --install-extension GitLab.gitlab-workflow \  | 
 | 247 | + && code-server --extensions-dir ${CODE_BUILTIN_EXTENSIONS_DIR} --install-extension ms-python.python \  | 
 | 248 | + && code-server --extensions-dir ${CODE_BUILTIN_EXTENSIONS_DIR} --install-extension ms-toolsai.jupyter \  | 
 | 249 | + && code-server --extensions-dir ${CODE_BUILTIN_EXTENSIONS_DIR} --install-extension christian-kohler.path-intellisense \  | 
 | 250 | + && code-server --extensions-dir ${CODE_BUILTIN_EXTENSIONS_DIR} --install-extension eamodio.gitlens@11.7.0 \  | 
 | 251 | + && code-server --extensions-dir ${CODE_BUILTIN_EXTENSIONS_DIR} --install-extension mhutchie.git-graph \  | 
 | 252 | + && code-server --extensions-dir ${CODE_BUILTIN_EXTENSIONS_DIR} --install-extension piotrpalarz.vscode-gitignore-generator \  | 
 | 253 | + && code-server --extensions-dir ${CODE_BUILTIN_EXTENSIONS_DIR} --install-extension redhat.vscode-yaml \  | 
 | 254 | + && code-server --extensions-dir ${CODE_BUILTIN_EXTENSIONS_DIR} --install-extension grapecity.gc-excelviewer \  | 
 | 255 | + && code-server --extensions-dir ${CODE_BUILTIN_EXTENSIONS_DIR} --install-extension editorconfig.editorconfig \  | 
 | 256 | + && code-server --extensions-dir ${CODE_BUILTIN_EXTENSIONS_DIR} --install-extension DavidAnson.vscode-markdownlint \  | 
 | 257 | + ## Fix permissions for Python Debugger extension  | 
 | 258 | + && chown :${NB_GID} /opt/code-server/lib/vscode/extensions/ms-python.debugpy-* \  | 
 | 259 | + && chmod g+w /opt/code-server/lib/vscode/extensions/ms-python.debugpy-* \  | 
 | 260 | + ## Create folders temp and tmp for Jupyter extension  | 
 | 261 | + && cd /opt/code-server/lib/vscode/extensions/ms-toolsai.jupyter-* \  | 
 | 262 | + && mkdir -m 1777 temp \  | 
 | 263 | + && mkdir -m 1777 tmp \  | 
 | 264 | + ## Clean up  | 
 | 265 | + && rm -rf /tmp/* \  | 
 | 266 | + ${HOME}/.config \  | 
 | 267 | + ${HOME}/.local  | 
 | 268 | + | 
 | 269 | +## Install JupyterLab  | 
 | 270 | +RUN export PIP_BREAK_SYSTEM_PACKAGES=1 \  | 
 | 271 | + && pip install \  | 
 | 272 | + jupyter-server-proxy \  | 
 | 273 | + jupyterhub==${JUPYTERHUB_VERSION} \  | 
 | 274 | + jupyterlab==${JUPYTERLAB_VERSION} \  | 
 | 275 | + jupyterlab-git \  | 
 | 276 | + jupyterlab-lsp \  | 
 | 277 | + notebook \  | 
 | 278 | + nbclassic \  | 
 | 279 | + nbconvert \  | 
 | 280 | + python-lsp-server[all] \  | 
 | 281 | + ## Jupyter Server Proxy: Set maximum allowed HTTP body size to 10 GiB  | 
 | 282 | + && sed -i 's/AsyncHTTPClient(/AsyncHTTPClient(max_body_size=10737418240, /g' \  | 
 | 283 | + /usr/local/lib/python*/*-packages/jupyter_server_proxy/handlers.py \  | 
 | 284 | + ## Jupyter Server Proxy: Set maximum allowed websocket message size to 1 GiB  | 
 | 285 | + && sed -i 's/"_default_max_message_size",.*$/"_default_max_message_size", 1024 \* 1024 \* 1024/g' \  | 
 | 286 | + /usr/local/lib/python*/*-packages/jupyter_server_proxy/websocket.py \  | 
 | 287 | + && sed -i 's/_default_max_message_size =.*$/_default_max_message_size = 1024 \* 1024 \* 1024/g' \  | 
 | 288 | + /usr/local/lib/python*/*-packages/tornado/websocket.py \  | 
 | 289 | + ## Copy custom fonts  | 
 | 290 | + && mkdir -p /usr/local/share/jupyter/lab/static/assets/fonts \  | 
 | 291 | + && cp -a /usr/share/fonts/truetype/meslo/*.ttf /usr/local/share/jupyter/lab/static/assets/fonts \  | 
 | 292 | + ## Include custom fonts  | 
 | 293 | + && sed -i 's|</head>|<link rel="preload" href="{{page_config.fullStaticUrl}}/assets/fonts/MesloLGS NF Regular.woff2" as="font" type="font/woff2" crossorigin="anonymous"></head>|g' /usr/local/share/jupyter/lab/static/index.html \  | 
 | 294 | + && sed -i 's|</head>|<link rel="preload" href="{{page_config.fullStaticUrl}}/assets/fonts/MesloLGS NF Italic.woff2" as="font" type="font/woff2" crossorigin="anonymous"></head>|g' /usr/local/share/jupyter/lab/static/index.html \  | 
 | 295 | + && sed -i 's|</head>|<link rel="preload" href="{{page_config.fullStaticUrl}}/assets/fonts/MesloLGS NF Bold.woff2" as="font" type="font/woff2" crossorigin="anonymous"></head>|g' /usr/local/share/jupyter/lab/static/index.html \  | 
 | 296 | + && sed -i 's|</head>|<link rel="preload" href="{{page_config.fullStaticUrl}}/assets/fonts/MesloLGS NF Bold Italic.woff2" as="font" type="font/woff2" crossorigin="anonymous"></head>|g' /usr/local/share/jupyter/lab/static/index.html \  | 
 | 297 | + && sed -i 's|</head>|<link rel="stylesheet" type="text/css" href="{{page_config.fullStaticUrl}}/assets/css/fonts.css"></head>|g' /usr/local/share/jupyter/lab/static/index.html \  | 
 | 298 | + ## Clean up  | 
 | 299 | + && rm -rf /tmp/* \  | 
 | 300 | + ${HOME}/.cache  | 
 | 301 | + | 
 | 302 | +## Switch back to ${NB_USER} to avoid accidental container runs as root  | 
 | 303 | +USER ${NB_USER}  | 
 | 304 | + | 
 | 305 | +ENV HOME=/home/${NB_USER} \  | 
 | 306 | + CODE_WORKDIR=${CODE_WORKDIR:-/home/${NB_USER}/projects} \  | 
 | 307 | + SHELL=/usr/bin/zsh \  | 
 | 308 | + TERM=xterm-256color  | 
 | 309 | + | 
 | 310 | +WORKDIR ${HOME}  | 
 | 311 | + | 
 | 312 | +## Install Oh My Zsh with Powerlevel10k theme  | 
 | 313 | +RUN sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended \  | 
 | 314 | + && git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${HOME}/.oh-my-zsh/custom/themes/powerlevel10k \  | 
 | 315 | + && ${HOME}/.oh-my-zsh/custom/themes/powerlevel10k/gitstatus/install -f \  | 
 | 316 | + && sed -i 's/ZSH="\/home\/jovyan\/.oh-my-zsh"/ZSH="$HOME\/.oh-my-zsh"/g' ${HOME}/.zshrc \  | 
 | 317 | + && sed -i 's/ZSH_THEME="robbyrussell"/ZSH_THEME="powerlevel10k\/powerlevel10k"/g' ${HOME}/.zshrc \  | 
 | 318 | + && echo "\n# set PATH so it includes user's private bin if it exists\nif [ -d \"\$HOME/bin\" ] && [[ \"\$PATH\" != *\"\$HOME/bin\"* ]] ; then\n PATH=\"\$HOME/bin:\$PATH\"\nfi" | tee -a ${HOME}/.bashrc ${HOME}/.zshrc \  | 
 | 319 | + && echo "\n# set PATH so it includes user's private bin if it exists\nif [ -d \"\$HOME/.local/bin\" ] && [[ \"\$PATH\" != *\"\$HOME/.local/bin\"* ]] ; then\n PATH=\"\$HOME/.local/bin:\$PATH\"\nfi" | tee -a ${HOME}/.bashrc ${HOME}/.zshrc \  | 
 | 320 | + && echo "\n# Update last-activity timestamps while in screen/tmux session\nif [ ! -z \"\$TMUX\" -o ! -z \"\$STY\" ] ; then\n busy &\nfi" >> ${HOME}/.bashrc \  | 
 | 321 | + && echo "\n# Update last-activity timestamps while in screen/tmux session\nif [ ! -z \"\$TMUX\" -o ! -z \"\$STY\" ] ; then\n setopt nocheckjobs\n busy &\nfi" >> ${HOME}/.zshrc \  | 
 | 322 | + && echo "\n# To customize prompt, run \`p10k configure\` or edit ~/.p10k.zsh." >> ${HOME}/.zshrc \  | 
 | 323 | + && echo "[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh" >> ${HOME}/.zshrc \  | 
 | 324 | + ## Create user's private bin  | 
 | 325 | + && mkdir -p ${HOME}/.local/bin \  | 
 | 326 | + ## Record population timestamp  | 
 | 327 | + && date -uIseconds > ${HOME}/.populated \  | 
 | 328 | + ## Create backup of home directory  | 
 | 329 | + && cp -a ${HOME}/. /var/backups/skel  | 
 | 330 | + | 
 | 331 | +## Copy files as late as possible to avoid cache busting  | 
 | 332 | +COPY --from=files /files /  | 
 | 333 | +COPY --from=files /files/var/backups/skel ${HOME}  | 
 | 334 | + | 
 | 335 | +ARG JUPYTER_PORT=8888  | 
 | 336 | +ENV JUPYTER_PORT=${JUPYTER_PORT}  | 
 | 337 | + | 
 | 338 | +EXPOSE $JUPYTER_PORT  | 
 | 339 | + | 
 | 340 | +## Configure container startup  | 
 | 341 | +ENTRYPOINT ["tini", "-g", "--", "start.sh"]  | 
 | 342 | +CMD ["start-notebook.sh"]  | 
0 commit comments