Dockerチュートリアルまとめ


## イメージとは？
コンテナを作成するために必要なもの
また、イメージを作成する為の設計図となるファイルがDockerfile

### イメージの作成方法
1. Dockerfileを作成
2. `docker build`を実行
3. `docker images` で作成を確認

### 補足
- `docker image history <REPOSITORY名>`で各レイヤーのサイズを知れる
    - レイヤー：FROM RUNなどのコマンドが1つずつのレイヤーになっている
- `-t <name>` で任意のタグをつけられる

### オプション

https://docs.docker.jp/engine/reference/commandline/build.html#id21

https://docs.docker.jp/engine/reference/commandline/images.html#id18

## コンテナとは？
アプリケーションを実際に実行できる環境のこと
イメージを使用して1つのイメージから1つのコンテナを作成できる

### コンテナの作成、実行
1. `docker run`を実行
2. `docker ps` で動いているコンテナを確認
3. `docker exec -it <コンテナID> bash`で中に入ることができる
4.`docker stop　<コンテナID>`でコンテナを停止
5. `docker rm <コンテナID>`でコンテナを削除


### 補足
- `docker run --d`でバックグラウンドで実行できる
- mysqlの場合は`docker exec -it <コンテナID> mysql -u root -p`になる
- `docker rm -f <コンテナID>`でコンテナを停止　削除


### オプション

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

https://docs.docker.jp/engine/reference/commandline/exec.html#docker-exec-options

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

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

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

## ボリューム
コンテナにファイルの作成、削除などを行ってもコンテナを削除すると変更はなくなってしまう
ボリュームを使用することで永続化できる

永続化するために2つの方法がある
- Dockerのボリュームを使用
- ローカルファイルをマウントして使用

### Dockerのボリュームを使用

1. `docker volume create <任意>`
2. `docker run -dp <port> --mount type=volume,src=<１で決めた任意の名前>,target=/etc/<任意> <コンテナ名> `
3. `docker volume inspect`で実際にDockerがデータを保存する場所を確認（MountPoint）

### ローカルファイルをマウントして使用（バインドマウント）

1. `docker run -it --mount type=bind,src="$(pwd)",target=/src ubuntu bash`
2. コンテナ内で加えた変更がローカルでも起きていることがわかります


### オプション

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

## コンテナ同士を繋ぐ
コンテナは1つの役割を担うことでバージョン管理が容易になったり、DBと分けてスケーリングできるなど良いことが多い
コンテナは他のコンテナを参照することができない
同一のネットワークを使用することでコンテナ同士でやり取りを行えるようにする


1. `docker network create <任意>`でネットワークを作成する
2. MySQLコンテナを起動してネットワークに割り当てる
```
docker run -d \
     --network <1で作成したネットワーク名> --network-alias mysql \
     -v <任意>:/var/lib/mysql \
     -e MYSQL_ROOT_PASSWORD=<任意> \
     -e MYSQL_DATABASE=<任意> \
     mysql:8.0
```
3. MySQLとアプリを繋ぎ込む
```
docker run -dp 127.0.0.1:3000:3000 \
   -w /app -v "$(pwd):/app" \
   --network <ネットワーク名> \
   -e MYSQL_HOST=mysql \
   -e MYSQL_USER=<任意> \
   -e MYSQL_PASSWORD=<2で作成したパスワード> \
   -e MYSQL_DB=<2で作成したDB> \
   node:18-alpine \
   sh -c "yarn install && yarn run dev"
```
4. `docker exec -it <mysqlコンテナID> mysql -p <2で作成したDB名>`で確認


### オプション

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

## Docker Compose
複数のコンテナを使用する場合にコンテナ同士を繋いだり、ボリュームのマウント、環境変数の設定など手順が多く時間がかかったりミスが発生することを防げるもの
docker-compose.ymlのあるディレクトリで`docker-compose up`のみでイメージの作成からコンテナの起動まで完了できる

```
services:
  app: ←なんでも可　自動的にネットワークエイリアス名となる
    image: node:18-alpine　←Docker Hubなどでも取得可能
    command: sh -c "yarn install && yarn run dev" ←imageとどちらが先でも可
    ports:
      - 127.0.0.1:3000:3000　←portを定義するもの
    working_dir: /app　←(-w /app)
    volumes:
      - ./:/app ←(-v "$(pwd):/app" \)
    environment:
      MYSQL_HOST: mysql
      MYSQL_USER: root
      MYSQL_PASSWORD: secret
      MYSQL_DB: todos

  mysql:
    image: mysql:8.0
    volumes:
      - todo-mysql-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: todos

volumes:
  todo-mysql-data:
```

| up | build | run | start|
|:-----------|------------:|:------------:|:------------:|
| Dockerイメージの作成からコンテナの作成、起動 Imageがすでにある場合は作り直さない　depends_onやlinksで紐づいているコンテナもまとめて起動 | Dockerイメージを作成 | Dockerイメージの作成からコンテナの作成、起動　１つのサービスに対して1つのコマンドのみ |作成済のコンテナを起動|


## オプション
https://docs.docker.jp/compose/reference/up.html

https://docs.docker.jp/compose/reference/build.html

https://docs.docker.jp/compose/reference/run.html

https://docs.docker.jp/compose/reference/start.html