python＆jupyterlabのコンテナ構築

## はじめに
Jupyterlabを使いPython環境を利用するコンテナを構築したので、その時の手順をメモとして残しておく。


## 実行環境
【Docker導入環境】
　　・Ubuntu 18.04 LTS（GCP上）
　　・docker 19.03.13


## 手順
１．環境準備
２．Pythonコンテナを構築
３．SSHサーバー機能を追加
４．JuypterlabとSSHの同時起動


## １．環境準備

**GCP上にVMインスタンスを作成**

**dockerのインストール**
　[【Dockerコンテナ内のUbuntuではsystemctlは使えない】](https://qiita.com/smiler5617/items/2a33d1aba0174480e9d3)の手順１を参考に。


## ２．コンテナ構築

ベースイメージを取得

```shell:
$ docker image pull python:3
```

コンテナを作成

```shell:
$ docker container run -it -d --name python-con1 python:3
```

起動中コンテナの中に入り、いくつかのパッケージをインストール

```shell:
$ docker container exec -it python-con1 /bin/bash
```

```shell:コンテナ内で実行するコマンド
# パッケージをインストール
pip install numpy pandas jupyterlab

# コンテナから出る
exit
```

変更後のコンテナイメージを作成

```shell:
# コンテナの停止
$ docker container stop python-con1

# 現在のコンテナをイメージ化
$ docker container commit python-con1 python-img:ver1
```

イメージが作成できている事を確認

```shell:
$ docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
python-img   ver1      34ad01ba7efb   41 seconds ago   1.19GB
python       3         d1eef6fb8dbe   2 weeks ago      885MB
```

作成したイメージから再度コンテナを作成する。
　※その際に、ポートマッピングやホスト側のディレクトリをマウント

```shell:
$ docker container run -it -d \
-p 8888:8888 \
#-v
--name python-con2 python-img:ver1
# jupyter lab --ip=0.0.0.0 --allow-root --LabApp.token=""
```

コンテナに入りJuypterlabを起動。
　※上記のコンテナ作成のタイミングで起動しても良い。(コメントアウト部分)

```shell:
$ docker container exec -it python-con2 /bin/bash
```

```shell:コンテナ内で実行するコマンド
jupyter lab --ip=0.0.0.0 --allow-root --LabApp.token=""
```

この状態でホスト側の8888番ポートにアクセスして、juypterlabが開かれれば問題なし。
　※ホスト側の8888番ポートは開放しておく。
　
**ここまで確認できたら、コンテナは一旦削除。**


## ３．SSHサーバー機能を追加

各コンテナに対して直接操作を行える様にするためにSSHサーバーもインストールし、SSH接続ができる状態にしておく。

```shell:
# コンテナ作成
$ docker container run -it -d --name python-con2 python-img:ver1

# コンテナに入る
$ docker container exec -it python-con2 /bin/bash 
```

```shell:コンテナ内で実行するコマンド
apt update
apt install -y openssh-server
apt install nano
```

サービスの起動に必要なフォルダを作成、共通鍵の登録
 ※鍵の生成は`Tera Term`などでしておく。今回はrootユーザーでアクセスする想定。

```shell:コンテナ内で実行するコマンド
mkdir /var/run/sshd
mkdir /root/.ssh/
nano /root/.ssh/authorized_keys
# 鍵の中身は公開鍵の[.pub]ファイルの中身をコピー
```

変更後のコンテナイメージを作成

```shell:
# コンテナの停止
$ docker container stop python-con2

# 現在のコンテナをイメージ化
$ docker container commit python-con2 python-img:ver2
```

イメージが作成できている事を確認

```shell:
$ docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
python-img   ver1      34ad01ba7efb   41 seconds ago   1.19GB
python       3         d1eef6fb8dbe   2 weeks ago      885MB
```

作成したイメージから再度コンテナを作成する。
　※その際に、ポートマッピングやホスト側のディレクトリをマウント

```shell:
$ docker container run -it -d \
-p 8888:8888 \
-p 20022:22 \
--name python-con3 python-img:ver2 \
/usr/sbin/sshd -D
```

この状態で、ローカルPCの`Tera Term`などからdockerホストの20022ポートにSSH接続できれば正常に動いている。
　※ホスト側のポートを開放しておくこと。


## ４．JuypterlabとSSHの同時起動

**JuypterLab**と**SSHサーバ**が立ち上がるshファイルを作成しておき、コンテナ作成時の`CMD`上書き命令で、そのshファイルを実行する事でコンテナの再起動時に毎回自動でサービスが立ち上げる様にしたかったが、上手くいかなかった。
原因はshファイル自体が実行完了するとコンテナが落ちてしまうため。無限ループする様なshファイルも試してみたが、結局うまく行かなかったので別の方法で実施することにした。

まずは下記のコマンドでコンテナを作成し、コンテナ起動のタイミングでSSHサービスが立ち上がる様にしておく。

```shell:
docker container run -it -d \
-p 8888:8888 \
-p 20022:22 \
--name 【任意のコンテナ名】 python-img:ver2 \
/usr/sbin/sshd -D
```

そして、その後SSH接続して以下のコマンドを実施する。

```shell:
jupyter lab --ip=0.0.0.0 --allow-root --LabApp.token=""
```

　※別ブラウザで立ち上げたコンソールからコンテナに入って上記のコマンドを実行しても良いが、個人的には上記のやり方の方が一手間少ないと思う。