👋

JupyterLab in Dockerに作るGitHub環境

2022/02/11に公開

概要

  • 今回,Dockerで作ったJupyterLab環境にGitHubを連携させました.
  • 誰がcloneしてきても,同じ挙動になるリポジトリを作りました.
    ※「リポジトリ単位でデータ分析コードを管理できひんやろ」って思ったのがきっかけです.(この考えが間違っていたら,ぜひご指摘ください)
  • リポジトリを作成したときの手順を残しています.
  • 作業中に,コンテナ内のssh接続やら,GitのGUIツールのインストールでエラーが出てはまったので,その解消方法も記載しています.

試行錯誤の内容を見るのがだるいなあと思う人は,以下をご覧ください.
https://github.com/yuiki-iwayama/JupyterLab-Docker

前提知識

  • gitコマンドの使い方
  • ssh設定以外のGitHubの使い方
  • 基本的なdockerコマンド, docker-composeコマンドの使い方
  • JupyterLabの使い方

試行環境とファイル構成

  • M1 MacBook Pro
  • macOS Monterey 12.0.1
  • Docker Desktop 4.4.2 (for Mac)
  • ファイル構成
.
├── .env
├── .gitigonre
├── Dockerfile
├── base.txt
├── config
├── docker-compose.yml
└── init.sh

手順

概要

  1. 公開鍵と秘密鍵の作成
  2. GitHubへの公開鍵の登録
  3. Dockerのリモートリポジトリを作成する
  4. 作成したリポジトリをローカルにcloneする
  5. Dockerfileを作成する
  6. base.txtを記述する
  7. configを記述する
  8. init.shを記述する
  9. .gitigonoreを記述する
  10. git pushする
  11. コンテナをbuildする
  12. docker-compose.ymlと.envを記述する
  13. コンテナ内でGitHubへssh接続できるかテストする
  14. 自身で保有しているリモートリポジトリをコンテナ内でcloneする
  15. jupyterlab-gitでもpushできるか確認する

1. 公開鍵と秘密鍵の作成


まずは公開鍵と秘密鍵を作成します.秘密鍵は自身のPC(ローカル)で作成し,公開鍵はGitHubに後ほど共有します.

  1. $ cd ~/.ssh
  2. $ ssh-keygen -t rsa -C <GitHubに登録しているe-mail>
  3. Enter file in which to save the key (/Users/xxx/.ssh/id_rsa):」と聞かれるので,Enterを押す
  4. Enter passphrase (empty for no passphrase):」と聞かれるので,特に指定がなければEnterをそのまま押す
  1. Enter same passphrase again:」と聞かれるので,指定していない場合はEnterを押す(passphraseを作った場合は同じ内容を入力する)
  2. $ lsで確認すると,「id_rsa」と「id_rsa.pub」ができている(.pubがついている方が公開鍵)
  3. $ pbcopy < ~/.ssh/id_rsa.pubで公開鍵を後の操作のためにクリップボードにコピーする

2. GitHubへの公開鍵の登録


公開鍵をGitHubに保存します.

  1. Settings -> SSH and GPG keysに移動
  2. New SSH keyを押す
  3. Titleを入力して,先ほどクリップボードにコピーした公開鍵をKeyに貼り付ける
    ※私はTitleはわかりやすいようにJupyterLab-Dockerとしました.
  4. Add SSH keyを押す
  5. パスワードを要求されるので入力してconfirmする

3. Dockerのリモートリポジトリを作成する


いよいよ本題のDockerを動かすためのリモートリポジトリを作ります.

  • Repositoriesに移動して,Newを押す
  • Repository nameを入力する
    ※私はわかりやすいようにJupyterLab-Dockerとしました
  • PublicかPrivateのどちらかを選択し,「ADD a README file」と「ADD .gitignoe」を選択する
  • Create repositoryを押す

4. 作成したリポジトリをローカルにcloneする


作成したリモートリポジトリをローカルにcloneしてきます.
(ローカルのssh設定はできている前提で進めます[1]

  • 作成したリポジトリのCodeを押して,SSHを選択してURLをクリップボードにコピーする.
  • $ cd ~/Desktop
  • $ git clone git@github.com:<user-name>/JupyterLab-Docker.git
  • $ cd JupyterLab-Docker

5. Dockerfileを作成する


Dockerfileを書いていきます.長くなるので,sshするためのポイントだけ記述します.

Dockerfile
Dockerfile
FROM continuumio/anaconda3:latest

# 必要なパッケージを入れる.
RUN apt-get update && apt-get install -y --no-install-recommends \
    fonts-ipaexfont \
    libgl1-mesa-dev \
    build-essential \
    ca-certificates \
    cmake \
    gcc \
    g++ \
    openssh-client \
    bash-completion \
    vim

# Debianの設定
RUN apt-get -y install locales && \
    localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9
ENV TERM xterm

# condaでインストール
COPY base.txt /tmp/base.txt
RUN conda update -n base -c defaults conda -y \
  && conda install -n base -c conda-forge --file /tmp/base.txt -y \
  && conda clean -a -y \
  && rm /tmp/base.txt

# GitHubからsshでcloneするための設定
ARG GITHUB_USER
ARG GITHUB_EMAIL
RUN mkdir -p ~/.ssh \
  && git config --global user.name "${GITHUB_USER}"  \
  && git config --global user.email ${GITHUB_EMAIL}
COPY config /root/.ssh
COPY init.sh /usr/bin

RUN apt-get autoremove -y \
  && apt-get clean
WORKDIR /work

CMD ["/bin/bash", "/usr/bin/init.sh"]
  1. apt-get installopenssh-clientをインストールする
  1. コンテナ内のGitに個人識別情報を登録する
ARG GITHUB_USER
ARG GITHUB_EMAIL
RUN mkdir -p ~/.ssh \
  && git config --global user.name "${GITHUB_USER}"  \
  && git config --global user.email "${GITHUB_EMAIL}"
  • ARGでdocker-compose.yml(後述)から変数をDockerfileに渡す
  • rootの下に.sshディレクトリを作る
  • git config --globalにARGで受け取った変数を登録する
  1. sshするために必要なconfigファイルとentrypoint.shファイルをコンテナ内にコピーする
COPY config /root/.ssh
COPY init.sh /usr/bin
  1. コピーしたinit.shファイルを実行する
CMD ["/bin/bash", "/usr/bin/init.sh"]

6. base.txtを記述する


condaでinstallするパッケージを記載するbase.txtを書いていきます.

base.txt
base.txt
eli5
lightgbm
xgboost
mlxtend
imbalanced-learn
jupyterlab-notifications
nodejs
git
jupyterlab-git
  • jupyterlab-gitを動かすためにnodejsgitjupyterlab-gitを記載する

7.configを記述する[3]


GitHubにssh接続するときの設定である~/.ssh/configを書いていきます.

config
Host github github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_rsa
    StrictHostKeyChecking no
  • StrictHostKeyChecking noで対話型の要求を抑制する

8. docker-compose.ymlと.envを記述する


コンテナをbuildする際の設定であるdocker-compose.ymlとコンテナ内に環境変数を渡すための.envを書いていきます.

docker-compose.yml
docker-compose.yml
version: "3"
services:
  notebook:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        GITHUB_USER: $GITHUB_USER
        GITHUB_EMAIL: $GITHUB_EMAIL
    container_name: "jupyterlab"
    ports:
      - 8888:8888
    restart: always
    volumes:
      - ./work:/work
    secrets:
      - user_ssh_key

secrets:
  user_ssh_key:
    file: $SSH_KEY_PATH
.env
SSH_KEY_PATH=~/.ssh/id_rsa
GITHUB_USER=
GITHUB_EMAIL=
args:
  GITHUB_USER: $GITHUB_USER
  GITHUB_EMAIL: $GITHUB_EMAIL
  • Dockerfileにわたすargsを記述している
  • .envに環境変数を定義しておいて,$で呼び出す
    secrets:
      - user_ssh_key

secrets:
  user_ssh_key:
    file: $SSH_KEY_PATH
  • secretsによって,ローカルマシンで作ったid_rsaをコンテナに受け渡す
  • .envに環境変数を定義しておいて,$で呼び出す

9. init.shを記述する


コンテナのbuildが終わったあとにコマンドを実行するためのinit.shを書いていきます.

init.sh
init.sh
#!/bin/bash

cp -ip /run/secrets/user_ssh_key ~/.ssh/id_rsa
source /etc/bash_completion
jupyter lab --ip=0.0.0.0 --allow-root --LabApp.token=''
cp -ip /run/secrets/user_ssh_key ~/.ssh/id_rsa
  • secretsでコンテナにコピーした秘密鍵は/run/secretsの下にできるので,~/.sshの下に移動させる
  • id_rsaをbuildのキャッシュに残さないためにやっている操作だが,本当にsecureなのかはあまり自信がない...

10. .gitignoreを記述する[4]


gitの管理に入れないフォルダやファイルを定義する.gitignoreを書いていきます.

.gitigonore
.DS_Store
# ipynb_checkpointsはgit管理下に入れない
/.ipynb_checkpoints
# 個別にwork配下にリポジトリを設置するためにgit管理下に入れない
work
  • 作業ディレクトリであるwork以下をgitの管理化に入れないようworkを記述する

11. git pushする


出来上がったリポジトリをリモートリポジトリにpushします.

  • $ git push origin master
  • リモートリポジトリにGitHubにsshアクセスできるJupyterLab in Docker環境ができる

12. コンテナをbuildする


Dockerコンテナをbuildできる環境もできたので,いよいよコンテナを立ち上げます.

  • $ cd ~/Desktop/JupyterLab-Docker
  • $ docker-compose up -d --build
  • 立ち上がったら,ブラウザでlocalhost:8888にアクセスしてJupyterLabがうまく起動できているか確認する

13. コンテナ内でGitHubへssh接続できるかテストする


buildが成功したら,次はコンテナの中に入ってGitHubにssh接続します.

  • $ docker-compose exec notebook bash
  • $ ssh -T github
  • Hi <user-name>! You've successfully authenticated, but GitHub does not provide shell access.と表示されたら接続成功

※ ssh接続するたびに,passphraseを毎回聞かれるのを回避する手順

$ eval "$ssh-agent -s"
$ echo "\n    UseKeychain yes\n    AddKeysToAgent yes" >> ~/Desktop/JupyterLab-Docker/config
$ ssh-add -K ~/.ssh/id_rsa

14. 自身で保有しているリモートリポジトリをコンテナ内でcloneする


GitHub上にあるリポジトリを実際にコンテナの中でcloneして,一連のgit操作を行ってみます.

  • testというリポジトリを作る
  • sshのURLをクリップボードにコピーする
  • $ git clone git@github.com:<user-name>/test.git
  • $ cd test
  • $ touch test.txt
  • $ git add test.txt
  • $ git commit -m 'test commit'
  • $ git push origin master
  • commit内容の反映がリモートリポジトリで確認できる

15. jupyterlab-gitでもpushできるか確認する


JupyterLab上でも一連のgit操作を行ってみます.

  • localhost:8888にブラウザでアクセスする
  • test.txtファイルを開いて「JupyterLabで上で変更」と書き,⌘+Sで保存する
  • ファイル名の横にある「+」を押すしてStagingに上げる
  • 左下にあるcommit用のインターフェースにて,commit messageを書いて「COMMIT」を押してcommitする
  • 右上にあるpull/push用のインターフェスにて,「cloud↑」マークを押してpushする
  • commit内容の反映がリモートリポジトリで確認できる

参考

謝辞

この記事を書くにあたって,終始熱心な指導をしてくれた友人に感謝の意を表します.
彼はいつも私のどんなお願いも聞いてくれて,どんな悩みも解決してくれます.
仕事が忙しくても,「頼ってくれる人のためなら!」と必ず時間をとってくれます.
あんな人格者,僕はみたことがありません.本当にありがとうございます.

脚注
  1. できていない方はGitHubにssh接続するまでの手順を参考にしてください. ↩︎

  2. failed to load the jupyterlab-git server extension git command not found #952をヒントにしました. ↩︎

  3. 説明部分以外はGitHub 接続時の ~/.ssh/config の書き方を参考にしてください. ↩︎

  4. .DS_Storeをすべてのリポジトリで無視したい場合は,すべてのリポジトリで .DS_Store を gitignore する方法を参考にしてください. ↩︎

Discussion