JupyterLab in Dockerに作るGitHub環境
概要
- 今回,Dockerで作ったJupyterLab環境にGitHubを連携させました.
- 誰がcloneしてきても,同じ挙動になるリポジトリを作りました.
※「リポジトリ単位でデータ分析コードを管理できひんやろ」って思ったのがきっかけです.(この考えが間違っていたら,ぜひご指摘ください) - リポジトリを作成したときの手順を残しています.
- 作業中に,コンテナ内のssh接続やら,GitのGUIツールのインストールでエラーが出てはまったので,その解消方法も記載しています.
試行錯誤の内容を見るのがだるいなあと思う人は,以下をご覧ください.
前提知識
- 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
手順
概要
- 公開鍵と秘密鍵の作成
- GitHubへの公開鍵の登録
- Dockerのリモートリポジトリを作成する
- 作成したリポジトリをローカルにcloneする
- Dockerfileを作成する
- base.txtを記述する
- configを記述する
- init.shを記述する
- .gitigonoreを記述する
- git pushする
- コンテナをbuildする
- docker-compose.ymlと.envを記述する
- コンテナ内でGitHubへssh接続できるかテストする
- 自身で保有しているリモートリポジトリをコンテナ内でcloneする
- jupyterlab-gitでもpushできるか確認する
1. 公開鍵と秘密鍵の作成
まずは公開鍵と秘密鍵を作成します.秘密鍵は自身のPC(ローカル)で作成し,公開鍵はGitHubに後ほど共有します.
$ cd ~/.ssh
$ ssh-keygen -t rsa -C <GitHubに登録しているe-mail>
- 「Enter file in which to save the key (/Users/xxx/.ssh/id_rsa):」と聞かれるので,Enterを押す
- 「Enter passphrase (empty for no passphrase):」と聞かれるので,特に指定がなければEnterをそのまま押す
- 「Enter same passphrase again:」と聞かれるので,指定していない場合はEnterを押す(passphraseを作った場合は同じ内容を入力する)
-
$ ls
で確認すると,「id_rsa」と「id_rsa.pub」ができている(.pubがついている方が公開鍵) -
$ pbcopy < ~/.ssh/id_rsa.pub
で公開鍵を後の操作のためにクリップボードにコピーする
2. GitHubへの公開鍵の登録
公開鍵をGitHubに保存します.
- Settings -> SSH and GPG keysに移動
-
New SSH keyを押す
- Titleを入力して,先ほどクリップボードにコピーした公開鍵をKeyに貼り付ける
※私はTitleはわかりやすいようにJupyterLab-Dockerとしました.
- Add SSH keyを押す
- パスワードを要求されるので入力して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
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"]
-
apt-get install
でopenssh-clientをインストールする
- コンテナ内の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で受け取った変数を登録する
- sshするために必要なconfigファイルとentrypoint.shファイルをコンテナ内にコピーする
COPY config /root/.ssh
COPY init.sh /usr/bin
- コピーしたinit.shファイルを実行する
CMD ["/bin/bash", "/usr/bin/init.sh"]
6. base.txtを記述する
condaでinstallするパッケージを記載するbase.txt
を書いていきます.
base.txt
eli5
lightgbm
xgboost
mlxtend
imbalanced-learn
jupyterlab-notifications
nodejs
git
jupyterlab-git
- jupyterlab-gitを動かすために
nodejs
・git
・jupyterlab-git
を記載する
[3]
7.configを記述する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
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
#!/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なのかはあまり自信がない...
[4]
10. .gitignoreを記述する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内容の反映がリモートリポジトリで確認できる
参考
- jupyterlabとgithubを連携させよう!
- Docker ComposeでSecretを使ってホストのssh秘密鍵を共有する
- 米国AI開発者がゼロから教えるDocker講座
- 米国AI開発者が優しく教えるGit入門講座
謝辞
この記事を書くにあたって,終始熱心な指導をしてくれた友人に感謝の意を表します.
彼はいつも私のどんなお願いも聞いてくれて,どんな悩みも解決してくれます.
仕事が忙しくても,「頼ってくれる人のためなら!」と必ず時間をとってくれます.
あんな人格者,僕はみたことがありません.本当にありがとうございます.
-
できていない方はGitHubにssh接続するまでの手順を参考にしてください. ↩︎
-
failed to load the jupyterlab-git server extension git command not found #952をヒントにしました. ↩︎
-
説明部分以外はGitHub 接続時の ~/.ssh/config の書き方を参考にしてください. ↩︎
-
.DS_Storeをすべてのリポジトリで無視したい場合は,すべてのリポジトリで .DS_Store を gitignore する方法を参考にしてください. ↩︎
Discussion