DockerFileとdocker-compose.ymlを理解する

## DockerFile
```Dockerfile```はDockerイメージを作成するためのファイルです。
イメージはコンテナの土台となり、```Dockerfile```からビルドすることでイメージが作成され、コンテナを起動することが可能になります。

## FROM
Dockerのベースイメージを指定します。(Node.js等)

## RUN
新しく作成されるイメージの中でコマンドを実行し、ソフトウェアのインストールやセットアップを行います。

Dockerはレイヤー（層）の積み重ねでイメージを構築し、レイヤーは少ない方が処理が軽くなります。例えば、```RUN apt-get update -qq && yarn global add @vue/cli```はレイヤーを減らすために```&&```を使用しています。
下記コマンドでは、updateで最新版に更新し```Vue CLI```をインストールしています。

```Dockerfile
RUN apt-get update -qq && yarn global add @vue/cli
```

## WORKDIR
コンテナ内の作業ディレクトリを設定します。
例えば/appと設定すると、後続の命令やコンテナの起動時のデフォルトディレクトリが/appになります。

## CMD
コンテナが起動した際に実行されるコマンドを設定します。
具体的な動作はpackage.jsonに定義されたスクリプトに依存します。
```Dockerfile
CMD ["yarn", "serve-dev"]
```
```json
"scripts": {
    "serve-dev": "vue-cli-service serve --mode local",
    }
```
package.jsonのscriptsは yarn または npm コマンドを使って実行することができます。
CMDコマンドは ```yarn serve-dev```すなわち```yarn vue-cli-service serve --mode local```がコンテナ実行時に実行されるということになります。

## COPY
ローカルのファイルやディレクトリをイメージにコピーすることができます。
```Dockerfile
COPY [コピー元][コピー先] 
```

## ENV
Dockerfile内で環境変数を設定するために使用されます。
```Dockerfile
ENV [キー]　＝　[値] 
```

## docker compose
```Docker Compose```は```docker-compose.yml```ファイルを元に、複数のコンテナを一括で作成・起動するツールです。

* コマンドの手順
  * docker compose build
  * docker compose run --rm client bash
  * docker compose up

## docker compose build
Dockerイメージを再構築します。
ただし、Dockerfileを先に編集しなければ変更は反映されません。

## docker compose run --rm client bash
指定したコンテナ内でbashシェルを起動します。
```client```ではyamlで定義されたサービス名が指定されることで、サービス名のコンテナを起動し、```bash```によりコンテナ内でbashシェルが起動します。
```--rm```はコンテナが終了したときに自動的に削除するためのものです。これにより、一時的な作業やデバッグセッションの後で不要なコンテナが残らないようにします。
ここで必要なモジュールをインポートします。

## docker compose up
対象となるコンテナが起動状態になります。
この時、オプションやサービス名を何も指定しない場合は、docker-```compose.yml```で定義した```services```が全て実行されることになります。

## docker execでコンテナ内のbashシェルを起動する方法
```docker exec```は既に実行中のDockerコンテナ内でコマンドを実行するためのもので、```docker compose up -d```でバックグラウンドでコンテナを起動させた状態で実行します
```docker
docker exec -it Dockerのコンテナ名 bash
```
```-it```は、-iでコンテナ内のシェルに入力を送ることができ、-tは簡単にいえば入力しやすくするコマンドです。

## docker-compose.yml
```
version: "バージョン"
services:
  サービス名(コンテナ):
    build:
      context: .
      dockerfile: ./docker/node/Dockerfile
    ports:
      - "8080:8080"
    expose:
      - "8080"
    volumes:
      - ./app:/app
    tty: true
    stdin_open: true
  サービス名(コンテナ):
    ....
    ....
```
```build```では、```context```でdockerfileとともにbuildされるコンテキストを指定し、```dockerfile```でdockerfileのパスを指定します。.は現在のディレクトリを指します。

```ports```では、ホストマシンの8080ポートを、コンテナの8080ポートにマッピングしています。
コンテナ内で動作しているアプリケーションが、コンテナ内部の8080ポートを待ち受け、外部からホストマシンの8080ポートへアクセスすると、その通信はコンテナの8080ポートに転送されます。
その結果、localhostと8080ポートを指定してアクセスすることで、実際にはコンテナ内部のアプリケーションにアクセスすることができます。

```expose```では、単にコンテナ内でのリッスンポートを示す情報を設定しています。
なので、外部からそのポートにアクセスするためには、portsを使用してホストとマッピングする必要があります。

```volumes```では、ホスト上のファイルやディレクトリをコンテナのファイルシステムにマウントするための設定です。つまり、データを永続化したり、ホストとコンテナ間でデータを共有することができます。
今回でいえば、ホストマシンの ./app ディレクトリを、コンテナの /app ディレクトリにマウントします。

```tty```をtrueにすると、コンテナが正常終了するのを防ぐことができます。
具体的には、ttyを設定することで、コンテナ側に仮想端末を置いて実行しているプロセスが用意されることでコンテナを持続させることができます。
```docker exec -it```コマンドの-tに当たる部分です

```stdin_open```をtrueにすることで標準入出力とエラー出力をコンテナに結びつけることができます。
```docker exec -it```コマンドの-iに当たる部分です

dockerコンテナは起動したらそのまま終了してしまいます。しかし、コンテナ内に入ってコマンドを打ち込ちたいケースで、dockerコンテナを起動させておく必要があります。
そんな時に```-it```を使いますが、それをdocker-compose.ymlのttyとstdin_openで設定しているのです。