Dockerコンテナからjupyter notebookに入るまでのコマンド長すぎて面倒だからBashスクリプトですっきりさせてみた

**頻繁に使うのにくそ長くて、尚且つフラグ等が変化しない**Docker関連のコマンドにうんざりしている方におすすめ。
既にいろんな人がやっているが、起こりうるエラーをすべて通ったんじゃないかと思うほど、エラーに見舞われた。
誰かの役に立ってくれたらうれしい。

（修正後）
この記事を8/27の早朝に公開したところ、瞬時にTwitterの心優しい方がDocker-composeで行ったほうが、ポート等の管理のしやすさの観点でおすすめということを教えていただきましたので、それも追加し、大幅修正を加えました。（私はDocker-composeを、複数のコンテナがある場合にのみ使うものだとばかり固い考えをしていました…ありがとうございます。）

# まずDocker-composeではなく、Dockerを使っている方へ
## 何ができるようになるのか
ホームディレクトリで
```
bash bin/example.sh
```
とするだけで、設定しておいたコンテナに入れる！
（ポートとかを指定する人はDocker-composeを使ったほうが管理が楽で、打つ文字数も減っていいですが、こっちはそれほど魅力はないかも。（ロマン重視）

## 方法
- ホームディレクトリである`C:\Users\ユーザ名\`に、`bin`ディレクトリを作成したうえで、`example.sh`を作る。

- `example.sh`の中身を以下のように編集する
※中身に普段使う`docker run`コマンドを書くだけです。あくまでこれは例です。（1行目を忘れないでください）
```bash
#!/bin/bash
docker run --rm -it IMAGE
```

<br>
<br>
さて、ここからが本番。

# Docker-composeを使う方へ
## これまで
開発を再開する度に、
- `docker-compose up -d`
- `docker-compose exec app bash`
- `jupyter notebook --port=8888 --ip=0.0.0.0 --allow-root`
を手打ちしていました。
開発を一時中断する際には、少なくとも、
- jupyter notebookを閉じる
- `exit`(コンテナからでる）
- `docker-compose down`
の動作が必要でした。（一回だけならまだしも、何回も必要となると、プログラマーの血が騒ぎました。）
## 結果
`docker-compose.yml`ファイルがあるディレクトリに移動した後に、
```
bash bin/crun.sh
```
と打つだけで、jupyter notebookを自動で起動させ、jupyter notebookを出たときは自動で`docker-compose down`までしてくれる。
実質コマンドラインで実行したコマンドはこれだけ。気持ちいい～

## 方法
### docker-compose.yml
- まず、`docker-compose.yml`ファイルを作成・編集します。
```docker-compose.yml:
#Composeのバージョンを指定
version: '3'
services:
  app:
    image: image-name
    ports:
      - "8888:8888"
    volumes:
      - /c/users/...:/app
    tty: true
```
この[サイト](https://y-ohgi.com/introduction-docker/3_production/docker-compose/)を参考にしたところ、`exited with code 0`の問題に直面しました。（厳密にはエラーではない）
必要に応じて最後の`tty: true`を付け足してください。



### Bashスクリプト
- 次に、一つ目に紹介した方法とは異なり、docker-compose.ymlがあるディレクトリに`bin`ディレクトリを作り、`example.sh`を作る。
- example.shを以下のように編集します。（念のため、それぞれの行の解説を書いておきますが、基本的に人によって多かれ少なかれ変化するものだと思います。）


```example.sh:
#!/bin/bash
#コンテナを作成して開始する
docker-compose up -d
#コンテナに入るのとコンテナ内で""内のコマンドを実行するように引数を渡している
winpty docker-compose exec cell-pj bash -c "jupyter notebook --port=8888 --ip=0.0.0.0 --allow-root --NotebookApp.token=''"
#exit codeを受け取る
EXIT_CODE=$?
#コンテナおよび、ネットワーク関連をすべて破棄
docker-compose down
#終了
exit EXIT_CODE
```




`EXIT_CODE=$?`の`$?`は[このWebサイト](https://www.cyberciti.biz/faq/linux-bash-exit-status-set-exit-statusin-bash/#:~:text=You%20can%20use%20special%20shell%20variable%20called%20%24%3F%20to%20get%20the%20exit%20status%20of%20the%20previously%20executed%20command.)によると
>You can use special shell variable called `$?` to get the exit status of the previously executed command. 
>（直前に実行されたコマンドの終了ステータスを取得するために呼び出される特別なシェル変数`$?`を使用できます。）


- あとは`docker-compose.yml`があるディレクトリで
```
bash example.sh
```
とするだけで、結果に述べたように一部の挙動が自動化される。


# エラー集
## command not found
### 問題
最初、コマンドプロンプト上でvimを用いて編集しましたが、バックスペースが使えなくなったり、`bash example.sh`とコマンドを叩いても`command not found`と返されました。

Bashスクリプトを実行するとこのようなエラー文が返ってくる。
```
The command 'docker' could not be found in this WSL 2 distro.
We recommend to activate the WSL integration in Docker Desktop settings.

For details about using Docker Desktop with WSL 2, visit:

https://docs.docker.com/go/wsl2/
```

どうやらとっても人気のissueらしい。即諦めました。
解決したいと思う方はこちらを参考にしてみるといいかもしれません。
- [GitHub - "The Windows Subsystem for Linux instance has terminated."](https://github.com/microsoft/WSL/issues/5110)

### 解決法
解決法として、Git Bashで編集して、`bash example.sh`で実行するとなんの問題もなくいけました。
（厳密には解決してないけど…ヨシ）

## exite with status 0
### 問題
Dockerコンテナが立ち上がってもすぐに閉じてしまう。
### 解決法
```docker-compose.yml:
version: '3'
services:
  app:
    image: image-name
    ports:
      - "8888:8888"
    volumes:
      - /c/users/...:/app
    tty: true #<-----appの中にこいつを書き込む
```
その他の解決法はこの[サイト「docker-composeでexit with status 0の解決法」](https://zenn.dev/torkralle/articles/388ae878cb5f8b)にまとめらているので、参考までに。

# 参考にした記事
- [シェルスクリプトを作成してpythonファイルを複数回動かす](https://qiita.com/suzuki_y/items/52160149baae1ac3d73c)
- [how to run python script without typing 'python ...'](https://stackoverflow.com/questions/4993621/how-to-run-python-script-without-typing-python)
- [stackoverflow - exited with code 0 docker](https://stackoverflow.com/questions/44884719/exited-with-code-0-docker)
- [入門 Docker - nginxを立ち上げるサンプル](https://y-ohgi.com/introduction-docker/3_production/docker-compose/)
- [えやみぐさ - docker-compose run --rm終了時に他のコンテナも削除する](https://zenn.dev/torkralle/articles/388ae878cb5f8b)
# 謝辞
- インターンシップ先のインフラつよつよの方
Bashスクリプトを使う大きなきっかけを与えてくださって本当にありがとうございます。
- TwitterにてDocker-composeでの改善策を教えてくださった[@hpp_ricecake](https://twitter.com/hpp_ricecake)さん
管理のしやすさが爆上がりしました。ありがとうございます。