Dockerを使う上での理解しておくべきコマンド(初心者向け)

# はじめに
本記事はDockerや仮想化コンテナの基本的な仕組みを理解したものの、Dockerコマンドを覚えられない人を対象にし、知っておくべき基本のDockerコマンドについてまとめた。

## Dockerとは
ソフトウェアをコンテナと呼ばれる独立した環境にパッケージ化して実行するためのオープンソースのプラットフォーム

## Dockerを使うメリット
- `ポータビリティ`: Windows、macOS、Linuxなど異なるローカル環境でも、テスト環境や本番環境と同じように動作する
- `軽量性`: 仮想マシンに比べ、コンテナはリソースの消費が少なく、起動も高速
- `再現性`: 開発から本番まで同じ環境を提供し、一貫した動作やテスト結果を確保できる
- `高速デプロイ`: コンテナの起動時間が短く、デプロイが迅速に行える
- `依存関係の解消`: アプリケーションとその依存関係を一つのコンテナ内にまとめることで、依存関係の問題が発生しない
- `CI/CDのサポート`: コンテナを使うことで、継続的インテグレーションやデプロイがより簡単に、効率よくできる

# Dockerの基本コマンドとライフサイクル
イメージの構築し、コンテナの立ち上げて、コンテナを停止させて、イメージを削除するまでの一連の流れをDockerコマンドと紐付けて理解する。

![docker_command.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3807523/d9e488e8-adbc-4dda-3629-74cf30c18005.png)

## イメージの操作
Dockerイメージとはアプリケーションやその依存関係をまとめたコンテナを実行するためのテンプレートのことで、Dockerコマンドを用いて、イメージのダウンロードやDockerfileを用いたビルドをする方法を解説する。

---
### `docker search` イメージの検索
Docker Hubなどのリポジトリから公開されているDockerイメージを検索する。
```bash
$ docker search <リポジトリ名>
```
##### Ex) ubuntuなどのDockerイメージを検索
```bash
$ docker search ubuntu
NAME      DESCRIPTION                                     STARS     OFFICIAL
ubuntu    Ubuntu is a Debian-based Linux operating sys…   17252     [OK]
：

$ docker search mysql
NAME      DESCRIPTION                                     STARS     OFFICIAL
mysql     MySQL is a widely used, open-source relation…   15364     [OK]
：

$ docker search postgres
NAME      DESCRIPTION                                     STARS     OFFICIAL
postgres  The PostgreSQL object-relational database sy…   13749     [OK]
：

$ docker search nginx
NAME      DESCRIPTION                  STARS     OFFICIAL
nginx     Official build of Nginx.     20184     [OK]
：

$ docker search rust
NAME      DESCRIPTION                                     STARS     OFFICIAL
rust      Rust is a systems programming language focus…   1016      [OK]
：
```
`NAME`: イメージの名前
`DESCRIPTION¥` イメージの簡単な説明
`STARS`: イメージの評価（人気度を示すスター数）
`OFFICIAL`: 公式イメージかどうかのフラグ

ちなみに、
`nginx(エンジンエックス)`は、高速で軽量なHTTPサーバー、リバースプロキシ、ロードバランサー、およびメールプロキシとして利用されているオープンソースのソフトウェアをコンテナ化したイメージ
`rust`は、高速性とメモリ安全性を兼ね備えた言語プログラミング言語であるRustの開発や実行を支援するために提供されるDockerイメージ

---
### ①: `docker pull` イメージのダウンロード
Docker Hubや他のリポジトリからDockerイメージをローカル環境にダウンロードする。基本的に既存のイメージを手を加えずそのまま利用する場合に使う。
```bash
$ docker pull <リポジトリ名>:<タグ>
```
`リポジトリ名`: イメージが存在するリポジトリを指定（例：nginx）
`タグ`: イメージのバージョンやタイプを指定するためのオプション（例：1.19, latest）。省略した場合、latest タグ（最新バージョン）がデフォルトで使用される

##### Ex) イメージnginxをダウンロード
```bash
$ docker pull nginx:1.19  
```

---
### ①’: `docker build` イメージの作成
次に説明するDockerfileをもとにして、カスタマイズされたイメージを作成する。
```bash
$ docker build -t <イメージ名>:<タグ> <Dockerfileのあるディレクトリ>
```
`-t`: ビルドしたイメージに名前とタグを付けるために使用する。指定しない場合、Dockerが自動で名前やタグを付けずにイメージをビルドするため、イメージIDを使って操作する必要があり、管理が不便になるので注意する。
##### Ex) /path/to/directoryにあるDockerfileをもとにイメージを作成
```bash
$ docker build -t myapp:v1.0 /path/to/directory
```

### `Dockerfile` Dockerイメージをビルドするためのレシピ
##### Ex) Ubuntuのイメージをベースにpython環境を構築
```Dockerfile
# ベースイメージとしてUbuntu 20.04を使用
FROM ubuntu:20.04

# コンテナ内でパッケージリストの更新とPython関連パッケージのインストール
RUN apt-get update && apt-get install -y \
    python3 \              # Python3のインストール
    python3-pip \          # pipのインストール
    python3-venv \         # 仮想環境作成ツール
    curl \                 # データ取得ツール
    wget \                 # データ取得ツール
    git \                  # バージョン管理ツール
    vim \                  # テキストエディタ
    && apt-get clean && \
    rm -rf /var/lib/apt/lists/*

RUN python3 -m venv venv && \
    . venv/bin/activate && \
    pip install --upgrade pip && \
    pip install -r requirements.txt

# コンテナ内に作業ディレクトリを作成し、そこに移動
WORKDIR /usr/src/app

# ローカルのファイルをコンテナ内にコピー
COPY ./app /usr/src/app

# コンテナ起動時に実行するコマンド
CMD ["python3", "/usr/src/app/app.py"]
```
`FROM`: 通常、Dockerfile では FROM コマンドでベースイメージを指定（例: FROM ubuntu:20.04）
`RUN`: パッケージのインストールやその他のスクリプト実行など、イメージビルド時に実行されるコマンドを定義
`COPY`: ローカルファイルをコンテナ内にコピー
`CMD`または `ENTRYPOINT`: コンテナ起動時にデフォルトで実行されるコマンドを指定

##### Ex) nginxのイメージをもとに環境構築
```Dockerfile
# ベースイメージとして公式のnginxイメージを使用
FROM nginx:latest

# ホストのカスタムHTMLファイルをコンテナ内のNginxのデフォルトの場所に追加
ADD ./index.html /usr/share/nginx/html/

# Nginxがデフォルトで80番ポートで動作するため、このポートを公開
EXPOSE 80

# Nginxサービスをフォアグラウンドで実行
CMD ["nginx", "-g", "daemon off;"]
```
`ADD`: ファイルをコピーするだけでなく、URLからのダウンロードや tar ファイルの解凍が可能。
`EXPOSE 80`: Nginxが使う80番ポートを外部（ホストマシンや他のコンピュータ）からのリクエストを受け取れるように公開します。

`ADD`はホストのファイルやディレクトリをコンテナにコピーすることもできるが、単純なコピーは`COPY`を推奨 

---
### `docker images` イメージの確認
ローカルに保存されているDockerイメージの一覧を表示する。
```bash
$ docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
rust          latest    37568f77c6f5   9 days ago      1.71GB
nginx         latest    195245f0c792   4 weeks ago     193MB
ubuntu        20.04     1a799365aa63   6 weeks ago     101MB
```
`REPOSITORY`: イメージが所属するリポジトリ名。Docker Hubなどのリポジトリから取得したイメージや、自分で作成したイメージがここに表示される
`TAG`: イメージのバージョンやバリエーションを示すタグ（例: latest, 20.04）
`IMAGE ID`: 各イメージを特定するために使用される一意のID
`CREATED`: ビルドやプルを使ってイメージがローカルに保存された日時
`SIZE`: ディスク上に保存されているイメージのサイズ

## コンテナの操作
### ②: `docker create` コンテナを作成
コンテナを作成するが、すぐには起動しないためのコマンド。
```bash
$ docker create [オプション] <イメージ名> [コマンド]
```
##### Ex) nginxのイメージからコンテナを作成
```bash
$ docker create --name my-container nginx
```
`--name`: 作成するコンテナに一意の名前をつける。後でコンテナに対して操作を行う際に、コンテナIDではなく名前を使って操作できるようになる。名前を指定しない場合、Dockerは自動的にランダムな名前を生成する

---
### ③: `docker start` コンテナを起動
一度起動されてから停止しているコンテナや、`docker create` で作成されたコンテナを起動するためのコマンド。すでに存在しているコンテナに対してのみ使用でき、新しいコンテナの作成はしない。
```bash
$ docker start [オプション] <コンテナ名またはコンテナID>
```
##### Ex) バックグラウンドで動作するコンテナを起動
```bash
$ docker start my-container
```
バックグラウンドで動作するサービス（例：Webサーバー、データベースなど）を再起動する場合に使用する。
##### Ex) フォアグラウンド動作のコンテナを再起動
```bash
$ docker start -a my-container
```
`-a`: アタッチモードで再起動する。コンテナの標準出力（stdout）と標準エラー出力（stderr）に接続し、再起動したコンテナの出力がターミナルに表示される。コンテナのログや標準出力をリアルタイムで確認したい場合に使用する
```bash
$ docker start -i my-container
```
`-i`: 標準入力が有効化され、ターミナルからコンテナにコマンドを入力する必要がある

---
### `docker restart` コンテナを再起動
実行中または停止中のコンテナを再起動するためのコマンド。アプリケーションの設定変更後やメモリの問題が発生したときなどに、コンテナを再起動して環境をリセットするために使う。
```bash
$ docker restart <コンテナ名またはコンテナID>
```

---
### `docker attach` 起動中のコンテナに接続
```
$ docker attach <コンテナ名またはコンテナID>
```
すでに起動しているコンテナにターミナルを接続する。この接続は、コンテナの標準入力、標準出力、標準エラー出力に対して行われる。
`docker start` や この後説明する `docker run` コマンドでコンテナをバックグラウンドで起動した場合、後から `docker attach` を使ってそのコンテナに接続(アタッチ)し、プロセスの出力をターミナルでリアルタイムに確認したり、入力が可能な場合は対話的に操作することができる。

---
### `docker exec` コンテナ内でコマンド実行
実行中のコンテナ内で任意のコマンドを実行するためのコマンド
```bash
$ docker exec [オプション] <コンテナ名またはコンテナID>
```
##### Ex) 実行中のコンテナ my-container の中で新しいプロセス（ここでは bash シェル）を起動し、そのシェルに対話型モードで接続
```bash
$ docker exec -it my-container /bin/bash
```
`-it`: 標準入力（stdin）を有効にする`-i`オプションと疑似ターミナルを割り当てる`-t`オプションを組み合わせることで、対話型モードでシェルを起動し、ターミナルで操作できる。(詳細は後述)
通常、システムの環境変数（`PATH`）に`/bin/`があるため 単に`bash`とするだけでも良い。

##### `docker attach` との違い
`attach` は実行中のコンテナの標準入出力に接続する。実行中のメインプロセスに接続するため、すでに動作しているプロセスに対してアタッチするだけの操作。一方、`exec -it` 実行中のコンテナの新しいコマンド（通常はシェル）を起動し、そのコマンドに対話的に接続する。メインプロセスには干渉せず、新しく起動したシェルやコマンドで自由に操作できる。

##### Ex) コンテナ my-container 内の `/usr/src/app` にあるファイルの一覧を表示
```bash
$ docker exec my-container ls /usr/src/app
```

##### Ex) バックグラウンドでコマンドを実行
```bash
docker exec -d my-container some-script.sh
```
`-d`: コンテナ内で some-script.sh をバックグラウンドで実行し、スクリプトが終了を待たずにすぐにターミナルに戻る。 `-d`をつけない場合、コマンドはフォアグラウンドで実行され、コマンドが終了するまでターミナルはブロックされ、終了後に制御が戻る。

##### Ex) 特定のユーザ権限でコマンドを実行
```
docker exec -u www-data my-container whoami
```
`-u`: www-dataユーザーとしてコンテナ内でコマンドを実行

---
### ①ー④: `docker run` 指定したイメージから新しいコンテナを作成・起動し、その中で指定したコマンドを実行
指定したイメージがローカルにない場合、リモートリポジトリからイメージをプルし、コンテナを新しく立ち上げてコマンドを実行する。`docker exec`と同様に、コンテナを起動する際には目的に応じて、対話型モードで起動する`-it`とバックグラウンドで起動する`-d`の2つのオプションを使い分ける。

![docker_run.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3807523/40f63d7d-a644-680b-f356-8ec7b4c2fdf0.png)

### `docker run -it` 対話型モードでのコンテナ実行
`-i (--interactive)`: 標準入力を有効化するオプション。コンテナが標準入力（stdin）を開いた状態で保持されるため、コンテナ内に対してユーザーがコマンドを入力できるようになる。
`-t (--tty)`: 疑似ターミナルを割り当てるオプション。ユーザーはコンテナ内でシェル（bashなど）を通じてコンテナを操作できる。

##### Ex) 対話型モードでコンテナを起動・実行
```bash
$ docker run -it ubuntu /bin/bash
```
`-it`: 対話型モードでシェルを起動
`ubuntu`: 使用するDockerイメージ
`/bin/bash`: コンテナ内で bash シェルを起動
- コンテナ内で直接操作したい場合に使用
- シェルにアクセスし、手動でコマンドを入力して作業できる
- コンテナを終了すると、シェルが閉じてコンテナも停止する

`docker run -it`は新しいコンテナを一時的に作成し、その中でシェルを起動する。シェルを終了すると、そのコンテナも停止する。
### `docker run -d`: バックグラウンド（デタッチドモード）でのコンテナ実行
`-d`: デタッチドモード（バックグラウンドモード）でコンテナを起動するオプション。コンテナはバックグラウンドで実行され、コマンドがすぐに制御を戻す (ユーザーは起動したコンテナのシェルに入らない)
##### Ex) デタッチモードでコンテナを起動・実行
```bash
$ docker run -d -p 8080:80 nginx
```
`-d`: デタッチドモード（バックグラウンドモード）で実行
`-p`: 8080:80: ホストの8080番ポートをコンテナの80番ポートにマッピング
`nginx`: 使用するDockerイメージ
`-d`のデタッチドモードではバックグラウンドで動作するコンテナに外部からアクセスできるようするため、基本的に`-p`オプションでポート番号を指定する。
- バックグラウンドでサービスを実行したい場合に使用
- コンテナはバックグラウンドで実行され、ターミナルの制御がすぐにユーザーに戻る
- Webサーバーやデータベースなどの長時間稼働するサービスを実行するのに適する

デタッチドモードでコンテナを実行した後、コンテナのシェルに入るには`docker exec -it`コマンドを使う。
`docker run -d` + `docker exec -it` でシェルに接続してシェルを閉じても、コンテナのメインプロセスは引き続き動作しているため、コンテナは停止しない。

---
### `docker ps` 稼働中のコンテナ確認
```bash
$ docker ps
```
現在稼働中のコンテナのリストを表示する。表示される情報には、コンテナID、イメージ名、コマンド、作成時間、ステータス、ポート、コンテナの名前などが含まれる。
```bash
$ docker ps -a
```
`-a`オプションを追加することで、停止中のコンテナも含めたすべてのコンテナを表示する。停止済みのコンテナの履歴や、どのコンテナが終了したかを確認できる。

##### Ex) 終了したコンテナを含めたすべてのコンテナの状態を確認する
```bash
$ docker ps -a
CONTAINER ID   IMAGE    COMMAND                   CREATED         STATUS                     PORTS                  NAMES
2744bfc401cf   rust      "bash"                   7 seconds ago   Exited (0) 3 seconds ago                          tender_goodall
72a5b8f04cfc   nginx     "/docker-entrypoint.…"   5 minutes ago   Up 5 minutes               0.0.0.0:8080->80/tcp   sweet_liskov
```
`CONTAINER ID`: コンテナの一意なID
`IMAGE`: 使用されたDockerイメージ名
`COMMAND`: コンテナが実行しているコマンド
`CREATED`: コンテナが作成された時間
`STATUS`: 現在のコンテナの状態（ `Up`: 実行中のコンテナ, `Exited`: 終了したコンテナ, `Paused`: 一時停止中のコンテナ, `Created`: コンテナが作成されたが、まだ起動していない状態）
`PORTS`: ホストとコンテナのポートマッピング
`NAMES`: コンテナの名前

---
### ④: `docker stop` コンテナの停止
実行中のコンテナを安全に停止する
```bash
$ docker stop <コンテナ名またはコンテナID>
```
##### Ex) 実行中のコンテナ my-container を停止する
```bash
$ docker stop my-container
```
- `stop`は、コンテナがプロセスを終了するのを待ってから停止する（デフォルトでは10秒待つ）
- 強制的に即座に停止させたい場合は、`docker kill`を使用する

### ⑤ `docker rm` コンテナの削除
停止したコンテナを削除する
```bash
$ docker rm <コンテナ名またはコンテナID>
```
##### Ex) 停止中のコンテナ my-container を削除する
```bash
$ docker rm my-container
```
- 削除後は`docker ps -a`コマンドで確認しても表示されなくなる
- `-f`オプションで実行中のコンテナを強制的に停止して削除できる
- `docker rm $(docker ps -a -q)`で停止したコンテナを全て削除できる

---
#### 参考資料
- 角間実、図解！ Dockerのツボとコツがゼッタイにわかる本
- [Qiita: Dockerコンテナの作成、起動〜停止まで](https://qiita.com/kooohei/items/0e788a2ce8c30f9dba53)