コンテナ技術 ハンズオン Vol.1  Docker操作編

# 本題の前に
---

## 位置付け・前提
本記事は、社内ワークショップ のために用意したものです。
複数回実施する予定で、下記も併せてご利用ください。

[コンテナ技術 ハンズオン Vol.2 Dockerイメージ編](https://qiita.com/syamane/items/1b552ce28932dbfd3c56)

なお、次の前提で進めることをご理解ください。

---

## 本ハンズオンの目的

参加者が必要に併せて **自学できる入口に立つ** ことを目的とします。

なお、本ハンズオンではコンテナ技術に関する知識は説明しません。また、本ハンズオンだけで、あらゆるコンテナ操作ができるようになるわけでもありません。

後日に「コンテナ」を扱おうとしたときに、自分で調べて理解でき、実際に扱えるようになることを目指します。

端的には、なんかこういうもんだ、という感じで軽く頭に残れば大丈夫と考えましょう。

---

## ターゲットとなる参加者

下記のような基礎知識があるエンジニアを対象とします。

* Linuxなどでコマンドを扱えるインフラの基礎知識があるエンジニア
* OSやネットワークの基礎知識は持っていること
* WEBサーバなどのミドルウェアの基礎知識を持っていること
    * nginx / WordPress / Ubuntu が何かわかること

---

## 参加者の前提知識

参加者は下記が説明できること。

* コンテナとイメージの違いが説明できる
* docker とdocker hub の違いが説明できる
* docker とdocker-compose / kubernetes の違いを説明できる
* コンテナとVMとの違いが説明できる
* docker の長所と短所が説明できる

もし分からないようであれば、下記を読み込んでおくこと。今回のハンズオン内では説明しません。

[![Docker入門-基礎編 いまから始めるDocker管理【2nd Edition】](http://image.slidesharecdn.com/introductiontodockermanagementandoperations2nd-151101144211-lva1-app6892/95/slide-1-1024.jpg)](https://www.slideshare.net/zembutsu/introduction-to-docker-management-and-operations-2nd)

[![コンテナ未経験新人が学ぶコンテナ技術入門](http://image.slidesharecdn.com/learningcontainer-181112024240/95/slide-1-1024.jpg)](https://www.slideshare.net/KoheiTokunaga/ss-122754942)

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

動画が良ければこちら。

* [Docker & Kubernetes入門 – (1) 概要編](https://www.youtube.com/watch?v=sEU5w6Muvy4&t=2515s)
* [Docker & Kubernetes入門 – (2) デモ編](https://www.youtube.com/watch?v=ii0X_1n4nRs)
* [創好リナのDocker入門講座](https://www.youtube.com/watch?v=5d8O7jm7Q5c)

※上記のうち、いずれか１つで良いと思います。

---

## docker ハンズオン環境

今回は [Play with Docker](https://labs.play-with-docker.com/) を活用してハンズオンを行います。

[![playwithdocker.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107190/bc635cbe-c24f-6cec-c871-f4a8073cfffb.png)](https://labs.play-with-docker.com/)

※要：[Docker Hub](https://hub.docker.com/) アカウント

注意点として、この環境は4時間の制限があります。４時間経過すると環境が削除されてしまう点を注意して下さい。

もちろんローカル環境でも構いません。

---

# ハンズオン

---

## 今回のゴール

* docker でイメージとコンテナを追加/確認/起動/停止/削除できること
* docker でコンテナの内部を操作できること
* dockerコンテナ同士を連携させること

---

## 今回やらないこと

* コンテナ/イメージを作ったり、変更したりはしません。
* kubernetes / docker-compose のようなオーケストレーションツールの使いません。

---

## Docker ヘルプ

基本的には docker コマンドで操作します。こちらを読めば、コマンドのオプションを忘れても大丈夫。

```bash
docker --help
```

表示結果はこちら。

```bash

Usage:  docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

Options:
      --config string      Location of client config files (default "/root/.docker")
  -c, --context string     Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default context set with "docker context use")
  -D, --debug              Enable debug mode
  -H, --host list          Daemon socket(s) to connect to
  -l, --log-level string   Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
      --tls                Use TLS; implied by --tlsverify
      --tlscacert string   Trust certs signed only by this CA (default "/root/.docker/ca.pem")
      --tlscert string     Path to TLS certificate file (default "/root/.docker/cert.pem")
      --tlskey string      Path to TLS key file (default "/root/.docker/key.pem")
      --tlsverify          Use TLS and verify the remote
  -v, --version            Print version information and quit

Management Commands:
  builder     Manage builds
  checkpoint  Manage checkpoints
  config      Manage Docker configs
  container   Manage containers
  context     Manage contexts
  engine      Manage the docker engine
  image       Manage images
  network     Manage networks
  node        Manage Swarm nodes
  plugin      Manage plugins
  secret      Manage Docker secrets
  service     Manage services
  stack       Manage Docker stacks
  swarm       Manage Swarm
  system      Manage Docker
  trust       Manage trust on Docker images
  volume      Manage volumes

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  build       Build an image from a Dockerfile
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  deploy      Deploy a new stack or update an existing stack
  diff        Inspect changes to files or directories on a container's filesystem
  events      Get real time events from the server
  exec        Run a command in a running container
  export      Export a container's filesystem as a tar archive
  history     Show the history of an image
  images      List images
  import      Import the contents from a tarball to create a filesystem image
  info        Display system-wide information
  inspect     Return low-level information on Docker objects
  kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  login       Log in to a Docker registry
  logout      Log out from a Docker registry
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes

Run 'docker COMMAND --help' for more information on a command.
```

困ったら長いけど、読めば使えます。


---

## Docker 動作テスト

```bash
docker run hello-world
```

実行結果の例はこちら。

```bash
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete 
Digest: sha256:6540fc08ee6e6b7b63468dc3317e3303aae178cb8a45ed3123180328bcc1d20f
Status: Downloaded newer image for hello-world:latest

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.

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/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/
```

---

## docker イメージの操作

---

### docker イメージの操作

ここでは、docker のイメージを操作していきます。コンテナの元になるイメージですから、様々な操作が必要です。

---

### 保有している docker イメージ一覧

保有している docker のイメージを一覧表示します。

```bash
docker images
```

さきほど実行した hello-world イメージだけが表示されるはず。

```bash
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              XXXXXXXXXXXX        7 months ago        1.84kB
```

これは先程の動作テストのコマンドで、「hello-world」イメージをダウンロードして保存していることを示します。

---

### 保有している Dockerイメージをコンテナとして起動する

先程のイメージ hello-world の IMAGE ID: XXXXXXXXXXXX を指定して起動します。

```bash
docker run XXXXXXXXXXXX
```

動作確認と同じメッセージが出ればOK.

---

### 保有している Dockerイメージを削除する

動作確認のためのイメージ hello-world を削除します。

```bash
docker rmi -f XXXXXXXXXXXX
```

または

```bash
docker image rm -f XXXXXXXXXXXX
```

どちらでも可能です。念のため、削除されてるかを下記のコマンドで確認しておきましょう。

```bash
docker images
```

---

## docker コンテナの操作

今度は動作の実態となる **コンテナ** を操作します。

---

### docker イメージを取得する

下記のコマンドでLinuxディストリビューションの「Ubuntu」のイメージを取得（ダウンロード）します。

```bash
docker pull ubuntu
```

実行すると、下記の実行結果が表示されます。

```bash
Using default tag: latest
latest: Pulling from library/ubuntu
35c102085707: Pull complete
251f5509d51d: Pull complete
8e829fe70a46: Pull complete
6001e1789921: Pull complete
Digest: sha256:d1d454df0f579c6be4d8161d227462d69e163a8ff9d20a847533989cf0c94d90
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latest
```

これはUbuntuの最新イメージがダウンロードされたことを意味します。
ちなみに、ダウンロード元は[Docker Hub](https://hub.docker.com)です。

キチンとダウンロードが成功したかは下記で確認します。

```bash
docker images
```
---

### docker コンテナの状態を確認する

先程、取得したイメージからコンテナが起動できていないことを確認します。

```bash
docker ps
```

恐らく表示はこちらになるはずです。

```
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
```

フィールド名の行だけ出力される状態です。つまり、コンテナは何も起動していません。

---

### docker コンテナを開始する

取得したイメージからコンテナを起動します。

```bash
docker run -it ubuntu
```

実行した結果、このような感じになります。

```bash
root@d3eea44310fc:/#
```

これはコンテナ内にログインして、シェルが起動した状態です。通常のLinuxと同じコマンドが使えます。

この状態で **Ctrl+P Ctrl+Q** の順にキーを入力してみましょう。

ホストOSのシェルに戻れます。（この行為を **dettach** と呼ぶ）

また、コンテナ内のシェルで **exit** を入力すると、起動したコンテナが停止します。

---

### docker コンテナの状態を確認する

コンテナのシェルから、ホストのシェルに戻った状態を下記のコマンドで確認してみましょう。

```bash
docker ps
```

```bash
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
d3eea44310fc        ubuntu              "/bin/bash"         3 minutes ago       Up 3 minutes                            silly_galileo
```

STATUS が「UP」と表記されている状態は、コンテナが起動している状態を指します。

---

### dockerコンテナにログインする

dockerコンテナにログインすることを **attach（アタッチ）** と呼びます。下記のコマンドで実行できます。

```bash
docker attach d3eea44310fc
```

実行した結果、このような感じになります。

```bash
root@d3eea44310fc:/#
```

ls コマンドやcdコマンドなどで色々移動してみると、ホントにコンテナのOSにログインしている事が分かります。

---

### dockerコンテナにログアウトしつつ、停止する（exit）

そのまま、exit コマンドを実行してみます。

```bash
root@d3eea44310fc:/# exit
```

先に記載した通り、これでコンテナも停止します。

```bash
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
```

コンテナが停止すると、何も表示されなくなります。

---

### dockerコンテナを全て表示する

停止したコンテナも含めて、全て表示してみます。

```bash
docker ps -a
```

そうすると、こんな感じで表示されます。

```bash

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                         PORTS               NAMES
d3eea44310fc        ubuntu              "/bin/bash"         8 minutes ago       Exited (0) 49 seconds ago                          silly_galileo
95cb9df8ea3c        fce289e99eb9        "/hello"            29 minutes ago      Exited (0) 29 minutes ago                          keen_davinci
```
STATUS列の値が Exited になっておいます。この **Exited は停止状態** を現します。

ちなみに、こちらでも同じように表示されます。使いやすい方を使って下さい。

```bash
docker container ls --all
```

### docker コンテナを削除する

上記の CONTAINER ID が d3eea44310fc の ubutntuコンテナを削除してみます。

```bash
$ docker rm d3eea44310fc
d3eea44310fc
```

成功すると、コンテナIDだけが表示されます。その後、どうなったか確認しましょう。

```bash
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
95cb9df8ea3c        fce289e99eb9        "/hello"            29 minutes ago      Exited (0) 29 minutes ago                          keen_davinci
```

ついでに、動作確認に使った hello コンテナも削除しておきましょう。

```bash
docker rm 95cb9df8ea3c
```

これでキレイになりました。

ちなみに、これまで実働する実態を「コンテナ」と呼んできました。しかし、一般的には「インスタンス」と呼ぶことも多いです。今後は **インスタンス** と呼ぶことにします。

---

## 複数の docker インスタンスを扱う

---

## docker イメージの取得

いくつかサービス提供できるイメージを取得してみます。

---
### Nginx インスタンス

Webサーバで定評のある nginx を取得して起動します。取得と起動を同時に行うには次のコマンドです。

```bash
docker run -p 80:80 nginx
```

これはインスタンス（コンテナ）の80番ポートをOSの80番ポートに紐付けて、起動するコマンドになります。これを実行してみると下記のようになります。

```bash
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
1ab2bdfe9778: Pull complete 
a17e64cfe253: Pull complete 
e1288088c7a8: Pull complete 
Digest: sha256:53ddb41e46de3d63376579acf46f9a41a8d7de33645db47a486de9769201fec9
Status: Downloaded newer image for nginx:latest
```

イメージ取得後に上記のメッセージを表示して、何も表示されなくなります。

その上で、Play with Docker のコンソールを見ると下記のようにリンク表示されますので、確認しましょう。

![Play with docker から nginx インスタンスを確認するリンク](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107190/7eaf5f73-cd3f-4802-1045-356896dec72b.png)

リンクを辿った結果、下記のように表示されれば成功です。

![nginx インスタンスの表示確認の結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107190/4eb9dd77-1f72-2b62-dc76-e0200022ee81.png)

コンソール上には、下記のようにアクセスログが表示されます。

![nginx のアクセスログ表示](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107190/cbbc44d1-2b4e-1feb-3d6f-7401e8a7219f.png)

その後、コンテナの状態を見てみましょう。とはいえ、この状態では **Ctrl-P Ctrl-Q**でnginxインスタンスからデタッチすることができません。一度、Ctrl+c で強制終了します。

---
### Nginx インスタンス（バックグラウンド）

改めて、下記のコマンドでバックグラウンド実行をしましょう。

```bash
docker run -p 80:80 -d nginx
```

引数 -d を追加すると、起動後にデタッチした状態、つまり**バックグラウンドでインスタンスを起動**することができます。次のコマンドでインスタンスの起動状態が確認できます。

```bash
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS               NAMES
084d96e489b8        nginx               "nginx -g 'daemon of…"   About a minute ago   Up About a minute   0.0.0.0:80->80/tcp              condescending_morse
```

PORTS 列に注目すると、「0.0.0.0:80 つまりホストOSの80番ポートに、 80/TCP つまりインスタンスの80番ポートを紐付ける」設定で起動していることが分かります。

---
### WordPress インスタンス

CMSとして有名なWordPressインスタンスを起動してみましょう。取得と起動に加え、先度と同じようにバックグラウンドでインスタンスを動作させます。

```bash
docker run -d -p 8080:80 --name wp-tmp wordpress
```

ちなみに、インスタンス（コンテナ）の80番ポートをOSの8080番ポートに紐付けて、起動するコマンドになります。インスタンスの名前も wp-tmp として付けています。

これを実行してみると下記のようになります。

```bash
$ docker run -d -p 8080:80 --name wp-tmp wordpress
Unable to find image 'wordpress:latest' locally
latest: Pulling from library/wordpress
1ab2bdfe9778: Already exists 
1448c64389e0: Pull complete 
4b8a4e62b444: Pull complete 
9eb9d1e8e241: Pull complete 
d20b2d19292c: Pull complete 
023060ea5930: Pull complete 
a7fa99bc84ac: Pull complete 
138ec8da18f2: Pull complete 
cd4dae5ac262: Pull complete 
c90eff48869a: Pull complete 
1bc49f4d3a43: Pull complete 
e3bb2b10f58d: Pull complete 
fd7b454ec570: Pull complete 
f683ca4a731d: Pull complete 
ddfc36999535: Pull complete 
7fddf219f6ab: Pull complete 
4f41fcb25817: Pull complete 
42e4c7a4efc8: Pull complete 
3db92b48316d: Pull complete 
09fa84b4298a: Pull complete 
Digest: sha256:c3c95ed75a85b024c07455b2722f5ecec78d4efb363aca02539f1b9057e713ac
Status: Downloaded newer image for wordpress:latest
4171518356b78f585a82522da48a2ca2ae522dcbffb1188e6b83266b25d716c8
```

イメージ取得後に上記のメッセージを表示して、シェルに戻ってきます。また、管理コンソールから8080ポートにアクセスすると下記の画面が表示されます。

![WordPress初期設定画面1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107190/64071309-b752-b686-be77-523f23cdc2cc.png)

この後進めると、実際にデータベースを設定する画面まで進められます。

![WordPress初期設定画面2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107190/eae69910-53f0-0b7d-9766-206580743e1f.png)

実際には、MySQLが必要となります。

そのため、一度この **WordPressインスタンスは停止および削除** してください。

```bash
docker stop wp-tmp
```

stop コマンドでインスタンスは停止することができます。もちろん、rm コマンドで削除しても構いません。

```bash
docker rm -f wp-tmp
```

引数 -r を付ければ、起動しているインスタンスごと強制的に削除可能です。

---
### MySQL インスタンスの取得

RDBMSとして有名なMySQLインスタンスを起動してみましょう。取得と起動に加え、バックグラウンドでインスタンスを動作させる引数「-d」をつけ、さらにインスタンス名と環境変数を設定するコマンドです。ちょっと複雑。

```bash
docker run --name wp-mysql -e MYSQL_ROOT_PASSWORD=wppassword -e MYSQL_USER=wpuser1 -e MYSQL_PASSWORD=password -e MYSQL_DATABASE=wp -d mysql:5.7.27
```

ちなみに、ここでは動作条件に必要なMySQLのバージョン指定をしています。

これを実行してみると下記のようになります。

```bash
$ docker run --name wp-mysql -e MYSQL_ROOT_PASSWORD=wppassword -e MYSQL_USER=wpuser1 -e MYSQL_PASSWORD=password -e MYSQL_DATABASE=wp -d mysql:5.7.27
Unable to find image 'mysql:latest' locally
latest: Pulling from library/mysql
9fc222b64b0a: Pull complete 
291e388076f0: Pull complete 
d6634415290b: Pull complete 
1f1e7d852ad4: Pull complete 
125fc05f36e0: Pull complete 
2aed16e5b02f: Pull complete 
5fa9342b7235: Pull complete 
6ce062d9949d: Pull complete 
c5a4e96aaa50: Pull complete 
60ca60d28457: Pull complete 
e93ef9cc9bb0: Pull complete 
9bc6d9fa3f72: Pull complete 
Digest: sha256:01cf53f2538aa805bda591d83f107c394adca8d31f98eacd3654e282dada3193
Status: Downloaded newer image for mysql:latest
93e8eb78dc7d837b72ddba842fd1283eae0ab8c0c24805ca071a722993b23525
```

---

### 再び WordPressインスタンスの作成
この MySQL インスタンスにアクセスできるWordPressインスタンスを作成します。

```bash
docker run --name wp -p 8080:80 --link wp-mysql:mysql -d wordpress
```

既にイメージは取得済みなので、サクッと起動できるはずです。違いとしては、引数 --link を設定していまして、意味は下記の通りです。

```bash
docker run -link [dockerコンテナ名、もしくはID][:[エイリアス]]
```

このようにコンテナ間をリンクさせることで、1つのOSで動作しているのと同じように動きます。

先程と同様に管理コンソールから8080番ポートにWEBアクセスして、先程のWordPress設定画面まで進めます。

![WordPress設定画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107190/32d39cbd-7018-a67a-c2d8-df4362711ecd.png)

先程とは違って、データベースの接続設定画面が表示されません。つまり、MySQLの接続が成功し、わざわざ設定しなく済んでいることが分かります。

今度は、適切に設定して、「WordPressインストール」ボタンを押下します。

![WordPressインストール成功画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107190/4114972a-66d3-dd66-c5f0-5d49201ceb4c.png)

あとは先程設定したユーザー名やパスワードを入れればログインできる画面まで到達できます。

![WordPressログイン画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107190/440746c3-e9e8-831e-e212-bcbeb75d74d9.png)

このとき、裏側では WordPress のコンテナと MySQL のコンテナが連携して動作しています。

このように同一ホスト上のコンテナの間で通信したい場合、接続したい相手のネットワーク情報を取得できるようにする仕組みを備えています。こちらも併せて読むと良いでしょう。

[Docker の基本学習 ~ コンテナ間のリンク](https://qiita.com/Arturias/items/75828479c1f9eb8d43fa)

---

## 問題

下記を調べましょう。

1. 起動しているコンテナはホストのどのディレクトリにあるでしょうか。
2. dockerイメージはどこにあるでしょうか。
3. dockerのプロセスはどれか。

また、1-3が完了した後は後始末をしましょう。

4. 起動しているインスタンスをすべて停止してください。
5. 起動しているインスタンスをすべて削除してください。
6. 取得したイメージをすべて削除してください。

---

# おわりに

今回は docker で１～数個のコンテナを扱う方法について、ハンズオンをしました。

しかし、dockerコンテナはそもそも誰かが作る必要がありますが、その手順は今後学んでいく必要があります。それはこちらで学習しましょう。

[コンテナ技術 ハンズオン Vol.2 Dockerイメージ編](https://qiita.com/syamane/items/1b552ce28932dbfd3c56)

また、コンテナの真骨頂は**大量のコンテナ操作**や**定型的な運用操作の効率化**にあります。今後は、Docker-compose や Kubernetes といったツールを学んでいきましょう。

なお、もう少しハンズオンを独自にやりたい人はこちらもどうぞ。

[Play with Docker Classroom（英語）](https://training.play-with-docker.com/)

---

# 参考

本ハンズオン資料を作成する上で、下記のページを参考にさせていただきました。ありがとうございました。

* [入門 Docker](https://y-ohgi.com/introduction-docker/)
* [Dockerでコンテナ作成/起動/停止/自分用Image作成](https://qiita.com/tomy103rider/items/bf4042ad2082a23f393b)
* [Dockerコンテナの作成、起動〜停止まで](https://qiita.com/kooohei/items/0e788a2ce8c30f9dba53)
* [Use the Docker command line | Docker Documentation](https://docs.docker.com/engine/reference/commandline/cli/)
* [Dockerのすべてが5分でわかるまとめ!(コマンド一覧付き) - paiza開発日誌](https://paiza.hatenablog.com/entry/docker_intro)
* [【Linux】Docker / Kubernetes 入門](https://fisproject.jp/2018/11/introduction-to-docker-and-kubernetes/)
* [Dockerハンズオン基礎編：コンテナとイメージのライフサイクルを理解 - Qiita](https://qiita.com/zembutsu/items/ca0fa7b874c8375be8a4)
* [Dockerハンズオン資料 - Qiita](https://qiita.com/wantonbe/items/54ea5fc076bb28937037)
* [Docker ハンズオン - 基本コマンド編 - Qiita](https://qiita.com/hihihiroro/items/6dda871dc2566801a6da)
* [こうしたいんだぜ！ という時の逆引きdockerコマンド | 株式会社ビヨンド](https://beyondjapan.com/blog/2016/08/docker-command-reverse-resolutions/)