Docker&Docker Composeの基礎

# 対象の読者
- DockerやDocker Composeについて初めて学ぶ人。基本的な概念から始め、具体的な使い方までを学びます。
- コンテナ仮想化技術に興味を持っている人。


# Docker
Dockerは、コンテナ仮想化を提供するプラットフォームで、アプリケーションやその依存関係を軽量で独立した単位である「コンテナ」にパッケージ化し、実行・配布するためのツールやエコシステムの総称です。
また、物理的な環境の違いや、サーバ構成の違いを無視できるため、開発や運用の効率が大幅に向上します。

### Dockerを使うメリット
- Dockerはコンテナを使うことで隔離できるため、異なるアプリケーションやサービスの依存関係を解決し、互いに影響を受けずに実行することができる。
- Dockerがあれば、物理的な環境の違いや、サーバ構成の違いを無視できる
- 環境構築をコード化(IaC)することで、複数の同じ環境が作れる、作成した環境を配布しやすい。
- イメージを読み込めば開発環境の再構築が容易。
- スクラップ＆ビルドが容易。
- カーネルを共有しているのでリソースを節約できる。


# Dockerのアーキテクチャ
Dockerはクライアント・サーバ型のアーキテクチャでDockerクライアントはDockerデーモンと通信することで、Dockerコンテナの構築、実行、配布といった力仕事をする。
Dockerクライアントとデーモンのいずれも同じシステム上で実行できる。
DockerクライアントはリモートのDockerデーモンに接続することも可能です。
Dockerクライアントとデーモンは、お互いにSocketかRESTful APIを通して通信します。

![docker-architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3577658/62be1e33-d031-a38b-4f25-40d9579f3fe2.png)
>引用元：https://docs.docker.jp/engine/introduction/understanding-docker.html#id7


## Docker クライアント
Docker(デーモン)を操作するのに利用する。
ユーザーからのコマンドを受け付けると、Dockerデーモンと通信し、応答を返す。


## Docker ホスト
Dockerホストとは、Dockerコンテナの実行環境を提供する物理的または仮想的なマシンです。

#### Docker デーモン
- Dockerデーモンは、ホストマシン上で動作します。これは、Dockerエンジンがインストールされたマシンで、Dockerコンテナの実行環境を提供します。
- ユーザーは、Dockerクライアントを通じてDockerデーモンと通信します。
つまり、ユーザーは直接デーモンと通信せず、Dockerクライアントを介してコンテナの管理や操作を行います。
- 主な役割は、コンテナの起動や管理を行うことです。

#### イメージ
Dockerイメージは、コンテナを起動するための読み取り専用のテンプレートで、Dockerfileから作成されます。これらのイメージは、Docker Hubからダウンロードしたり、自分で作成したりすることができます。つまり、DockerイメージはDockerにおける構築(ビルド)の基本単位です。

#### コンテナ
Dockerコンテナは、アプリケーションとその依存関係を一つのパッケージにまとめ、独立して実行できる環境を提供します。各コンテナは分離されており、実行、開始、停止、移動、削除が可能です。また、複数の環境で同じコンテナを動作させることができるため、移植性が高いです。基本的に1コンテナは1プロセスを表し、オブジェクト指向の観点から見ると、コンテナはイメージのインスタンスと考えることができます。

https://docs.docker.com/engine/reference/commandline/cli/


## Dockerレジストリ
イメージを保存、管理するリポジトリ。
既存のイメージをPULLしてローカル環境で使ったり、自分のイメージをPUSHして共有したりする。
パブリックなDockerレジストリとしてDocker Hubが提供されている。
DockerレジストリとはDockerにおける配布(distribution)コンポーネントです。

#### Docker Hub
Docker公式のDockerレジストリ。
代表的なミドルウェアはすでにイメージ化されているのでそのまま使える。(カスタマイズすることも可能)

https://hub.docker.com/


## Dockerfile
Dockerfileは、単一のDockerイメージをビルドするための設定ファイルであり、アプリケーションの構成や構築手順を明示的に定義します。このファイルにはビルドに必要な命令や依存関係が含まれ、一つのコマンドでイメージを構築できます。Dockerfileを使用することで、同じ環境を簡単に複製し、常に同じ構成で環境を再現できます。

https://docs.docker.com/engine/reference/builder/

## FlaskアプリのDocker化
ディレクトリ構成
```
project
├── app.py
├── Dockerfile
└── requirements.txt
```

```app.py
from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello world"

if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)
```

```requirements.txt
Flask==2.1.0
```

```Dockerfile
# 使用するベースイメージ
FROM python:3.8-slim

# 作業ディレクトリの指定
WORKDIR /app

# ホストのrequirements.txtをコンテナにコピー
COPY requirements.txt .

# 必要なライブラリのインストール
RUN pip install --no-cache-dir -r requirements.txt

# ホストのアプリケーションコードをコンテナにコピー
COPY . .

# Flaskアプリケーションの実行コマンド
CMD ["python", "app.py"]
```

コンテナをビルドする
```terminal
$ docker build -t flask-image .
```
コンテナを実行する
```terminal
$ docker container run -d -p 5000:5000 --name flask-app flask-image
```
http://localhost:5000 にアクセスすると「Hello world」が表示される


## Dockerコンテナのライフサイクル
Dockerコンテナは「使い捨て」が推奨される手法です。
これは、ソフトウェアが組み込まれたコンテナを素早く再構築できるためです。複数のコンテナが同時に稼働している場合、1つずつアップデートするのは非効率的です。そのため、古いコンテナは廃棄し、新しいイメージから新たなコンテナを作成して切り替えることが一般的です。

1. 作成
Dockerfileは、Dockerイメージを作成するための手順書として作成されます。
2. ビルド
docker buildコマンドを使用して、Dockerfileに記述された手順を実行し、Dockerイメージを作成します。
3. 実行
作成したDockerイメージから、docker runコマンドを使用してDockerコンテナを起動します。
4. 停止/再開
docker stopやdocker startコマンドを使用して、Dockerコンテナを停止または再開します。
5. 削除
不要になったDockerコンテナは、docker rmコマンドを使用して削除します。


# Docker Compose
Docker Composeは、複数のDockerコンテナを一元管理するためのツールです。docker-compose.ymlという設定ファイルを使用して、各コンテナに対する設定を定義し、一括で起動・停止・管理することができます。


### Docker Composeを使うメリット
- 複数のDockerコンテナを簡単・効率的に管理・実行できるようになる。
- コンテナを運用する際のミスを軽減できる。
- コンテナ間のネットワーク設定が簡単になる。


## docker-compose.yml(compose.yml)
docker-compose.ymlは、Docker Composeの設定ファイルで、複数のDockerコンテナを協調して管理するための設定を定義します。このファイルはYAML形式で書かれ、以下のような情報を含むことができます。
- サービス
アプリケーションの各コンポーネント(例えば、app、db、webなど)を定義します。各サービスは個別のコンテナとして実行されます。
- ネットワーク
コンテナ間の通信を管理します。これにより、異なるサービスが互いに通信できるようになります。
- ボリューム
データを永続化するためのストレージを定義します。これにより、コンテナが停止または削除されてもデータが保持されます。

#### docker-compose.ymlの基本的な構造のサンプル
```
version: '3'
services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
  db:
    image: postgres:latest
    volumes:
      - db-data:/var/lib/postgresql/data
volumes:
  db-data:
```
この例では、webとdbという2つのサービス(コンテナ)が定義されています。webサービスはnginx:alpineイメージを使用し、ホストの8080ポートとコンテナの80ポートをマッピングしています。dbサービスはpostgres:latestイメージを使用し、db-dataというボリュームをデータベースのデータを保存するために使用しています。

https://docs.docker.com/compose/compose-file/compose-file-v3/


## データの永続化
Dockerでデータの永続化をする方法は主に2種類あります。
- マウント(同期)を利用したデータの永続化
ホスト(ローカル)ディレクトリとコンテナディレクトリを同期させることでデータを永続化します。
- データボリュームを利用した永続化
データボリュームは1つまたは複数のDockerコンテナ内でデータの共有・再利用をするために設計された特別なディレクトリです。データボリュームとコンテナのライフサイクルはそれぞれ独立しており、コンテナを削除してもデータボリュームは削除されません。


## Docker Composeコマンド
ビルドコマンド
```terminal
$ docker-compose build
```
実行コマンド
```terminal
$ docker-compose up
```

Dockerコンテナ内でコマンドを使う
```terminal
# 構文
$ docker exec -it <コンテナ名またはID> <任意のコマンド>

# npmパッケージのインストール
$ docker exec -it <コンテナ名またはID> npm install <パッケージ名>

#　Djangoでマイグレーションを作成する
$ docker exec -it <コンテナ名またはID> python manage.py makemigrations
```
https://docs.docker.jp/v19.03/compose/reference/index.html


## まとめ
- DockerとDocker Composeは、ソフトウェア開発の効率を向上させるためのツールです。
- Dockerは、アプリケーションとその依存関係を「コンテナ」と呼ばれる独立した単位にパッケージ化することができます。これにより、アプリケーションはどの環境でも同じように動作します。
- Docker Composeは、複数のDockerコンテナを一括で管理するためのツールです。これにより、複数のコンテナを同時に起動、停止、削除することができます。
- これらのツールを使用することで、開発者は環境の設定や管理を効率的に行うことができます。


## 参考資料
Dockerアーキテクチャの理解(公式)

https://docs.docker.jp/engine/introduction/understanding-docker.html

MIXIの研修資料
 
https://speakerdeck.com/mixi_engineers/2023-container-training-number-01

https://www.youtube.com/watch?v=Dk0isJQ6a80

Dockerでデータを保存するための2つのオプション

https://docs.docker.com/storage/


## おすすめ書籍
仕組みと使い方がわかるDocker&Kubernetes(おすすめ)

https://www.amazon.co.jp/%E4%BB%95%E7%B5%84%E3%81%BF%E3%81%A8%E4%BD%BF%E3%81%84%E6%96%B9%E3%81%8C%E3%82%8F%E3%81%8B%E3%82%8B-Docker-Kubernetes%E3%81%AE%E3%81%8D%E3%81%BB%E3%82%93%E3%81%AE%E3%81%8D%E3%81%BB%E3%82%93-%E5%B0%8F%E7%AC%A0%E5%8E%9F%E7%A8%AE%E9%AB%98/dp/4839972745/ref=sr_1_5?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=3RMMPVTW3N54C&keywords=Docker&qid=1702025674&sprefix=docker%2Caps%2C265&sr=8-5

Docker&仮想サーバー完全入門

https://www.amazon.co.jp/Docker-%E4%BB%AE%E6%83%B3%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E5%AE%8C%E5%85%A8%E5%85%A5%E9%96%80-Web%E3%82%AF%E3%83%AA%E3%82%A8%E3%82%A4%E3%82%BF%E3%83%BC%EF%BC%86%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%AE%E4%BD%9C%E6%A5%AD%E3%81%8C%E3%81%AF%E3%81%8B%E3%81%A9%E3%82%8B%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89%E3%82%AC%E3%82%A4%E3%83%89-%E3%83%AA%E3%83%96%E3%83%AD%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9/dp/4295015318/ref=sr_1_2_sspa?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=5A658GMG4GZ&keywords=Docker&qid=1702046296&sprefix=docker%2Caps%2C177&sr=8-2-spons&sp_csd=d2lkZ2V0TmFtZT1zcF9hdGY&psc=1