Dockerコマンドとファイルの書き方【追加更新継続中】

# 概要
dockerとかdocker-composeとか使ったものを少しずつ追加していっています。

# docker事前知識
- 実環境を汚さないためにコンテナ上に仮想環境を構築する
- DockerをインストールしたOS（Ubuntu)で、OSやアクリケーションが入った実行イメージ(イメージ)というものを入手する必要があり、Dockerが運営しているイメージの共有サイトから入手する`docker pull`
- イメージが準備できたらそれを実行する`docker run`
    - 実行するとCONTAINERというものができる。ここで色々な設定をしたり、アプリケーションを作ったり、色々インストールしたして、必要な環境を整える
- CONTAINERでの様々な設定をした状態から更にイメージを作ることができる`docekr commit`
- 作成したイメージを他のマシンで動かしたい場合には`docker push`をする
    - そこでまた、動かしたい環境下でpushしたものを入手する`docker pull`

**- 導入はこちら -**
[Docker Desktop for Mac](https://docs.docker.com/docker-for-mac/)
[docker-compose](http://docs.docker.jp/compose/toc.html)

**- 目次 -**
dockerについては[ここ](#dockerコマンド)から
docekr-composeについては[ここ](#docekr-compose)から

# dockerコマンド

[Docker コマンド](http://docs.docker.jp/engine/reference/commandline/)

|コマンド |オプション |概要 |
|:-- |:-- |:-- |
|search | |イメージを検索 |
|pull | |イメージを取得 |
|images | |取得済みのイメージを一覧表示 |
|inspect | |イメージの詳細を確認 |
|rmi | |イメージを削除 |
|run | |イメージからコンテナを生成して起動 |
|└ |-d |デタッチド・モード: コンテナをバックグラウンドで実行し、新しいコンテナ名を表示 |
|└ |-i, --interactive |コンテナの STDIN にアタッチ |
|└ |-t, --tty |疑似ターミナル(pseudo-tty)を割り当て。 |
|└ |-it |-i, -tの組み合わせ。コンテナを生成・起動と同時にコンテナの中に入ってbashで操作 |
|└ |--name NAME |コンテナに名前を割り当 |
|└ |-u, --user="" |実行時のユーザ名または uid を指定 |
|└ |--rm |コンテナ実行後に削除。デタッチド・モードの場合は無視 |
|└ |-p, --publish=[] |コンテナのポートをホスト側に公開 |
|└ |--service-ports |サービス用のポートを有効化し、ホスト側に割り当て可能にする |
|attach | |バックグラウンドで実行中のコンテナをフォアグラウンドへ |
|└ |--sig-proxy=false |コンテナを停止させずバックグラウンドに戻す |
|logs | |コンテナのログを表示 |
|ps | |実行中のコンテナ一覧を表示 |
|└ |-a, --all |停止中も含めた全てのコンテナ一覧を表示 |
|stop, kill | |実行中のコンテナを停止 |
|start | |停止中のコンテナを再度起動 |
|restart | |実行中のコンテナを再起動 |
|rm | |コンテナを削除 |
|exec | |起動中のコンテナにログインしてbashで操作 |
|commit | |コンテナからイメージを生成 |
|login | |Docker Hubにログイン |
|push | | イメージをDocker Hubレジストリに送信 |
|build | |Dockerfileからイメージをビルド |
|cp | |ホストとコンテナ間でのファイルコピー |

https://qiita.com/k5n/items/2212b87feac5ebc33ecb




# search: イメージを検索

- イメージの入手は下記の検索ボックスから検索して入手する(検索例：centos)
    - https://hub.docker.com/
- コマンドライン上からも`search`コマンドで検索が可能

```sh
$ docker search {検索ワード} | more
```

```sh:(例)
$ docker search centos | more

NAME                               DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
centos                             The official build of CentOS.                   5633                [OK]                
ansible/centos7-ansible            Ansible on Centos7                              125                                     [OK]
jdeathe/centos-ssh                 OpenSSH / Supervisor / EPEL/IUS/SCL Repos - …   114                                     [OK]
~~ 省略 ~~
```


# pull: イメージを取得

pullしたいイメージは`search`コマンドの検索結果の**NAME**を入力する

```sh
$ docker pull {pullしたいイメージ}
$ docker pull centos
```

# images: 取得済みのイメージを一覧表示

- 次のように出力され、TAGはversionを表し、IMAGE IDがイメージの実体である。
- TAGが異なってもIDが同じであれば同じ実体である(解釈がちょっと違うかも)

```sh
$ docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              0f3e07c0138f        3 weeks ago         220MB
~~ 省略 ~~
```

# inspect: イメージの詳細を確認

- `{REPOSITORY名}:{TAG名}`で指定する場合と`IMAGE ID`で指定する場合の2通りある
    - latestの場合はTAG名を省略できる
- IDで指定する場合は一意に決まれば良いため最初の数文字程度で他に一致するイメージがなければ省略が可能である
- IMAGE IDが簡単なので次からはIMAGE IDのみでコマンド紹介

```
$ docker inspect {REPOSITORY名}:{TAG名}
$ docker inspect {IMAGE ID}
```

```sh:(例)
# {REPOSITORY名}:{TAG名}で指定する場合
$ docker inspect centos:latest

# IMAGE IDで指定する場合
$ docker inspect 0aa7bb41deca
# 省力する場合
$ docker inspect 0aa


# 結果の例
[
    {
        "Id": "sha256:0aa7bb41deca2572a560442b8e607a520853726939bafa222b5426feeba631bb",
        "RepoTags": [
            "node:10-alpine"
        ],
        "RepoDigests": [
            "node@sha256:6eaca0f766a0403bc6be295d470381044e5083c895cea33b39d9ba6a29d64c92"
        ],
~~省略~~
```


# rmi: イメージを削除

- rmiはremove imageの略
- [Docker不要なコンテナ、イメージを大掃除！コンテナとイメージの一括削除](http://www.kaasan.info/archives/3953)

```sh
$ docker rmi {IMAGE ID}
```



# run: イメージからコンテナを生成して起動


|オプション |概要 |
|:-- |:-- |
|-d |デタッチド・モード: コンテナをバックグラウンドで実行し、新しいコンテナ名を表示 |
|-i, --interactive |コンテナの STDIN にアタッチ |
|--name NAME |コンテナに名前を割り当 |
|-u, --user="" |実行時のユーザ名または uid を指定 |
|--rm |コンテナ実行後に削除。デタッチド・モードの場合は無視 |
|-p, --publish=[] |コンテナのポートをホスト側に公開 |
|--service-ports |サービス用のポートを有効化し、ホスト側に割り当て可能にする |
|-t, --tty |疑似ターミナル(pseudo-tty)を割り当て。 |


- `docker run`コマンドでコンテナが作成され、同時に指定した実行したいコマンドが実行される

```shell:
$ docker run {IMAGE ID} {実行したいコマンド}
```

```shell:(例)
$ docker run centos echo 'hello world'
```

## 【runオプション】 -d: デタッチド・モード(バックグラウンド)で起動
- リアルタイムでコマンドライン上に実行結果を表示させる
- 継続的に処理が実行される場合はバックグラウンドでは知らせておくとコマンドラインが奪われずに済む

```shell:
$ docker run -d {IMAGE ID} {実行したいコマンド}
```

```shell:(例)
$ docker run -d centos free -s 3
```

## 【runオプション】 -it: コンテナを生成・起動と同時にコンテナの中に入ってbashで操作
- **`-i, --interactive`: インタラクティブ・モードで起動**と
**`-t, --tty`: 擬似ターミナルを割り当て**を両方指定した状態で、通常合わせて`-it`として使用する

```shell:
$ docker run -i -t {IMAGE ID} /bin/bash
$ docker run -it {IMAGE ID} /bin/bash
```

## 【runオプション】 --rm: コンテナ実行後に削除。デタッチド・モードの場合は無視

```shell:
$ docker run --rm -it {IMAGE ID} /bin/bash
```

## 【runオプション】 -p, --publish=[]: コンテナのポートをホスト側に公開して起動
ホスト側のportを8080、ゲスト側をDockerfileで`EXPOSE 80`で指定した場合

```shell:
$ docker run -p 8080:80 {IMAGE ID}
```

Vagrantfileで指定したホスト側のipを指定してブラウザを開いて内容が表示されればok




# attach: バックグラウンドで実行中のコンテナをフォアグラウンドへ

|オプション |概要 |
|:-- |:-- |
|--sig-proxy=true |受信したシグナルをプロセスに全てプロキシする |


- バックグラウンドで実行中のコンテナをフォアグラウンドへ持ってきて出力を表示させる
- `Ctrl+C`で抜けれるがデフォルトではコンテナごと停止される
    - `--sig-proxy=false`とすることでコンテナのプロセスに影響を与えず、コンソールのみに影響するため、そのままコンテナはバックグラウンドに戻る


```shell:
$ docker attach  --sig-proxy=false {CONTAINER ID}
```


# logs: コンテナのログを確認

```shell:
$ docker logs {CONTAINER ID}
```


# ps: コンテナの一覧を表示

|オプション |概要 |
|:-- |:-- |
|-a, --all |停止中も含めたコンテナ一覧を表示 | 
|-l, --latest |最後に作成したコンテナを表示 |
|-n=5 |直近で作成したコンテナを指定数表示 |
|-q, --quiet |実行中のコンテナのIDのみ表示 |
- デフォルトでは実行中のコンテナのみ一覧表示される
    - 停止中も含めたコンテナ一覧を表示するには`-a`オプションを付ける


```shell:
$ docker ps
```

## 【psオプション】 -a, --all: 停止中も含めたコンテナ一覧を表示

```shell:
$ docekr ps -a
```


## 【psオプション】 -n=5: 直近で作成したコンテナを指定数表示

```shell:
$ docker ps -a -n=5
```


## 【psオプション】 -q, --quiet: 実行中のコンテナのIDのみ表示

```shell:
$ ducker ps -q

# 停止中も含めたコンテナのIDのみ表示する場合
$ docker ps -a -p
```


# stop, kill: 実行中のコンテナを停止

```shell:
$ docker stop {CONTAINER ID}
or
$ docker kill {CONTAINER ID}
```


# start: 停止中のコンテナを再度起動
同じ処理をさせる場合はCONTAINERが残っているため`docker run`をしなくて良い

```shell:
$ docker start {CONTAINER ID}
```

# restart: 実行中のコンテナを再起動

```shell:
$ docker restart {CONTAINER ID}
```



# rm: コンテナを削除する
コンテナは予め停止させておく

```shell:
$ docekr rm {CONTAINER ID}
```



# exec: 起動中のコンテナにログインしてbashで操作

```shell:
$ docker exec -i -t {CONTAINER ID} /bin/bash
```



# commit: コンテナからイメージを作成
- イメージの名前は{User名/任意の名称}とする
    - User名はdocker hubのアカウントのユーザー名を指定しなければpushしたときにエラーが発生する

```shell:
$ docker commit {CONTAINER ID} {User名/任意のイメージ名}
```

```sh:(例)
$ docker commit f20a hoge/fuga
```


# login: Docker Hubにログイン
次のコマンドを打つとusernameとpassを聞かれるので入力する

```
$ docker login
```

# push: イメージをDocker Hubレジストリに送信
login後に行う


```sh
$ docker push {User名/任意のイメージ名}
```

```sh:(例)
$ docker psuh hoge/httpd
```


# build: Dockerfileからイメージをビルド
- 取得したイメージを元にコンテナを生成して変更を加えたものを再びイメージ化するという`pull`, `run`, `commit`の一連の流れをスクリプトとして自動化することが可能であり、`build`コマンドで実行可能
- 自動化するためのスクリプトファイルは**Dockerfile**であり、ここに処理内容を記載しておく

```
# カレントディレクトリにあるDockerfileを使う場合は最後に"."をつける
$ docker build -t {新しく作られるイメージの名前} .
```


# (補足)Dockerfile作成

[Dockerfile のベストプラクティス](http://docs.docker.jp/engine/articles/dockerfile_best-practice.html)

|処理内容|概要 |
|:-- |:-- |
|FROM |処理するベースとなるイメージの指定 |
|MAINTAINER |作成者情報を設定 |
|RUN |ベースイメージ'(FROM)から起動したコンテナ内で実行するコマンドを設定 |
|ENV |環境変数を設定 |
|WORKDIR |作業ディレクトリの設定|
|USER |ユーザ変更設定 |
|LABEL |メタ情報(バージョンやコメントなど)設定 |
|EXPOSE |公開ポート番号設定(アクセス時は`run -p`を使用する) |
|ADD |ファイルやディレクトリをコピー（リモート可） |
|COPY |ローカルからファイルやディレクトリをコンテナへコピー |
|VOLUME |ボリューム設定(コンテナ内のマウントポイント) |
|ONBUILD |次のbuild時に実行されるコマンドを設定 |
|CMD |作成したイメージが起動されたら実行するコマンドを設定 |
|ENTRYPOINT |作成したイメージが起動されたら最初に実行されるコマンドを設定 |

https://qiita.com/gold-kou/items/44860fbda1a34a001fc1



```sh:Dockerfile
FROM centos
MAINTAINER hoge
LABEL title="sampleImage"\
      version="1.0"\
      description="This is a sample."
      
RUN ["yum -y install httpd"]
ENV hoge=hogehoge\

WORKDIR /tmp
# WORKDID後のRUNは移動後のディレクトリで実行される
RUN ["pwd"]

USER admin
# USER後のRUNは変更されたユーザーで実行される
RUN ["whoami"]

# コンテナの公開ポートの設定
EXPOSE 80

ADD https://github.com/docker/cli/blob/master/README.md /tmp
COPY tmp.txt /tmp

# ホストOSからのマウントポイントを設定
# コンテナ内のファイルはコンテナを削除すると消えてしまうため、重要なデータはコンテナでなく外部ボリュームで管理
VOLUME /myvol

# 生成されたイメージから稼働したコンテナで実行するコマンドを１つ設定できる
# CMDとENTRYPOINTの主な違いはrunコマンド実行時の上書きの仕方だけ。
CMD ["ping","127.0.0.1","-c","5"]
ENTRYPOINT ["ping","127.0.0.1","-c","5"]
```

# docekr-compose
docker-composeは同一ホストOS上の複数コンテナを一括管理するコンポーネント。
複数のコンテナで一つのサービスを構成するとき、その構成情報を`docoker-compose.yml`に定義して`docker-compose`コマンドで起動や停止などの管理をする。

# docker-composeコマンド

|コマンド |概要 |
|:-- |:-- |
|build |指定されたイメージをビルドする |
|up |サービス用のコンテナを構築、作成、起動、アタッチ |
|down |コンテナの停止 |
|ps |コンテナ一覧を表示 |
|scale |生成するコンテナ数の指定 |
|logs |コンテナログの確認 |
|run |コンテナの実行 |
|start |コンテナの起動 |
|stop |コンテナの停止 |
|restart |コンテナの再起動 |
|rm |コンテナの削除 |


# build: 指定されたイメージをビルドする

基本的には初回とDockerfile書き換え時に実行
サービスは プロジェクト名_サービス として構築時にタグ付けられる

```sh
$ docker-compose build
```

# up: サービス用のコンテナを構築、作成、起動、アタッチ

このコマンドによってリンクされているサービスも起動される

```sh
$ docker-compose up
```
## 【upオプション】 -d: バックグラウンドで実行

```sh
$ docker-compose up -d
```


# down: コンテナの停止
コンテナを停止し、 up で作成したコンテナ・ネットワーク・ボリューム・イメージを削除します。デフォルトではコンテナとネットワークのみ削除します。


|オプション |概要 |
|:-- |:-- |
|--rmi type {all or local} |イメージの削除。`type all`: あらゆるサービスで使う全イメージを削除。`type local`: image フィールドにカスタム・タグのないイメージだけ削除 |
|-v, --volumes |Compose ファイルの `volumes` セクションの名前付きボリュームを削除。また、コンテナがアタッチしたアノニマス・ボリュームも削除 |
|--remove-orphans |Compose ファイルで定義していないサービス用のコンテナも削除 |


```sh
$ docker-compose down
 ```

## ps: コンテナ一覧を表示

デフォルトでは実行中のコンテナ一覧のみが表示される
オプションはdockerコマンドと同じ


# (補足)docker-compose.yml作成

|処理 |概要 |
|:-- |:-- |
|version | docker-composeのバージョン(現在最新バージョン3)|
|services | ここにサービスを定義していく(webやdbと名付けるのが慣例) |
|image |ベースとなるイメージの指定 |
|build |Dockerfileのパスを指定(基本はカレントディレクトリ) |
|depends_on |依存関係を示していて起動順を制御できる(depends_on: dbとすることでdb->webの順で起動されるffffff) |
|command |コンテナ内で実行するコマンドの設定 |
|links |コンテナ間リンク設定 |
|ports |ホストOS外部への公開ポート設定(コスト:コンテナで設定) |
|expose |コンテナ間のみでの公開ポート設定 |
|volumes |ボリュームマウントの設定 |
|volumes_from |別コンテナをボリュームとしてマウントするための設定 |
|environment |環境変数設定 |
|env_file |環境変数をファイル読み込みで設定 |
|container_name |コンテナの名前設定 |

[いまさらDockerに入門したので分かりやすくまとめます](https://qiita.com/gold-kou/items/44860fbda1a34a001fc1)



- アプリケーションを動かすための各要素をServiceといい、設定ファイル`docekr-compose.yml（ComposeFileという)`にServicesをネストさせて内容を記載する
    - 設定ファイルをComposeFileいう
    - 下記の例ではServiceにdbとwebというService名のServiceが定義されている
- composefile[リファレンス](https://docs.docker.com/compose/compose-file/)



```sh:docker-compose.yml
version: '3'

# サービスを定義していく
services:
  db:
    # ベースとなるイメージの指定
    # コンテナの起動にはイメージが必要でimageかbuildのどちらかの記載が必須
    image: mysql

  web:
    # Dockerfileの指定
    # buildの場合Dockerfile内のFROMでイメージを指定しているためimageは不要
    build: .
    
    # コンテナ内で実行するコマンドの指定
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    
    # サービス名を指定してコンテナ間のネットワーク設定
    # linksで指定したコンテナへ、指定元コンテナから接続可能にする
    # この場合(web->db)へ接続を可能にする
    links:
      - db

    # コンテナにボリュームをマウント
    # {マウント元}:{マウント先(コンテナ側)}
    volumes:
      - .:/myapp

    # 別のコンテナからボリュームをマウント
    # storageという名前のコンテナからマウントする例
    volumes_from:
      - storage
      
    # コンテナの外部への公開ポート設定
    ports:
      - "3000:3000"
      
    # コンテナ間のみでの公開ポート設定
    expose:
      - "3000"
    
    # コンテナ内の環境変数設定
    environment:
      - hoge=hogehoge
      
    # コンテナ内の環境変数をファイル読み込みで設定
    # 同一階層にenvfileを作成し、そこに"hoge=hogehoge"など環境変数を記載して読み込ませる
    env_file: envfile
    
    # コンテナの名前を設定
    container_name: sample-container1
```