ゼロから始めるDocker入門

## はじめに

実務でDockerの使用をしていますが

- ***「雰囲気で使用してしまっている」***
- ***「言語化できていない」***

ところがあったので基礎を学習し直しました。

実際に使用してみると自分の理解できていない部分が見えてくると思うので
私の記事を読んでいただけた方は自分の環境でも試してみると
内容が理解しやすいかもしれません。

記事のボリュームが大きくなりすぎてしまうため
記事を三部構成にしました。(途中から読んでも理解できる構成にしています。)

1. [ゼロから始めるDocker入門](https://qiita.com/suzu12/items/315fba934de11af826bd) 　←今回はここ
2. [はじめてのDockerfile](https://qiita.com/suzu12/items/c4bc47c0df6ec9b9290b)
3. [はじめてのDocker compose](https://qiita.com/suzu12/items/4ec2cc8c1a7c23aa112b)

以上のような形で執筆いたします。


### 対象読者

- Dockerを使ってみたいけどどのように使えば良いかわからない方
- 実務でなんとなく使っている方
- 短時間で主要部分を抑えたい方

### この記事から得られること
- Dockerとは
- Docker imageからコンテナを作成
- Dockerの基礎になるコマンド

### 前提
- Docker Desktopの導入

https://www.docker.com/products/docker-desktop

## 目次

- [はじめに](#はじめに)

    - [対象読者](#対象読者)
    - [この記事から得られること](#この記事から得られること)
    - [前提](#前提)

- [目次](#目次)

- [用語](#用語)

    - [コンテナ](#コンテナ)

    - [Docker Image](#docker-image)

- [Dockerのメリット](#dockerのメリット)

- [Dockerのワークフロー](#dockerのワークフロー)

- [簡単チュートリアル](#簡単チュートリアル)

    - [①Docker imageの取得](#docker-imageの取得)

    - [②コンテナの作成](#コンテナの作成)

- [Docker client と Docker daemon](#docker-client-と-docker-daemon)

    - [Docker client](#docker-client)

    - [Docker daemon](#docker-daemon)

- [dockerコマンド](#dockerコマンド)

- [docker run](#docker-run)

    - [docker run -it bash](#docker-run--it--bash)

    - [docker run --name <コンテナ名>](#docker-run---name-コンテナ名-)

    - [docker run --rm](#docker-run---rm-)

    - [docker run -v <ホスト側パス>:<コンテナ側パス>](#docker-run--v-ホスト側パスコンテナ側パス-)

    - [docker run -p <ホスト側ポート>:<コンテナ側ポート>](#docker-run--p-ホスト側ポートコンテナ側ポート)

    - [docker run -it -u $(id -u):$(id -g)](#docker-run--it--u-id--uid--g)

- [イメージ](#イメージ)

    - [docker images](#docker-images)

    - [docker rmi](#docker-rmi-)

    - [docker rmi -f](#docker-rmi--f-)

    - [docker tag <変更後のimage名> <変更前のimage名>](#docker-tag-変更後のimage名-変更前のimage名)

    - [docker image prune](#docker-image-prune)

- [コンテナ](#コンテナ)

    - [docker ps](#docker-ps)

    - [docker ps -a](#docker-ps--a)

    - [docker rm](#docker-rm-)

    - [docker rm -f](#docker-rm--f-)

    - [docker system prune](#docker-system-prune)

    - [docker exec -it](#docker-exec--it-)

- [その他](#その他)

    - [docker network ls](#docker-network-ls)

    - [docker network rm](#docker-network-rm-)

    - [docker inspect](#docker-inspect-)

- [コマンド早見表](#コマンド早見表)

- [おわりに](#おわりに)

- [参考文献](#参考文献)

- [おすすめ教材](#おすすめ教材)

## 用語

頻繁にでてくる用語を整理します。

### コンテナ

コンテナとはDockerの持つ仮想化技術のことです。

### Docker Image

イメージとはコンテナのベースとなるものです。
**ubuntu**　や　**alpine**　などのOSや　**MySQL**　や　**Ruby**　のようなものまであります。

イメージは **レイヤ構造** になっていて、イメージやレイヤを重ねていくことによって一つのイメージを作成し　**コンテナ（環境）**　を作成していきます。

## Dockerのメリット

Docker環境を構築することは様々なメリットがありますが主なものを3点まとめました。

>1.　環境構築が容易
>2.　構築した環境の配布・共有することができ、誰でも同じ環境を作ることができる
>3.　Web業界でよく使用されている技術なので学んでおいて損がない

## Dockerのワークフロー

**Docker**　では　**Docker image**　を **使用・作成** してコンテナを作成していきます。
を Git で管理して GitHub などに push することでコンテナ(コンテナ)をチームのメンバーと共有します。
(他にも方法があると思いますが、この方法が一般的だと思いますので今回は省略します。)

## 簡単チュートリアル

Dockerコマンドで挙動を確認しながら以下の流れを追っていきます。

>①imageを取得
②コンテナを作成


### ①Docker imageの取得

`Docker Hub`　という　`Docker Registry`　から コンテナのベースとなる　image　を取得します。
pull コマンドを使えば取得できます。

今回は `hello-world`　というimageを取得します。

下記リンクの左上の検索窓から色々な　**image**　があることを確認できます。

https://hub.docker.com/_/hello-world


```sh:ターミナル
docker pull hello-world
```

```sh:ターミナル
docker images

# 以下のような形で出力されれば正常にimageを取得できています。
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    d1165f221234   5 months ago   13.3kB
```

### ②コンテナの作成
今取得したimageを使ってコンテナを作成します。
`docker images` で確認できますがコンテナを作成するときは `IMAGE ID` を使用してコンテナを作成します。私の場合は `d1165f221234` です。

```sh:ターミナル
docker run d1165f221234

# 出力結果
## hello-world imageからコンテナを実行すると以下のように出力されるようにプログラムされている。
Hello from Docker!
This message shows that your installation appears to be working correctly.

## どのような手順を行ったのか
To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

## ubuntu　はこちらのコマンドで実行できます。
To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

## Dockerチュートリアル
For more examples and ideas, visit:
 https://docs.docker.com/get-started/
```

## Docker client と Docker daemon

`hello-world` の出力結果の中に　`Docker daemon`　と　`Docker client` という単語がでてきましたので簡単にご説明せていきます。
Docker はクライアント・サーバ型のアーキテクチャなのでクライアントとサーバがあります。
クライアントというのが `Docker client` サーバが　`Docker daemon` のことです。
もっと詳しく知りたい方はドキュメントを見ると図も乗っているので理解しやすいです。

https://docs.docker.jp/engine/introduction/understanding-docker.html#id7

### Docker client

Docker を使用している自分（ホスト）のことです。
ホストが **Docker daemon** に命令を出して **image** や **コンテナ** を作成します。
命令というのは `Docker run` などのDockerコマンドのことです。

流れとしては **Docker client** からサーバーにある　**Docker daemon** に命令を出して　**Dockerオブジェクト** を操作しています。


### Docker daemon

**Docker daemon** は **Docker client** からの命令(コマンド)に従って **Dockerオブジェクト** を操作します。

## dockerコマンド

Dockerコマンドはたくさんありますが、その中でもよく使うコマンドをご紹介していきます。
`docker-compose` や `Dockerfile` については次回の記事以降で触れていきたいと思います。

## docker run

`docker run` コマンドは　**イメージ**　がなければ　**Registry**　からイメージを `pull`　してコンテナを作成実行してくれるコマンドです。

https://docs.docker.jp/engine/reference/commandline/run.html?highlight=it

### docker run -it <image ID> bash

たとえば ubuntu のイメージを指定するとコンテナに入ることができます。
(**※イメージにシェルが入っている必要があります。**)

`-it` は　`-i` と `-t` をあわせたものです。

`-i` はinput（入力を可能にする）

https://wa3.i-3-i.info/word1596.html

`-t` はtty（表示する）

https://wa3.i-3-i.info/word11668.html

https://docs.docker.jp/engine/reference/commandline/run.html?highlight=name#tty-name-it

### docker run --name <コンテナ名> <image>

`docker run` をしてコンテナをたてた場合コンテナ名は適当なものが勝手につけられてしまいます。
なにかと区別したい場合、管理したい場合は `--name` オプションでコンテナ名をつけてコンテナを作成することができます。


### docker run --rm <image ID>

`docker run` を実行して作成されたコマンドは消えません。
コンテナを実行して終了したとき同時にコンテナの削除をしたいときは `--rm` フラグをつけると
コンテナが削除されます。一時的にコンテナを立てたい時などに便利です。

`--rm` はリムーブの略です。

https://wa3.i-3-i.info/word11170.html


### docker run -v <ホスト側パス>:<コンテナ側パス> <image ID>

ファイルを共有することができます。
具体的にいうとホスト側のファイルをコンテナ側にマウントするということです。

マウントをすることで、コンテナからホストのファイルやフォルダを操作することができます。

https://docs.docker.jp/engine/reference/run.html#id31

https://qiita.com/tbpgr/items/5ff706ce2c62bffafd88


https://wa3.i-3-i.info/word13188.html


### docker run -p <ホスト側ポート>:<コンテナ側ポート>

コンテナで指定したポートをホスト側で公開することができます。

`-p` は **publish** の略で　**公開**　という意味があります。 

たとえば `docker run -it -p 8000:80 nginx` と指定すれば

http://localhost:8000/

ホストの　port8000番にアクセスすることでコンテナの80番ポートを見ることができます。

https://docs.docker.jp/engine/reference/run.html#expose

https://qiita.com/tifa2chan/items/a58e34019d4f10097a4d

### docker run -it -u $(id -u):$(id -g)

`docker run` をして立てたコンテナに入るとデフォルトだと 
**rootユーザー** であることがわかります。
ユーザーを変更したい場合は `-u` オプションをつけ 
**userId** や **groupId** を渡すことでそのユーザーでコンテナを起動することができます。


https://docs.docker.jp/engine/security/rootless.html

https://docs.docker.jp/engine/reference/run.html#user

## イメージ

### docker images

作成したイメージの一覧を見ることができます。

イメージの一覧なので `images`　です。複数形なことに注意します。

https://docs.docker.jp/engine/reference/commandline/images.html?highlight=images

### docker rmi <image　ID>

作成したイメージを削除したいときに使うコマンドです。
消したいイメージのIDを指定して `rmi` をつけることでイメージの削除をすることができます。

`rm` はリムーブ(削除する) と `i` image(イメージ) という意味です。

`rm` と非常に似ているので注意します。

https://docs.docker.jp/engine/reference/commandline/rmi.html?highlight=rmi

### docker rmi -f <image ID>

`-f` フラグは強制的にという意味合いがあります。
どうしても削除したときは使用しましょう。
(削除できないときは立てたコンテナで使用しているイメージだったりとなんらかの原因があるはずなので多用はしないほうが良いかもです。)

`-f` はforce（強制的）という意味です。


https://kitsune.blog/linux-command-summary#sec-5


### docker tag <変更後のimage名> <変更前のimage名>

docker imageは基本的に作成したときは **latest** というタグがつけられます。
これを変更したいときは `tag` コマンドで任意のイメージ名（リポジトリ名とタグ名）をつけることができます。

https://docs.docker.jp/engine/reference/commandline/tag.html?highlight=tag

### docker image prune

使用していない全ての **image** の削除をすることができます。
イメージ一覧が綺麗になるので整理したいときに使えます。

`prune` を直訳すると

>**「透かす, 刈り込む, 刈る, 切り落とす, 切り払う, 切り下げる, 切り調える」**

という意味です。（強そうですね、なんとなく理解できます。）

更に詳しく見たい方はドキュメントがわかりやすくまとめられています。

https://docs.docker.jp/config/pruning.html


## コンテナ

### docker ps

実行中のコンテナ一覧をみることができます。

https://docs.docker.jp/engine/reference/commandline/ps.html

https://docs.docker.com/engine/reference/commandline/ps/


### docker ps -a

`-a` オプションをつけることで終了しているコンテナを含め全てのコンテナを確認できます。

### docker rm <container ID>

コンテナを指定して削除することができます。

https://docs.docker.jp/engine/reference/commandline/rm.html

### docker rm -f <container ID>

強制的に削除するときに `-f` オプションをつけます。

### docker system prune

使用していない全ての **コンテナ** の削除をすることができます。


### docker exec -it <container ID>

実行中のコンテナでコマンドを実行することができます。
`exec` は　`execute(実行)` の略です。

https://docs.docker.jp/engine/reference/commandline/exec.html?highlight=exec


## その他

### docker network ls

ユーザーが作成した全てのネットワーク一覧を確認することができる。

https://docs.docker.jp/engine/reference/commandline/network_ls.html?highlight=network

### docker network rm <network ID>

指定したネットワークを削除することができる。

https://docs.docker.jp/engine/reference/commandline/network_rm.html?highlight=network%20rm

### docker inspect <container ID, image ID ...>

`inspect` のあとにコンテナIDやイメージIDを指定し、指定したものの情報を確認することができる。

https://docs.docker.jp/engine/reference/commandline/inspect.html?highlight=inspect


## コマンド早見表

| コマンド | オプション・フラグ・引数 | 意味 | 
|:-:|:-:|:-:|
| docker run   | -it, --name, --rm, -v, -p, -u, <イメージID> | コンテナを作成、実行する |
| docker images  |   |　イメージ一覧　|
| docker rmi  | <イメージId>  |イメージ削除|
| docker tag  | <変更後のイメージ名> <変更前のイメージ名>  |イメージ名（リポジトリ・タグ）名の命名|
| docker image prune  |   |使用していないイメージの一括削除|
| docker ps  | -a  |コンテナ一覧|
| docker rm  | <コンテナ名・ID>  |コンテナの削除|
| docker system prune  |   |使用していないコンテナの一括削除|
| docker exec   | <コンテナ名・ID>  |コマンドを実行する|
| docker network ls  |   |ネットワークの一覧|
| docker network rm  | <ネットワーク名・ID>  |ネットワークの削除|
| docker inspect  | <コンテナID, イメージID>  |詳細の確認|




## おわりに

Docker コマンドやそれに付随する **オプション**、**フラグ** は他にもたくさんあります。
全部を覚えることは難しいのでよく使うものから順番に使えるようにしていきます。

とはいえ、後に執筆予定の　`docker-compose`　を使用すれば上であげたような
コマンドを省略して使用できる場合もあります。ただ、上であげたようなコマンドが土台となっていることが多いので抑えておくと理解が捗るかもしれません。


## 参考文献

- [Docker リファレンス](https://docs.docker.jp/engine/reference/run.html)

- [Docker [アーキテクチャの理解] ](https://docs.docker.jp/engine/introduction/understanding-docker.html)

- [Docker Hub](https://hub.docker.com/)

- [Dockerチュートリアル](https://docs.docker.com/get-started/)

- [「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典(入力)](https://wa3.i-3-i.info/word1596.html)

- [「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典(tty)](https://wa3.i-3-i.info/word11668.html)

- [「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典(rm)](https://wa3.i-3-i.info/word11170.html)

- [これで完璧！Linux基本コマンドとオプションの使い方【一覧あり】](https://kitsune.blog/linux-command-summary#sec-5)

- [米国AI開発者がゼロから教えるDocker講座（Udemy）](https://www.udemy.com/share/103aTR3@da2-j-DfxBStXsYOuZ1y_sS4vk3xdT8M4amD4UNriM1YI_i0MyOoyfuBKvIZ27zBcA==/)

- [入門 Docker](https://y-ohgi.com/introduction-docker/)

## おすすめ教材

どちらのサイトも、ものすごくわかりやすかったのでおすすめです！
（**※個人的な意見なので購入する際は自己判断でお願いします。(入門 Dockerは無料)**）

- [米国AI開発者がゼロから教えるDocker講座（Udemy）](https://www.udemy.com/share/103aTR3@da2-j-DfxBStXsYOuZ1y_sS4vk3xdT8M4amD4UNriM1YI_i0MyOoyfuBKvIZ27zBcA==/)

- [入門 Docker](https://y-ohgi.com/introduction-docker/)