Docker基本コマンド

#はじめに
以下Dockerコマンドについてまとめていく。覚えたコマンドは随時追加予定。

## Dockerとは何か。従来の仮想化とコンテナ型仮想化
コンテナがホストOSのカーネルを使用するということは、カーネルを共有できないOSはコンテナで動作させることができないということ。

## 従来の仮想化とDockerのメリットデメリット
分離レベル
・従来の仮想化 ハードウェアレベルで仮想化されており、ホストOSや仮想マシン間の分離レベルが高く、それぞれが影響を受けにくい。
・コンテナ型仮想化 OSの機能を使用した仮想化は、従来の仮想化に比べて分離レベルは低い。DockerにおいてコンテナはホストOSの１プロセスとして動作するため。

## hello-worldコンテナの実行と動作の解説

```docker
docker run hello-world
# コマンドを分割した場合
docker pull:イメージの取得
docker create:コンテナの作成
docker start:コンテナの起動
```

## ローカル上のDockerイメージの管理
```docker
# イメージにタグ付けするコマンド
docker tag docker/whalesay my_whalesay
```
tag #タグ付けするサブコマンド
docker/whalesay #元となるイメージ名
my_walesay #新しいイメージ名

```docker
# イメージの詳細情報を表示するコマンド
docker inspect my_whalesay
```
inspect #イメージの詳細情報を表示するサブコマンド
my_whalesay #対象のイメージ名もしくはイメージID

```docker
# ローカルのイメージを削除するコマンド(矯正削除する場合は-f)
docker rmi docker/whelsay
```
rmi #ローカル上のイメージ名を削除するサブコマンド
docker/whelsay #対象のイメージ名もしくはイメージID

## Dockerfileを使用したイメージビルド
```docker
# Dockerfileからイメージをビルドするコマンド
docker build -t docker-whale .
```
build #イメージをビルドするサブコマンド
-t docker-whale #タグ名の指定
. #ビルドコンテキストの指定

## Docker Hubへのイメージのプッシュ
Docker Hubにおけるタグ付けルール
<DockerID>/<イメージ名>:<タグ名>

## nginxコンテナの実行とデタッチモード
```docker
# nginxのコンテナを立ち上げるコマンド
docker run --name <コンテナ名> -d -p <ホスト側のポート番号>:<コンテナ側のポート番号> <イメージ名>
docker run --name test-nginx -d -p 8080:80 nginx
# -dを指定していない場合はフォアグラウンドでnginxが起動する。フォアグラウンドで実行している場合はnginxのログが画面に流れてくる。フォアグラウンドでnginxコンテナが動作しているため、ctrl+cなどでフォアグラウンドのプロセスを終了させるとコンテナも停止する。
```

## バインドマウントの解説
```docker
# nginxのコンテナを立ち上げるコマンド~バインドマウントを使用するケース~
docker run --name <コンテナ名> -d ¥
-v <ホスト側のディレクトリ>:<コンテナ側のマウントポイント>:<オプション> ¥
-p <ホスト側のポート番号>:<コンテナ側のポート番号> <イメージ名>
# nginxリポジトリの説明に書かれていたコマンド
docker run --name some-nginx -v /some/content:/usr/share/nginx/html:ro -d nginx
```

## DockerfileのCOPY命令、ADD命令
docker cpコマンドの説明

```docker
# ホストマシンのファイルをコンテナ内にコピーする場合
docker cp <ホスト上のコピーしたいファイルのパス> <コンテナ名orID>:<コピー先のパス>
```
```docker
# コンテナ内のファイルをホストマシンにコピーする場合
docker cp <コンテナ名orID>:<コンテナ上のコピーしたいファイルのパス> <コピー先のパス>
```
docker cpコマンドに似た命令としてdocker add命令がある。docker add命令はdocker cpコマンドの機能に加え、tarでアーカイブされたファイルをコピー時に自動で展開したり、コピー元にURLを指定した場合はURLからダウンロードしてコピー先に転送するといった動作をする。

## コンテナのシェルへの接続
コンテナのシェルに接続するコマンド

```docker
# docker attachを使用する場合
# exitで抜けた場合PID1のプロセスが終了してコンテナも停止する。-itオプションをつけておくとControl p qと連続して入力することでコンテナを停止させることなく抜けることができる。
docker attach <コンテナ名またはコンテナID>
```
```docker
# docker execを使用する場合
# 立ち上がったシェルの標準入出力に接続することができる。exitで抜けてもコンテナを停止させることがないため、こちらの方が安全。
docker exec -it <コンテナ名またはコンテナID> /bin/bash
```

## Dockerコミットの解説
```docker
# docker commitコマンド
# コンテナの状態をイメージとして保存することができる。
docker commit <コンテナ名またはコンテナID> <イメージ名>:<タグ名>
```

## Docker Machineとは
Docker Engineを搭載した仮想マシンの作成、起動、停止、再起動などをコマンドラインから実行できるツール
(例）仮想化のドライバーにバーチャルボックスを指定してdefaultという名前のdockerhostを作成

```docker
docker-machine create --driver virtualbox default
```
### 作成したDockerホストへ接続する方法

```docker
# 操作対象のDockerホストを設定するための設定コマンドを表示
docker-machine env default
# まとめて環境変数を設定
eval $(docker-machine env default
# アクティブなdockerマシンの選択を解除するコマンドを表示
docker-machine env -u 
### 環境変数を削除
eval $(docker-machine env -u)
```
### Dockerホストにssh接続
```docker
docker-machine ssh default
```
### Dockerホストのip確認
```docker
docker-machine ip default
```
### Dockerホストの起動停止
```docker
docker-machine stop default
docker-machine start default
```

## Dockerネットワーク
Docker networkにはデフォルトで存在する3つのネットワークがあり、それぞれ使用するドライバーがbridge、host、nullとなっている。コンテナはデフォルトでbridgeドライバーで接続されたbridgeネットワークに属することになる。
### ネットワークの詳細な情報を参照
```docker
docker network inspect bridge
```
### ユーザー定義のbridgeネットワークを作成
デフォルトのネットワークではDockerデーモンでDNSの機能が提供されていないため、コンテナ名で通信することができない。これはユーザ定義のbridgeネットワークを使用することで解決する。

```docker
docker network create [ネットワーク名]
```
### ネットワークにコンテナを接続する
```docker
docker network connect my_nw alpine1
# 切断する
docker network disconnect my_nw alpine1
# 最初から接続するネットワークを指定する
docker run -itd  --name alpine3 --network my_nw alpine
```

### noneネットワーク
ドライバーはnullとなっている。nullドライバーのネットワークに接続したコンテナはループバックインターフェース以外にネットワークインターフェースを持たない状態となる。また、noneネットワークに接続するコンテナはその他すべてのネットワークを切断した状態にする必要がある。

```docker
docker run -itd --name none --network none alpine /bin/sh
```
### hostネットワーク
hostドライバーを使用したネットワーク。hostネットワークに接続したコンテナはDockerホストと同じネットワーク設定となる。例えばhostネットワークのコンテナでwebサーバを起動した場合、ホストマシンのipの８０番でListenしているのと同じ動作になる。そのため、-pフラグを使用しなくてもコンテナを起動しただけでDockerホストのipの８０番にアクセスすればコンテナのipの８０番に接続可能

```docker
docker run -itd --name host --network host nginx
```

## Dockerのデータ管理
コンテナで扱う動的なデータは起動中のデータの読み書き可能なレイヤ内に置くことは可能であるがデメリットがある。例えばコンテナが消えた時点でコンテナ内にあったデータは消えてしまう。また、コンテナ間でデータを共有することができない。そのほかに、書き込みのパフォーマンスもホスト上に書き込むのに比べてよくない。これはコンテナの読み書き可能なレイヤには通常のファイルシステムとは異なりUnionFSを使用しているため。
### volumeを使用したデータ管理
Linuxホスト上の/var/lib/docker/volumesのディレクトリの配下に自動的にディレクトリが作成され、それがコンテナにマウントされる。作成されたコンテナは名前をつけることができ、複数のコンテナにマウントすることができる。その場合は複数のコンテナで共通のファイルを読み書きすることができる。volumeはコンテナが削除されても消えず、明示的に削除されるまで消えない。ホスト上のファイルはディレクトリを直接移動したり編集することは推奨されておらず、あくまでコンテナ上でファイルを管理するために用意されている機能。

```docker
# volumeを作成
docker volume create volume名
```
```docker
# 存在するvolumeを確認
docker volume ls
```
```docker
# 作成したvolumeの詳細情報を表示
docker volume inspect volume名
```
```docker
# volumeを削除
docker volume rm volume名
```

```docker
# -vによるマウント方法 コロン区切りでボリューム名とコンテナ上のパスを指定
docker run -itd --name mount-c1 -v vol1:app nginx:latest
```

```docker
# --mountフラグによるマウント方法 マウントもとのvolumeをsourceに指定し、マウント先をtargetに指定
docer run -itd --name mount-c2 --mount source=vol1,target=/app nginx:latest
```
### bind mountを使用したデータ管理
ホストのユーザが管理している任意のファイルやディレクトリをコンテナ上にマウントする。プロジェクトのソースコードや設定ファイルをホスト上に置いておき、それをマウントすることでホスト側でファイルを編集しながら動作を確認することができる。

```docker
# -vによるマウント方法
docker run -itd --name bind-test1 -v "$(pwd)"/source:app nginx:latest
```

```docker
# --mountフラグによるマウント方法 type=bindを指定
docker run -itd --name bind-test2 --mount type=bind,source="$(pwd)"/source2,target=/app nginx:latest
```
### tmpfsを使用したデータ管理
ホストのメモリ上の領域をコンテナにマウントする。コンテナが消えた場合はデータも消える。

```docker
docker run -itd --name tmptest --mount type=tmpfs,destination=/app nginx:latest
```

##Docker compose
マルチコンテナのDockerアプリケーションを定義して実行するためのツール。
### 実行のステップ
1. Dockerfileを用意するか使用するイメージをDockerHubなどに用意する。
2. docker-compose.ymlを定義する。
3. docker-compose upを実行する。

```docker
# docker-compose runにはymlに指定したサービスを指定。以降はサービスのコンテナ起動時に実行されるコマンド。プロジェクト名はexamplepj。保存先をカレントディレクトリ。特定のサービスでコンテナを起動したい場合。
docker-compose run web django-admin.py startproject examplepj .
```

```docker
# デタッチモードで各サービスを起動
docker-compose up -d
```

```docker
# アプリケーション作成
docker-compose run web python3 manage.py startapp polls

## Docker swarm
クラスタ管理機能とオーケストレーション機能を提供する。

```docker
# swarmの初期化　docker swarm initを実行した実行したホストは自動的にマネージャーノードとなる
docker swarm init --advertise-addr (他のノードと通信可能なIPアドレス）
# コマンド入力後クラスタにワーカーノードを追加するためのコマンドが表示される。
```

```docker
# swarmを構成しているノードを表示。マネージャーノードでのみ有効
docker node ls
```

```docker
# managerノード追加用のトークンを含むコマンド
docker swarm join-token manager
# workerノード追加用のトークンを含むコマンド
docker swarm join-token worker
```
### サービスとタスク
swarmクラスタのノードでコンテナを起動するには最初にサービスを作成する。サービスとはどのイメージから幾つのコンテナを起動するのかを定義したもの。

```docker
# タスク作成
docker service create -d --name nginx --replicas 3 --publish 8000:80 nginx
```