辦公室有一台GPU server供幾位工程師共用,有不便放上雲端的資料就可以直接放進去跑。深度學習演算法的開發常常需要使用不同環境,因此我們以docker方式提供Tensorflow 2.x, 1.x, Pytorch等幾種不同環境,然後每種環境以不同的port為進入點,都以Jupyterlab為介面。
這樣的環境算是堪用,但也有許多不便,首先,沒有帳號管理,不同人的檔案只能以資料夾做區隔,也無法得知是否有人正在跟你共用同一個環境,然後每個port到底裝了什麼環境只能靠大家的記憶或是擲筊。
利用JupyterHub可以解決上述問題,每個使用者能自己選擇現在想使用的環境(這些環境都各是不同的docker image產生),且除了自身就有帳號管理機制外,還能連結像是Google、GitHub之類的帳號,admin介面能夠看到目前的使用者,也能手動或設定自動關掉沒在跑的server。
為了維持乾淨整潔,JupyterHub是以docker的方式安裝,另外之前提到的Tensorflow, Pytorch等,也都會建立成一個個不同的docker image。
安裝JupyterHub
我們以docker compose方式安裝JupyterHub,所以其實只需要三個設定檔,首先是docker-compose.yml:
要注意的是,為了避免檔案因為docker container重啟而消失,我們將本機資料夾/home/aifuser/jupyterhub掛到docker裡的/persist上。
version: '3'
services:
# Configuration for Hub+Proxy
jupyterhub:
build: . # Build the container from this folder
container_name: jupyterhub_hub # The service will use this container name.
volumes: # Give access to Docker socket.
- /var/run/docker.sock:/var/run/docker.sock
- jupyterhub_data:/srv/jupyterlab
- /home/aifuser/jupyterhub:/persist
environment: # Env variables passed to the Hub process.
DOCKER_NETWORK_NAME: jupyter_hub
ports:
- 8000:8000
restart: unless-stopped # Configuration for the single-user servers
jupyterlab:
image: jupyter/tensorflow-notebook
command: echo
volumes:
jupyterhub_data:
第二個是最主要的設定檔jupyterhub_config.py:
第一段設定了如何產生使用者真正的要使用的開發環境,我們使用DockerSpawner來產生環境,且在c.DockerSpawner.allowed_images設定一些環境可供選擇,例如:”tensorflow-cpu”: “jupyter/tensorflow-notebook”。”tensorflow-cpu”是選單中的名稱,“jupyter/tensorflow-notebook”則是docker image的名稱,其實也就是官方的image。
import os
import sys
import shutil
c.JupyterHub.spawner_class = 'dockerspawner.DockerSpawner'
c.DockerSpawner.network_name = os.environ['DOCKER_NETWORK_NAME']
c.DockerSpawner.allowed_images = {
"tensorflow-cpu": "jupyter/tensorflow-notebook",
"tensorflow-gpu (Tensorflow 2.8)": "harbor.aif.tw/env/tensorflow-notebook",
"pytorch-gpu (Pytorch 1.10)": "harbor.aif.tw/env/pytorch-notebook"
}
c.DockerSpawner.remove_containers = True
c.DockerSpawner.extra_host_config = {'runtime': 'nvidia'}
c.Spawner.environment = {'GRANT_SUDO': 'yes'}
c.Spawner.default_url = '/lab'
供使用者選擇的開發環境選單
接下來,指定admin為管理者帳號;設定使用FirstUseAuthenticator,我們直接使用內建的帳號管理系統,從admin介面新增使用者之後,使用者在第一次登入時必須自行設定密碼。
from jupyter_client.localinterfaces import public_ips
c.JupyterHub.hub_ip = public_ips()[0]
c.JupyterHub.admin_access = True
c.Authenticator.admin_users = {'admin'}
c.JupyterHub.authenticator_class = 'firstuseauthenticator.FirstUseAuthenticator'
c.LocalAuthenticator.create_system_users = True
設定idle多久自動關閉server,這裡指的server是使用者開的開發環境。
#shutdown the server after no activity for an hour
c.ServerApp.shutdown_no_activity_timeout = 60 * 60
#shutdown kernels after no activity for 30 minutes
c.MappingKernelManager.cull_idle_timeout = 30 * 60
#check for idle kernels every two minutes
c.MappingKernelManager.cull_interval = 2 * 60
設定建立新使用者的家目錄,並且與docker外的本機目錄連結,家目錄的owner ID/group ID需要與本機的user ID/group ID相同,否則會發生無法編輯的錯誤。
def create_dir_hook(spawner):
""" Create directory """
username = spawner.user.name # get the username
home_path = os.path.join('/persist/', username)
if not os.path.exists(home_path):
os.mkdir(home_path)
os.chown(home_path, 1000, 1000) # Same UID/GID as in local machine
c.Spawner.pre_spawn_hook = create_dir_hook
notebook_dir = os.environ.get('DOCKER_NOTEBOOK_DIR') or '/home/jovyan/work'
c.DockerSpawner.notebook_dir = notebook_dir
c.DockerSpawner.volumes = {'/home/aifuser/jupyterhub/{username}': '/home/jovyan/work'}
JupyterHub的設定與使用者資料會存在/persist下,以免JupyterHub重啟後全部消失。
c.JupyterHub.cookie_secret_file = '/persist/jupyterhub_cookie_secret'
c.JupyterHub.db_url = '/persist/jupyterhub.sqlite'
第三個設定檔是Dockerfile:
FROM jupyterhub/jupyterhub
#Copy the JupyterHub configuration in the container
COPY jupyterhub_config.py .
#Install dependencies (for advanced authentication and spawning)
RUN pip install dockerspawner
RUN pip install jupyter-client
RUN pip install jupyterhub-firstuseauthenticator
我們直接使用JupyterHub官方提供的docker image,放入jupyterhub_config.py,並且加入指令安裝其他需要使用到的package。
建立開發環境
如先前所說,我們會以docker image方式提供Tensorflow, Pytorch等幾種不同環境,因為jupyter的tensorflow-notebook已經幫我們安裝設定好了大部分使用Python做資料分析與處理的套件與tensorflow,我們直接使用下列指令拉下image做為CPU版tensorflow環境:
$ docker pull jupyter/tensorflow-notebook
要讓tensorflow支援GPU,所以接下來就以tensorflow-notebook為基礎來做修改;首先是將安裝的tensorflow改成tensorflow-gpu,如下:
#Install Tensorflow
RUN pip install — quiet — no-cache-dir \
‘tensorflow-gpu’ && \
mamba clean — all -f -y && \
fix-permissions “${CONDA_DIR}” && \
fix-permissions “/home/${NB_USER}”
除了安裝tensorflow-gpu,docker image所使用的OS也要能支援GPU;從tensorflow-notebook的Dockerfile中可以看到,tensorflow-notebook是基於scipy-notebook,scipy-notebook是基於minimal-notebook,minimal-notebook是基於base-notebook,於是我們找到base-notebook原本使用的是ubuntu:focal的image,配合我們GPU server現在的設定和CUDA/cudnn版本,將它改成nvidia/cuda:11.2.2-cudnn8-devel-ubuntu20.04。
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
# Ubuntu 20.04 (focal)
# https://hub.docker.com/_/ubuntu/?tab=tags&name=focal
# ARG ROOT_CONTAINER=ubuntu:focal
ARG ROOT_CONTAINER=nvidia/cuda:11.2.2-cudnn8-devel-ubuntu20.04
FROM $ROOT_CONTAINER
LABEL maintainer="Jupyter Project <jupyter@googlegroups.com>"
ARG NB_USER="jovyan"
ARG NB_UID="1000"
ARG NB_GID="100"
使用下列指令建立上述docker images
$ docker build -t harbor.aif.tw/env/tensorflow-notebook:lastest .
$ docker push harbor.aif.tw/env/tensorflow-notebook:lastest
Pytorch的環境也同樣藉由修改tensorflow-notebook的Dockerfile得來,修改如下:
ARG OWNER=harbor.aif.tw/env
ARG BASE_CONTAINER=$OWNER/scipy-notebook
FROM $BASE_CONTAINER
# Fix DL4006
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Install Tensorflow
RUN conda install --quiet --yes \
'pytorch' \
'torchvision' \
'torchaudio' \
'cudatoolkit=11.3' \
-c pytorch && \
mamba clean --all -f -y && \
fix-permissions "${CONDA_DIR}" && \
fix-permissions "/home/${NB_USER}"
使用下列指令建立上述docker images
$ docker build -t harbor.aif.tw/env/pytorch-notebook:lastest .
$ docker push harbor.aif.tw/env/pytorch-notebook:lastest
JupyterHub~啟動!
設定檔準備好了,開發環境的image也準備好了,回到JupyterHub設定檔的目錄下,準備啟動!
$ docker-compose build
$ docker-compose up -d
連線到http://localhost:8000,便能看到JupyterHub的登入畫面;因為設定檔中已有指定admin為管理者帳號,只要設定密碼後便能登入。
(撰稿工程師:張嘉哲)
參考資料
https://hackmd.io/@DanielChen/Sy81P-Aw4?type=view
https://medium.com/analytics-vidhya/jupyterhub-docker-31b7a3469872
(原文連結:多人AI開發環境JupyterHub安裝)