dockerの超超基本からまとめる #2 ~とりあえず動かしてみよう~

#はじめに
この記事はDocker初心者の私がなんとか自分なりにDockerを動かせるようになるまでの備忘録です。
内容に至らない点は多いと思いますが、生暖かい目で見守ってください。

##前回までのあらすじ
[前回: dockerの超超基本からまとめる #1 ~仮想環境とDocker~](https://qiita.com/kyabe02/items/b90c44d25b05a0f3556e)
Dockerとは？仮想環境とは？コンテナ？イメージ？
現状の認識についてまとめた。

##今回の内容
なんとかしてDocker上でちょっと古いバージョンのpythonを動かしてみる。

##開発環境
MacBook Pro (Catalina 10.15.6)
docker (2.3.0.4)

##今回参考にしたリンク
[DockerでPythonの開発環境を作成してみる　その１](https://ittech-nsnl.hatenablog.com/entry/2019/11/12/233136)

#Docker動かしてみよう
##dockerfileとは
**めちゃくちゃわからん！！！**
わからなさすぎて何がわからないかわからんぞ！！

とりあえずわかっていることを書こう。

- dockerfileによってコンテナの中にどのイメージを持ってくるか決まっている

これだけしかわからない。

では今回使うdockerfileをみてみよう。

```:dockerfile
# ベースイメージ
FROM python:3.5.9

# pipをアップグレード
RUN pip install --upgrade pip

# 作業ディレクトリ作成
WORKDIR /workdir

# ポート
EXPOSE 8080
```

うーん、見た感じ大文字がコマンドでその後に色々打ち込んでいる様子？
[dockerの公式ドキュメント](https://docs.docker.com/engine/reference/builder)を参考に解読してみます。

| コマンド| 意味 |
|:-:|:--|
|FROM| ベースとなるイメージを選択する |
|RUN| 現在のイメージの上に任意のコマンドを実行する|
|WORKDIR| 作業用のディレクトリを作成する  |
|EXPOSE| listenするポート番号を設定しておく|

わかったような、わからないような。

今回のdockerfileではpythonの3.5.9を使おうとしている。
そして、なぜかpipをアップデートして、作業用のディレクトリを作成して、なぜかポートを開けている、と。

やっていることはわかったが、なんのためにやっているのかはよくわからない。
とりあえず先に進もう。

##dockerをbuildする
簡単に言ってくれますね。
dockerをbuildするとは一体なんぞや。

dockerがdockerfileの設定に基づいて、イメージを作ることをdocker buildと表現する。
先ほどのdockerfileによるとpythonの3.5.9のイメージが必要みたい。
`docker images`で現在の取得しているイメージの一覧を確認できる。

```
$ docker images
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
python                               3.5.9               d97bc12bd39e        2 days ago          910MB
```

pythonの3.5.9がきちんと取得できていることがわかる。

ここまででbuildの準備ができたので、早速buildをしてみる。
コマンドは`docker build [-t コンテナの名前] {dockerfileのある場所}`だ。
コンテナの名前は設定しないと~~*かっこいい*~~名前を勝手につけてくれるが、使いにくいので自分で名前をつけよう。

```
$ docker build -t pythondev .
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM python:3.5.9
 ---> d97bc12bd39e
Step 2/4 : RUN pip install --upgrade pip
 ---> Running in 525799f95f6d
Requirement already up-to-date: pip in /usr/local/lib/python3.5/site-packages (20.2)
Removing intermediate container 525799f95f6d
 ---> c2d7a316ec79
Step 3/4 : WORKDIR /workdir
 ---> Running in eeb6a9396ea6
Removing intermediate container eeb6a9396ea6
 ---> 810f2c4617a1
Step 4/4 : EXPOSE 8080
 ---> Running in acd9e412eea5
Removing intermediate container acd9e412eea5
 ---> 5c48c0526e48
Successfully built 5c48c0526e48
Successfully tagged pythondev:latest
```

何しているか細かいことはよくわからないが、dockerfileの記述通りの処理をしてくれてる感じがする。

```
$ docker images 
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
pythondev                            latest              5c48c0526e48        3 minutes ago       916MB
```
きちんとイメージが作成されていることも確認する。
これでpythonの3.5.9の環境のイメージが完成。


###検証

現在取得できていないpython3.5.8にdockerfileを書き換えてbuildしてみたところ、どうやら足りないイメージは自動で落としてくれるみたい。便利ですね。

```
$ docker build .
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM python:3.5.8
3.5.8: Pulling from library/python
c7b7d16361e0: Pull complete 
b7a128769df1: Pull complete 
1128949d0793: Pull complete 
667692510b70: Pull complete 
bed4ecf88e6a: Pull complete 
94d1c1cbf347: Pull complete 
765d0dc09bbf: Pull complete 
65bf6e648924: Pull complete 
66c62c8268bd: Pull complete 
Digest: sha256:46dbbb6c23a9069da0fae6d5afb74483e0344c1fbc796a18507c52517b5438db
Status: Downloaded newer image for python:3.5.8
 ---> 0688d5a54cf4
```

ついでなのでイメージの削除方法について[別記事](https://qiita.com/kyabe02/items/deaab84a320e909abb78)にまとめた。

##dockerをrunする
buildをすることで作成したイメージを使って実際に使用するコンテナを作成していく。

```
$ docker run -it --name pythonwork pythondev
Python 3.5.9 (default, Jul 22 2020, 13:58:49) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> exit()
$ docker ps -a
CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS                      PORTS                                      NAMES
c205807cc2eb        pythondev                   "python3"                43 seconds ago      Exited (0) 12 seconds ago                                              pythonwork
```
`-it`のオプションでコンテナの内部に入れるらしい(？)
`--name`のオプションによって任意の名前がついたコンテナが作成されていることがわかる。
このコンテナにもう一回入るには`docker start {コンテナ名}`でコンテナを起動した上で`docker exec -it {コンテナ名} {コマンド}`で入ることができる。

```
$ docker start pythonwork
pythonwork
$ docker exec -it pythonwork bash
root@c205807cc2eb:/workdir# 
```
ここではコマンドに`bash`を使うことでshellコマンド打てる状態になっている。
さらにdockerfileで記述した`workdir`のディレクトリに入っているのがわかる。

何はともあれ、これでdocker上でpython3.5.9が動いたぞ！

##外部ファイルとの連携
**だがしかし**、これコーディングできないよね？
当然VScodeもvimもemacsも入っていない環境なので、ろくなコードが書けない。
そこで、外部ファイルとコンテナを同期する方法があるらしい。

`$ docker run -it -v /Users/kyabe/python/bert/src:/workdir --name pythonwork pythondev /bin/bash`

このコマンドを動かすとローカルの`/Users/kyabe/python/bert/src`と`/workdir`をリンクさせることができる。

実際にコンテナの中身を見てみるとdockerfileが既に入っていることがわかる。

```
$ docker run -it -v /Users/kyabe/python/bert:/workdir --name pythonwork pythondev /bin/bash
root@dbc8113d1f3b:/workdir# ls
dockerfile
```
これでローカルで編集したコードをdocker上で動かせるようになった！

#まとめ
自分でdockerの環境を作った

- dockerfileを作成
- buildしてイメージを作成
- runでコンテナを作成
    - -itでそのまま中に入れる
- exitで脱出
- startで再開
- このままだとコーディングできないので、ローカルのディレクトリとリンクさせた

#わからないこと
- dockerfile謎すぎ
- -itとはなんぞ
- なんでデフォルトでpython3が起動するんだ？
    - 多分`docker ps -a`でみたときの`COMMAND`のところのコマンドが実行されているのかな
    - そしてこれはおそらくdockerfileのCMDなのかなっていう予想