Dockerの基本的な利用法-(2)基本のコマンド


## はじめに

これはシリーズ記事です。  
前回記事 ↓

https://qiita.com/k_nulluo/items/e6b4d6f20562e67c133d

前回記事でコマンドの見方の基本を説明したので、今回記事からは、Docker を利用するうえで頻出の基本コマンドを解説していきます

## イメージを操作するコマンド

上位コマンドは`image`です

### イメージの取得(image pull)

```sh
# 基本形
$ docker image pull イメージ名[:タグ]

# 省略形
$ docker pull イメージ名[:タグ]

# 例
$ docker image pull httpd:2.4.62

## タグを省略すると latest を取得しにいく
## (下記の２つのコマンドはどちらも同じ動きをする)
$ docker image pull httpd:latest
$ docker image pull httpd

## デフォルトでは Docker Hub からイメージを取得するが、別のレジストリから取得することもできる
## 下記の例では、ポート5000を開放したローカルのレジストリからイメージを取得している
$ docker pull myregistry.local:5000/testing/test-image
```

### イメージの詳細情報を表示する(image inspect)

```sh
# 基本形
$ docker image inspect イメージ名[:タグ]

# 省略形
$ docker inspect イメージ名[:タグ]
```

この手順ではローカルにプル済みのイメージしか詳細情報を見れないことに注意

### イメージの一覧を見る(image ls)

```sh
# 基本形
$ docker image ls

# 省略形
$ docker images
# (docker ls ではないので注意)
```

### イメージの構築(image build)

```sh
# 基本形
$ docker image build -t イメージ名 構築コンテクスト

# 省略形
$ docker build -t イメージ名 構築コンテクスト

## Dockerfileはデフォルトでは`構築コンテクスト/Dockerfile`を使用するが、ファイル名を変更する場合は`-f`オプションを使用する
$ docker build -t イメージ名 -f 使用するDockerfileの名前 構築コンテクスト
```

`構築コンテクスト`は、イメージ構築の際に使用するファイルが置かれている場所で、ディレクトリパスや URL が指定可能  
Dockerfile は単一コンテナの内容と起動時の挙動を定義したファイルで、これを参照することで`docker build`でイメージが構築できる。  
言い換えると開発に必要な環境の要件を記載した Dockerfile を開発者に配布することで、全開発者間の環境を統一することができたりします。

Dockerfile の書き方は後日、記事にする予定

<!-- TODO:Dockerfile の書き方の記事を書く -->

### イメージの削除(image rm)

```sh
# 基本形
$ docker image rm イメージ名

# 省略形
$ docker rmi イメージ名
# (docker rm だとコンテナの削除になるので注意)
```

## コンテナを操作するコマンド

上位コマンドは`container`です

### コンテナの一覧を表示する(container ls)

```sh
# 基本形
$ docker container ls [オプション]

# 省略形
$ docker ps [オプション]
## (docker ls ではないので注意)

# 例
$ docker ps -a
## -a オプションは いま、実行中でない（停止中の）コンテナも含めて、全てのコンテナを表示する
```

### イメージからコンテナを作成(container create)

```sh
# 基本形
$ docker container create [オプション] イメージ名

# 省略形
$ docker create [オプション] イメージ名

# 例
$ docker create --name CONTAINER-HTTPD httpd
## イメージhttpdからCONTAINER-HTTPDという名前のコンテナを作成する

```

`docker container create`から作成した場合、コンテナはまだ起動していない(停止中の状態で作成される)

### コンテナを起動する(container start)

```sh
# 基本形
$ docker container start [オプション] コンテナ名

# 省略形
$ docker start [オプション] コンテナ名
```

### コンテナを停止する(container stop)

```sh
# 基本形
$ docker container stop コンテナ名

# 省略形
$ docker stop コンテナ名
```

### コンテナを削除する(container rm)

```sh
# 基本形
$ docker container rm コンテナ名

# 省略形
$ docker rm コンテナ名
```

起動中のコンテナを削除しようとするとエラーになります。先にコンテナを停止してから`docker rm`しましょう

```sh
# 実行中のコンテナを削除しようとすると、エラーが出て削除失敗する
$ docker rm WORKING-CONTAINER
Error response from daemon: cannot remove container "/WORKING-CONTAINER": container is running: stop the container before removing or force remove
```

### コンテナ内でコマンドを実行する(container exec)

```sh
# 基本形
$ docker container exec [オプション] コンテナ名

# 省略形
$ docker exec [オプション] コンテナ名

# 例
## コンテナ WORKING-CONTAINER内に入って `echo コマンドを実行する`
$  docker exec -it WORKING-CONTAINER sh
# echo hoge && echo fuga
hoge
fuga
```

#### `docker container exec`でよく使うオプション

| オプション | 機能                                                     |
| ---------- | -------------------------------------------------------- |
| `-i`       | アタッチしていなくても、標準入力を開き続ける             |
| `-t`       | 疑似 TTY を割り当てる                                    |
| `-d`       | デタッチド・モード(バックグラウンドでコマンドを実行する) |

### イメージの取得からコンテナ起動までをまとめて行う(container run)

さて、ここまでの説明で、イメージを取得するところから、イメージからコンテナを作成して、コンテナを起動するところまでに必要なコマンドは一通り説明しました。ただ、そのためには下記の４つのコマンドを覚える必要があります。

- `docker image pull`
- `docker image build`
- `docker container create`
- `docker container start`

でも、コマンドをたくさん覚えたり、入力するのは面倒です。「イメージを指定してコンテナを起動する」ことを最短で行うコマンドがあれば便利ですね。  
実は、それが`docker container run `です.(上位コマンドを省略すると`docker run`)  
上記の４つのコマンドのすべての機能を内包しています。

つまり、`docker run`は、コマンド一発実行しただけで、イメージをレジストリから取得する場合は`docker pull`の動きを、イメージを Dockerfile から構築する場合は`docker build`の動きをしますし、そうやって得られたイメージを元にコンテナ作成(`docker create`と同じ動き)を行い、作成されたコンテナを起動(`docker start`と同じ動き)してくれるわけです。便利ですので、これは是非覚えましょう

:::note info

#### だったら最初から`docker run`コマンドだけ教えてくれたらよかったのでは？

…と言われそうですが、わざわざ遠回りして説明したのは理由があって、いきなり`docker run`コマンドから入ると内部で行われている処理の種類が多すぎて、初心者はコマンドの結果何が起きているのか、過程が分かりにくくなるのではと思ったからです。  
実際、筆者は分からなくなったので`docker pull`,`docker build`,`docker create`,`docker start`と一つずつコマンドを実際に打ち込みながら何をやっているか理解することで、ようやく`docker run`の機能を理解する事ができました。
:::

```sh
# 基本形
$ docker container run [オプション] イメージ名

# 省略形
$ docker run [オプション] イメージ名

# 例
## httpd(Apache)のイメージを取得し、ポートは8080(ホスト側)と80(コンテナ側)をつなぎ、バックグラウンドで起動する
$ docker run --name CONTAINER-APACHE -p 8080:80 -d httpd
```

#### `docker container exec`でよく使うオプション

| オプション                                         | 機能                                                                         |
| -------------------------------------------------- | ---------------------------------------------------------------------------- |
| `--name` コンテナ名                                | コンテナにつける名前                                                         |
| `-i`                                               | アタッチしていなくても、標準入力を開き続ける                                 |
| `-t`                                               | 疑似 TTY を割り当てる                                                        |
| `-d`                                               | デタッチド・モード(バックグラウンドでコマンドを実行する)                     |
| `-p` ホストのポート番号:コンテナのポート番号       | ポート番号の指定                                                             |
| `-v`=[ホスト側ディレクトリ:]コンテナ側ディレクトリ | ボリュームのバインド・マウント(ホスト側ディレクトリは絶対パスにするのがよい) |
| `-e` 環境変数名=値                                 | 環境変数の指定                                                               |
| `--env-file` ファイル名                            | 環境変数を読み込むファイルの指定                                             |

##### `docker container exec`で環境変数を設定する場合

直前の表にも簡単に説明を記載したが、補足が必要なので下記のオプションの使い方をもう少し掘り下げて説明する。

- `-e`
- `--env-file`

下記の形でオプションを渡してやるとコンテナ起動時の環境変数を設定することができる。

```sh
$ docker run -e 環境変数名=値 ...

# 例
## postgres のイメージを取得し、CONTAINER-POSTGRES という名前でコンテナを作成し、
## ポートは(ホスト側とコンテナ側ともに)5432でつないで、
## postgreSQLのルートユーザーはtaro, ルートパスワードはpassとして、
## バックグラウンドで起動して標準入力から操作可能にする
$ docker run --name CONTAINER-POSTGRES -p 5432:5432  -e POSTGRES_PASSWORD=pass -e  POSTGRES_USER=taro -dit postgres
# => これを実行すると、実際にローカルでpostgreSQLのデータベースが起動するので、
#   postgreSQLデータベースに接続可能な環境があれば、接続して確認することができます。
$ psql -h localhost -U taro
Password for user taro:
psql (14.13 (Homebrew), server 17.2 (Debian 17.2-1.pgdg120+1))
WARNING: psql major version 14, server major version 17.
         Some psql features might not work.
Type "help" for help.

taro=# select
```

※ postgreSQL をよく知らないので psql が分からないという方はこちらを参照  
 <https://www.postgresql.jp/docs/9.4/app-psql.html>

また、この環境変数を外部ファイルから渡したい場合は`--env-file`オプションを使えばよい。

```sh
docker run  --env-file ファイル名 ...
```

具体的な使用例は下記のようにする。  
まず下記の内容の.env ファイルをカレントディレクトリに保存する。

```txt:.env
POSTGRES_PASSWORD=pass
POSTGRES_USER=taro
```

そして、下記コマンドを実行すると先程の例と同様に postgreSQL のデータベースが、ルートユーザーは taro, ルートパスワードは pass で起動する

```sh
 docker run --name CONTAINER-POSTGRES -p 5432:5432 --env-file ./.env -dit postgres
```

## 終わりに

イメージを取得して単一のコンテナを起動するところまでは、（だいぶ端折りつつも）一応説明できました  
が、自分の用途に合わせてイメージをいじる方法については説明してないので、これだとまだ出来ることが少ないです

よって、次回はその点の解決策として Dockerfile の編集方法の解説を予定しています。