Dockerについて初学者がまとめてみる

# 導入
現在、常駐している客先では、無縁のDockerですが、
色んな方のリポジトリを見ているとよくお目にかかるDokcerfileやDocker-Compose.yml。
現場が変わった際に初めましてとなるのも大変だと思うので、
少し自分で調べたものをアウトプットする目的で記事にしました。

:::note info
初学者による記事のため、内容に誤りや誤解を招く表現がある場合があります。
ぜひ、コメントや編集リクエストにて訂正・指摘をお願いいたします。
:::

# Dockerとは

## Dockerとは何か

Dockerはアプリケーションを開発、配布、実行するためのオープンプラットフォームです。
Dockerを使用することで、アプリケーションをインフラから切り離し、
ソフトウェアを迅速に提供する事ができます。
アプリケーションを管理するのと同じ手法で、インフラを管理できます。

https://docs.docker.com/get-started/get-docker/?utm_source=chatgpt.com

## Docker頻出単語

Dockerを学習・利用するにあたって知っておいたほうがいい単語がいくつかあるため紹介します。

**Dockerコンテナ**

コードや依存関係を一緒にパッケージ化したアプリレイヤーの抽象化。
イメージをもとに実行されるインスタンスで、動作している実態のことを指します。

**Dockerイメージ**

Dockerコンテナを生成するためのテンプレートで、Dockerコンテナの設計図。
Docker公式イメージはDockerHubからダウンロードでき、自作したイメージを使用することも可能です。

**Dockerfile**

Dockerイメージの設計図。
環境構築の一連の流れをコード化したもので、好きなようにカスタマイズできます。

**docker-compose.yml**

複数のコンテナを同時に管理する設定ファイルです。

**Dockerレジストリ**

Dockerレジストリは、Dockerイメージのストアで、DockerHub等が挙げられます。
オフライン環境では、ローカルにDockerレジストリを設定して使用します。

**ボリューム**

ストレージの任意の領域を区切ったもので、永続化のための仕組みです。

**マウント**

ある対象をOSやアプリケーションが操作可能な状態にすることです。
具体的に言うと、ホスト側のストレージをコンテナ内で利用可能にする仕組みのことです。
Dockerでは、永続化の際に使用されます。

**オーケストレーション**
kubernetesなどを使用して、システムやソフトウェア、サービスなどの構築、運用管理を自動化することを指します。

## コンテナと仮想マシンの違い

### Dockerコンテナ

- アプリケーションのコードと依存関係(プログラムファイル、ライブラリ、フレームワーク、システムツールやランタイム)をパッケージ化したアプリレイヤーの抽象化
- 複数コンテナを同マシン上で実行
- OSカーネルはコンテナ間で共有されるため、少ないリソースで起動
- それぞれが分離されたプロセスとして実行
- コンテナは大抵数十MB（※大きいものだと数百MBになることもあります）

### 仮想マシン

- 1台のサーバーを多数のサーバーに変える物理ハードウェアの抽象化
- HyperVを使用して、複数のVMを1台のマシン上で実行
- OSごと用意されるため、数十GB

この比較からいくと、コンテナ運用の方が断然良さそうに見えます。

https://www.docker.com/resources/what-container/

# Docker導入による影響

## メリット

### **環境の一貫性と再現性**

環境構築をコマンド、コードで行うことで、作業に一貫性を保ち、再現性を保証します。
実際私が今いる現場では、環境構築手順書を作成していますが、そもそも過去のドキュメントが残っていなかったり、記載漏れや記載内容の表現の揺れ等で、環境間で差が生じ、問題が発生したりすることがあるため、このような問題は少なく済みそうです。

### イミュータブルな環境

Dockerを利用したアプリケーションは開発環境をそのまま本番環境に移行できることがあるため、本番用のシステムに一切手を加えないことから、イミュータブルインフラストラクチャと呼ばれています。
開発・本番環境が同じものを使用するため、運用コストも削減されます。

### **可搬性と拡張性**

作成したDockerコンテナは、他の環境でも容易に動かすことができるため、可搬性に優れています。
軽量で拡張性に優れているため、必要に応じて作成・削除が可能です。
よって開発・運用の切り替えや、障害発生時の対応において、別環境を作成するなどの作業コストが削減されます。

### **リソースの最適化**

上記のDockerコンテナの解説にもあったように、
OSカーネルを共有する等の工夫によって軽量であるDockerコンテナは仮想マシンに比べて、リソースの削減が見込まれます。

## デメリット

ただし、本番環境をDockerで構築するとなると、色々問題点もある模様です。以下にデメリットを記します。

### セキュリティリスク

複数コンテナがホストのリソースを共有しているため、コンテナそれぞれの脆弱性に対して対策を行う必要があります。
適切な権限の設定や、ネットワークの隔離、ファイヤーウォールの設定など、対策は多岐にわたるため、大規模な開発・運用になればなるほど、そのリスクは高くなり、対策の設計等も複雑になります。
後述にもありますが、これらの知識がもちろん必要となるため、学習コストも高くなります。

### 学習コスト

Dockerの基礎知識はもちろん、本番運用となると、Dockerfileの設定がより複雑になることが考えられます。拡張性が高いゆえに、これらの設定を理解する必要があるため、通常の仮想マシン、物理マシンの環境構築とは別の学習コストが必要となります。

### 異種OSでの検証

Dockerの特徴として、同一のOSカーネルを共有しているとありましたが、これにより、異なるOS環境での検証の際は、仮想マシンで構築を行う必要があります。Linuxカーネルを使用しているLinuxディストリビューションであれば、OSのコンテナイメージを使用して再現は可能ですが、OS固有の機能を使用する場合、ホストOSをあわせる必要があるため、仮想マシンを使用して検証を行う必要があります。

> OSのコンテナイメージはあくまでもアプリケーションの動作に必要な環境を「それっぽく」再現しているに過ぎない
> 

https://thinkit.co.jp/article/17301

### 本番環境におけるDockerfileのアンチパターン

以下の記事では、本番運用におけるDockerfileの注意点・アンチパターンが以下のように記載されていました。

> **1.VMで稼働してるインフラの作り方をDockerfileに適用する
2.言語のバージョンをもってイメージを場合分けする
3.公開されているイメージを生かさない
4.OSのディストリビューションにこだわる
5.Dockerfileとして軽量にできる記法/手法を使わない**
> 

https://qiita.com/kapibarasensei/items/f81a93481cefd1d57474

実際使用する際は、上記のアンチパターンに気をつけて実装する必要が有りますが、
基本的に、僕みたいな学習や小規模アプリケーション開発用途であれば、Dockerは積極的に使っていっても良さそうです。

# Dockerが必要とされるシーン

実際どのような場面でDocker導入による恩恵が受けられるかを考察してみました。

Dockerはメリットにも記載した通り、一貫性のある環境提供やリソースの効率性を強みとしています。

よって下記のような場面ではDocker導入を一度検討してみるべきだと考えました。

- 開発環境では動くのに、本番だとなぜか動かない
- 開発環境の構築に時間がかかる
- 環境構築に関するドキュメントがまとまっていない

これらは、Dockerが提供する開発環境と本番環境の一貫性を保つことと、イミュータブルな環境により解決に役立つように思えます。

# まとめ

Dockerに関する基礎知識を初学者なりにまとめてみました。
Dockerを使用する知識はもちろんですが、それがどうやって動いているのかや、
Linuxに対する知識についても少し理解する必要がありました。
これからハンズオンなどで実際に使用していき、
現場で使う機会が来た際に、対応できるようにしていきたいです。

# 参考資料

https://jitera.com/ja/insights/8236

https://www.geekly.co.jp/column/cat-technology/1902_047/

https://docs.oracle.com/cd/E39368_01/E75728/html/ch05.html

https://qiita.com/kirikunix/items/33414240b4cacee362da