今日から始めるDocker入門（必要性を理解してから動かす）


# Dockerとは
おそらく、仕組みを言葉で表現されても良く分からないと思うので、wikipediaを引用させていただきます
後述で必要性や歴史を記載しますので、そこで実感してもらえればなと思っています

> Docker（ドッカー[4]）は、コンテナ仮想化を用いてアプリケーションを開発・配置・実行するためのオープンプラットフォームである
> Dockerはコンテナ仮想化を用いたOSレベルの仮想化によりアプリケーションを開発・実行環境から隔離し、アプリケーションの素早い提供を可能にする。かつその環境自体をアプリケーションと同じようにコード（イメージ）として管理可能にする[6]。Dockerを開発・テスト・デプロイに用いることで「コードを書く」と「コードが製品として実行される」間の時間的ギャップを大きく短縮できる

https://ja.wikipedia.org/wiki/Docker


# なぜ必要か
私がこの業界に来た時はDockerというものはなかったと思います（認識してなかっただけかも）
Dockerがない時代の開発環境といえば・・なつかしい

- プロジェクトで用意しているNAS（Network Attached Storage）上にある、インストーラーをダウンロード
    - なぜサイトからではないかというと、細かいバージョン違いやインストール手順を共通化したいから
- 自分のPCにapacheをインストール、httpd.confをプロジェクト用に修正
- 自分のPCにPostgreSQLをインストールし、postgresql.conf、pg_hba.confをプロジェクト用に修正
- アプリケーションをsvnからチェックアウトして、必要なconfigファイルを修正
- ローカル特有のコード修正を入れる
- apacheを起動/再起動してアプリケーションを動かす

これだけで、1日から1.5日かかりました
それに加え、工夫をしないとミドルウェアのマイナーバージョンが人によって微妙に違ったり
ローカル特有の修正コードが違ったり、めちゃくちゃです
今じゃ考えられないほどのコストをエンジニア個々人が費やしていました

それが、Dockerだとソースさえ手元にあれば、コマンド一つ二つで開発環境が立ち上がります
しかも使う人はみんな同じバージョンになります

## ローカル開発の歴史
※ 個人的に歩んできた歴史になりますので、世間一般ではない点ご承知おきを。
今あえて以下で説明するような技術をやってみるのはそれはそれですごい勉強になりますので、オススメです！

### ローカルにそのままインストール
少なくとも私が体験してきた最古の歴史では、開発PC（当時はwindows）にそのままapache（WEBサーバー）や、Postgres（DB）をインストールして動かしていました
単純にlocalhost内で通信ができるので、シンプルで非常にわかりやすい点はあるかもしれませんが、色々な問題点があります

- インストールやその他設定が大変
- OS差分がある（本番はlinuxだけど、開発はwindowsやmacで動かすことになる。OS差分の代表的なものはファイルセパレーター）

https://httpd.apache.org/download.cgi

https://www.enterprisedb.com/downloads/postgres-postgresql-downloads

### vmware/virtual box
OS差分問題を解決するために、仮想環境を開発PCにインストールして、その上にapacheやPostgresをインストールする手法がありました
この段階ではもう「OSの上にOSをインストール」して開発をすることが可能となってまして、私もwindowsOSの上にCentOSをインストールして開発を行っていました
これが可能となると、本番環境と同じOSでローカル開発が可能となるわけです！

ただしこれでも問題が。

- 仮想環境自体の設定が結構難しい
- 自らインストールコマンドを打つので、linuxを動かせる知識がそれなりに必要
- インストールやその他設定が大変（ローカルインストール時代よりも大変になった）
- 単純に仮想環境が重い・・（必要以上にメモリやCPUなどのPCリソースをくう）

https://www.virtualbox.org/

### vagrant
インストールや設定が面倒くさい問題をついに解決してくれたのが、vagrantでした
virtual boxの設定かつ仮想OS起動後のインストールコマンドその全てが起動スクリプト（vagrantファイル）に書き込め、有識者一人がvagrantファイルを一回作ってしまえばその内容を開発者間で共有でき、カスタマイズ不要でローカルに仮想環境を起動することが可能となりました

https://blog.flan999.com/?p=391#toc20

### からのdocker
あとはみなさんがこれから学ぼうとしているdockerになります
virtualbox環境も良かったのですが、dockerと比べるとPCにかける負荷が高いです！
さらには、各種有名どこのクラウドプラットフォームでも、Dockerイメージからサーバーを起動できるようになっており、ネットワーク関連の設定を除けば、本番とローカルでまったく同じ環境を作り上げることが可能となりました


# Dockerで最低限覚えておかなければいけないこと
### コンテナ
OSを動かす独立したサーバー仮想環境です。vmwareやvirtual boxをイメージすると近いです
そもそも仮想環境とは、物理的なハードウェア上に論理的に分割した環境のことを言います
それぞれ独立したCPU、メモリー、ストレージを持っていて（独立といっても物理ハードウェアのリソースを使うのですが）、OSを持ってます
OSが持てるということはそれはもうみなさんが使用している一般的なパソコンとさほど変わらない状態といえます

https://docs.docker.jp/get-started/what-is-a-containe.html

https://www.redhat.com/ja/topics/virtualization/what-is-a-virtual-machine

### イメージ
「イメージ」はDockerの専門用語ではありません
一般的にいえば種類は色々あって、「OSイメージ」「アプリイメージ」などなどまとめた物の違いによってprefixが変わったりします
簡単にいうと、OSやアプリを使うために必要な一式が格納されているファイルのことを指し
Dockerの文脈で言うと「コンテナイメージ」と言われ、コンテナを起動するために必要な一式が格納されているファイルのことを指します

https://wa3.i-3-i.info/word12660.html

### Dockerfile（ドッカーファイル）
多分どこでも同じ様な説明になるほどDockerfileの役割というのは明確で
イメージを作成するための設計図になります
以下にサンプルを提示しますが、Dockerfile内の一行一行の実行された結果がコンテナイメージとなります

```Dockerfile
FROM php:7.4-apache
RUN apt-get update && apt-get install -y vim zip unzip
RUN a2enmod rewrite
EXPOSE 80
CMD ["apache2-foreground"]
```

### docker compose（ドッカーコンポーズ）
これは公式の説明を引用するのが一番分かり易そうです
> Docker Compose とは、複数コンテナのアプリケーションを定義・共有するために役立つように、開発されたツールです。Compose があれば、サービスを定義する YAML ファイルを作成し、コマンドを１つ実行するだけで、瞬時にすべて立ち上げたり、すべてを削除したりできます。

通常、Dockerを動かそうと思うと、docker runに対して複数の引数を並べる必要があったり、複数のコンテナ間で通信を行おうと思うと別にネットワーク定義をしなきゃいけなかったりで色々と面倒です。
その面倒を解決してくれるのがcomposeであり、そのcomposeは通常のDocker定義に対してyamlファイルを追加するだけになります

## 各キーワードを関連付けるとこう

![Docker説明.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/3f0d870a-05a0-5fb4-8eb8-8a3749fab060.png)

docker hub（正確にはそれ以外のリポジトリでも可能）からベースコンテナのイメージをダウンロード（docker pull）。
ローカルPC内に持って来れたらそのイメージと自分で作ったDockerfileを合わせて独自のイメージを作成（docker build もしくは docker compose build）。
独自のイメージをコンテナとして起動する（docker run もしくは docker compose up）。

※ docker composeを使用する場合は別途docker-compose.ymlを作成する必要があります

# シンプル構成でDockerを作ってみよう
WEBアプリケーションを構築する場合にミニマムで必要なものといえば、WEBサーバーとDBサーバーですよね
それでは一つずつ作っていきましょう！

## まずはベースコンテナを探す（決める）
Dockerのベースイメージを探す際はdocuer hubを使用します

https://hub.docker.com/

WEBサーバーにはapacheを採用してみましょう
ベースイメージを採用する際に特に気をつけたいのは「Docker Official Image」であるかどうかです
将来的にこのWEBサーバーイメージをどこかにデプロイして運用したい場合にそれが信頼に欠けるイメージだとよろしくないですね
![スクリーンショット 2023-10-31 8.45.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/b58fbcab-8f06-ff79-ede6-e6ed0edfe68e.png)

Tipsですが、「Supported tags and respective Dockerfile links」にあるリンク先に飛ぶと、ベースイメージのDockerfileを確認することができ、これが結構勉強になります
RUNがなぜ可読性度外視でワンライナー形式で書かれているか、どう書くのが一番キャッシュをきかせられるかなどを考えながら見てくのもいいです
![スクリーンショット 2023-10-31 8.54.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/140d3d4e-cd6f-9123-5016-e216f69509fe.png)


DBサーバーはmysqlにしてみましょう
![スクリーンショット 2023-10-31 9.10.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/4c2273b7-2517-86cb-0ac4-bed65d042c81.png)


## 使い方は2パターン
apacheはカスタマイズして、mysqlはカスタマイズなしで動かしてみましょう

### カスタマイズなしにそのまま使う方法
カスタマイズなしに動かすパターンはすごく簡単で、ベースイメージをそのままrunするだけになります

ベースコンテナ: mysql:8.2
こちらで設定するコンテナ名: qiita-docker-mysql
パスワード: password
で動かすパターンは以下になります
```terminal
$ docker run -it --name qiita-docker-mysql -e MYSQL_ROOT_PASSWORD=password -d mysql:8.2
```
これだけです！

接続確認をします

```terminal
% docker exec -it qiita-docker-mysql  bash -p
bash-4.4# mysql -u root -p -h localhost
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.2.0 MySQL Community Server - GPL

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
```

※ 今回の起動方法だとネットワーク設定ができていないため、一度コンテナにアタッチしてからmysqlに繋ぎに行かないと確認ができないので注意です
※ 本記事では割愛しますが、ネットワーク設定を頑張らずにホストPCからコンテナ内のmysqlに直接接続したい場合は、docker composeを使ってしまいましょう

### Dockerfileを作ってカスタマイズして作る方法
カスタマイズする場合には自前でDockerfileを用意する必要があります
フォルダ構成はこんな感じで、apacheを起動して静的ページを表示してみます

```
.
├── Dockerfile
└── public-html
    └── index.html
```

```Dockerfile
FROM httpd:2.4
COPY ./public-html/ /usr/local/apache2/htdocs/
```

```terminal
$ docker build ./ -t qiita-docker-apache
$ docker run -dit -p 8080:80 qiita-docker-apache
```

ここまでやると起動完了で、実際に動かして確認できます！
簡単ですね

![スクリーンショット 2023-10-31 10.05.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/68c0f551-9003-d5c3-0778-97db55339987.png)

### tips
#### dashboard便利
dockerのコマンドいちいち覚えてられないって人は、dashboardから操作するのもありです！
便利なのでぜひ使ってみましょう
![スクリーンショット 2023-10-31 10.13.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/98698cb4-f780-548b-241a-ef316e819f7e.png)

#### docker hubのページはちゃんと読むといい
実は、コンテナの起動方法を上で解説してますが、docker hubの「How to use this image.」の部分にある程度書いてあります！
確認しておきましょう！
![スクリーンショット 2023-11-01 9.28.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/5b5d1d01-1589-69f3-1621-5bef722665f4.png)
![スクリーンショット 2023-11-01 9.29.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/a50bf105-c292-be14-2fb9-ff42e16e8b80.png)


# オススメ文献
Dockerを理解するのにすごいわかりやすいスライドを提供してくださっていますので是非

https://www.slideshare.net/zembutsu/explaining-best-practices-for-writing-dockerfiles

# 参考
NAS：https://www.iodata.jp/product/nas/info/landisk/nas.htm
SVN：https://tortoisesvn.net/