docker版のjupyterにSwiftを入れてみた。

# はじめに
最近Macを買いまして、せっかくなのでSwiftを学習しようと
思い立ちました。
で、jupyterで使えれば便利よねと思い、
普段使っているdocker版jupyterにswiftを突っ込んでみました。
※うまく動かなかったのでちゃんと最新版のSwift for TensorFlowを
　使うようにしました。

# レシピ

- debian 10
- jupyter-minimalから育て上げたdockerイメージ(jupyter/mylangs)
- Swift for TensorFlow
- swift-jupyter

# 参考

[How to Install Swift in Debian 10](https://linuxhint.com/install-swift-debian/)
[GitHub - tensorflow/swift: Swift for TensorFlow](https://github.com/tensorflow/swift)
[GitHub - google/swift-jupyter](https://github.com/google/swift-jupyter)

# 手順

## Swift for TensorFlowのインストール

### 稼働中のdockerコンテナのプロンプトに入る

以下のコマンドでコンテナのプロンプトに入れます。
コンテナ名は既定で `jupyter_notebook_1` となっているはずです。

```bash
$ docker exec -it -e GRANT_SUDO=yes --user root jupyter_notebook_1 bash
```

### 依存パッケージのインストール

うちの子の環境ではPython3.9が入っていますが、
Swift for TensorFlow はPython3.6のライブラリを要求します。
とりあえずaptで入れられるものはaptでインストールし、
Python3.6関連のライブラリは個別にダウンロードして
`dpkg -i` で突っ込みます！
Ubuntu18.04のパッケージですがまあdebianでもいけます。
というかいけました。

```bash
# wget http://archive.ubuntu.com/ubuntu/pool/main/libf/libffi/libffi6_3.2.1-8_amd64.deb
# wget http://archive.ubuntu.com/ubuntu/pool/main/r/readline/libreadline7_7.0-3_amd64.deb
# wget http://archive.ubuntu.com/ubuntu/pool/main/p/python3.6/libpython3.6-minimal_3.6.5-3_amd64.deb
# wget http://archive.ubuntu.com/ubuntu/pool/main/p/python3.6/libpython3.6-stdlib_3.6.5-3_amd64.deb
# wget http://archive.ubuntu.com/ubuntu/pool/main/p/python3.6/libpython3.6_3.6.5-3_amd64.deb
# apt update
# apt install libncurses5 libncursesw5　clang libcurl4 libpython2.7
# dpkg -i libffi6_3.2.1-8_amd64.deb
# dpkg -i libreadline7_7.0-3_amd64.deb
# dpkg -i libpython3.6-minimal_3.6.5-3_amd64.deb
# dpkg -i libpython3.6-stdlib_3.6.5-3_amd64.deb
# dpkg -i libpython3.6_3.6.5-3_amd64.deb
```

と順にインストールします。
依存関係があるので順番に注意です。

### Swift for TensorFlowをインストールする

以下のコマンドを順次実行。ダウンロードして解凍するだけ。

```bash
# cd /opt
# wget https://storage.googleapis.com/swift-tensorflow-artifacts/releases/v0.13/swift-tensorflow-RELEASE-0.13-ubuntu18.04.tar.gz
# tar xzf swift-tensorflow-RELEASE-0.13-ubuntu18.04.tar.gz
# mkdir swift
# mv usr swift
```

### 環境変数の設定

`.bashrc` ファイルを編集し、
環境変数PATHにSwiftのパスを追加しておく。

```bash:.bashrc
export PATH=${PATH}:/opt/swift/usr/bin
```

`.bashrc` の内容を反映する。

```bash
# source ~/.bashrc
```

### ひとまずSwiftの動作確認

以下のようになればOK

```bash
# swift --version
Swift version 5.3-dev (LLVM e86f8c8c72a2a82, Swift 6a6f972f7fcf51d)
Target: x86_64-unknown-linux-gnu
```

## swift-jupyterのインストール

### swift-jupyterをインストールする

以下のコマンドを実行。

```bash
# cd /opt
# git clone https://github.com/google/swift-jupyter.git
# cd swift-jupyter
# python3 -m venv venv
# . venv/bin/activate
# pip install -r requirements.txt
# python register.py --sys-prefix --swift-toolchain /opt/swift
```

最後までコマンドを実行すると以下のようなjsonが吐かれる。

```json:kernel.json
{
  "argv": [
    "/opt/swift-jupyter/venv/bin/python",
    "/opt/swift-jupyter/swift_kernel.py",
    "-f",
    "{connection_file}"
  ],
  "display_name": "Swift",
  "language": "swift",
  "env": {
    "PYTHONPATH": "/opt/swift/usr/lib/python3/dist-packages",
    "LD_LIBRARY_PATH": "/opt/swift/usr/lib/swift/linux",
    "REPL_SWIFT_PATH": "/opt/swift/usr/bin/repl_swift",
    "SWIFT_BUILD_PATH": "/opt/swift/usr/bin/swift-build",
    "SWIFT_PACKAGE_PATH": "/opt/swift/usr/bin/swift-package"
  }
}
```

`/home/jovyan/.local/share/jupyter/kernels` に
`swift` フォルダを作成し、
その中に `kernel.json` というファイル名で
先ほど吐かれたjsonを保存する。

まあ、

```bash
$ mkdir /home/jovyan/.local/share/jupyter/kernels/swift
$ python register.py --sys-prefix --swift-toolchain /opt/swift > /home/jovyan/.local/share/jupyter/kernels/swift/kernel.json  
```

でもいいような気もする。

### swift-jupyterの動作確認

こんな感じでSwiftが追加されていればOK。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298004/6aa57b88-878f-9d7d-3d0a-ec658a2c8fe8.png)

## dokerイメージの作成

### コンテナの停止

以下のコマンドでコンテナを停止。
うっかり `down` しちゃうとせっかく作ったコンテナが消えちゃうので注意。
`docker-compose` で楽してます。

```bash
$ docker-compose stop
```

### イメージの作成

以下のコマンドで現在のコンテナの内容でイメージを作成
けっこう時間がかかるかも。

```bash
$ docker commit jupyter_notebook_1 jupyter/mylangs:latest
```

### コンテナの削除

以下のコマンドでコンテナの削除を行う。

```bash
$ docker-compose down
```

### コンテナの起動

以下のコマンドでコンテナを起動する。

```bash
$ docker-compose up -d
```

## おまけ

ちなみに今運用している `docker-compose.yml` の中身はこんな感じです。

```yml
version: "3"
services:
  notebook:
    image: jupyter/mylangs
    ports:
      - "9999:8888"
    environment:
      - TZ=Asia/Tokyo
      - JUPYTER_ENABLE_LAB=yes
    volumes:
      - ./work:/home/jovyan/work
    privileged: true
    command: start-notebook.sh --NotebookApp.token=''
```