메인 콘텐츠로 이동하기
  1. Posts/

Docker로 나만의 `JupyterLab` workspace 만들기

목차
Docker로 JupyterLab workspace를 구성한 짧은 TID입니다. 🤔

시작한 이유 #

Python과 JavaScript의 짧은 코드나 함수를 테스트할 때마다 필요한 dependency를 로컬에 직접 설치하고 싶지는 않았습니다. JupyterLab은 browser에서 두 언어를 실행할 수 있어 작은 실험용 workspace로 사용하기 좋았습니다.

Docker를 사용하면 runtime과 dependency를 workspace 안에 둘 수 있습니다. Docker만 준비되어 있다면 운영체제가 달라도 같은 구성을 실행할 수 있습니다.

이 구성은 로컬이나 신뢰할 수 있는 network에서 사용하는 것을 전제로 합니다. 예시에서는 편의를 위해 Jupyter token을 비활성화했기 때문에, 인증 없이 public internet에 노출하면 안 됩니다.

Workspace 구조 #

container 정의, server 설정과 notebook을 각각 나누고 필요한 파일만 남겼습니다.

.
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
├── config
│   └── jupyter_server_config.py
└── workspace
    ├── python
    └── javascript

Dockerfile은 image를 만들고, docker-compose.yml은 service를 실행합니다. config/jupyter_server_config.py에는 Jupyter Server 설정을 둡니다. workspace는 volume으로 host와 연결해 container를 다시 만들어도 작업 파일을 유지합니다.

Image 만들기 #

기본 image는 jupyter/docker-stacksbase-notebook을 사용했습니다. 첫 번째 stage에서 Python package를 설치하고, ijs stage에서 iJavaScript kernel을 추가합니다.

FROM jupyter/base-notebook:ubuntu-22.04 AS base

COPY --chown=${NB_UID}:${NB_GID} requirements.txt /tmp/
RUN pip install --quiet --no-cache-dir --requirement /tmp/requirements.txt && \
    fix-permissions "${CONDA_DIR}" && \
    fix-permissions "/home/${NB_USER}"

FROM base AS ijs

RUN npm install -g ijavascript
RUN ijsinstall

image target을 나누면 JavaScript kernel을 추가한 구성이 어디에서 시작되는지 분명해집니다. Python만 필요하다면 base image에서 멈추면 됩니다.

Container 연결하기 #

Compose file에서는 workspace와 server config를 mount하고, 8888 port로 JupyterLab을 노출합니다.

services:
  jupyter:
    container_name: jupyter
    build:
      context: .
      dockerfile: Dockerfile
      target: ijs
    volumes:
      - ./workspace:/home/jovyan/work
      - ./config/jupyter_server_config.py:/etc/jupyter/jupyter_server_config.py
    ports:
      - "8888:8888"
    command: jupyter lab --allow-root --ServerApp.token=''

이 구성에서 중요한 부분은 workspace volume입니다. container를 다시 build해도 workspace 아래에 저장한 notebook은 host에 남아 있습니다.

Server 설정 #

config file에서 container network의 요청을 받을 수 있도록 설정하고, container 안에서 browser가 열리지 않게 했습니다.

c = get_config()  # noqa: F821
c.ServerApp.ip = "0.0.0.0"
c.ServerApp.open_browser = False

# 이 구성에서 VS Code Jupyter extension을 사용하기 위한 설정입니다.
c.ServerApp.disable_check_xsrf = True

전체 예시는 base-notebook server configuration을 참고했습니다. XSRF check와 token을 끄는 설정은 public server의 기본값으로 사용할 수 없습니다.

실행하기 #

파일을 준비한 뒤 Docker Compose로 service를 build하고 실행합니다.

docker compose up -d
docker compose logs -f

container가 실행되면 browser에서 http://localhost:8888/lab을 엽니다. 같은 workspace에서 Python과 iJavaScript kernel을 선택할 수 있습니다.

정리 #

이번 작업에서 유용했던 부분은 JupyterLab을 Docker에서 실행한 것만은 아니었습니다. image, server 설정과 host workspace를 분리하니 notebook을 잃지 않고 구성을 다시 만들 수 있었습니다.

token을 끄면 local 실험은 편해지지만, 이 workspace의 사용 범위도 분명해집니다. 다른 사람이 접근할 수 있는 서버에 배포한다면 인증과 안전한 server 설정을 먼저 추가해야 합니다.

참고 #