Dockerを少しずつ理解しようっていうお話

# はじめに
初めまして！
エンジニアになって数年、今まで本を読むだけでしたが、もっとプライベートで楽しみながら成長したい！自分が学んだ足跡を残していきたい！と思い記事をかきました！
最終的には自在に開発できるようになりたいと思っています。:triumph:
いろいろな記事を参考にさせてもらっています。:bow_tone2:
その中でもこれってどういう意味？とかつまづいたところを念入りに書いていこうかと思います。:fist:



# 今回の目的
Dockerってもらったものそのまま使えば簡単に動いちゃうのでとてもやりやすい！なんて思うんですけど、一から作ってとなると「はて？どうすればいいのかわからない・・・」とはっきりしてません。:cry:
最小限でDockerを動かしながらそれぞれがどんな役割をしているの？どんなことを書いているの？を理解していきます！

# 使用したものや事前準備
・Macbook Pro
・Docker Desktop
・Docker Hub
・Visual Studio Code

# 主に参考にさせていただいた記事
下記の書籍をベースに勉強しました。

https://book.impress.co.jp/books/1121101138

# 検証を始める前に
任意のディレクトリでプロジェクト用のファイルを作りました。

```
mkdir docker-test
```
最小構成で段々と作っていきます。

# コマンドだけでコンテナを立ち上げる
Dockerfileっていうものがあるんだからそれ使わないといけないんじゃないの？？って思っていました。でもその認識自体が間違えていました。:worried:
ベースイメージをDocker Hubから引っ張ってきてメモリ上でコンテナを立ち上げられればいらないのです。

下記のコマンドを実行します。

```
docker container run --name apache01 -p 8080:80 -d httpd
```

※dockerコマンドがない方はDockerとDocker Desktopをセッティングしてください

<dl>
  <dt>コマンドの説明</dt>
  <dd>・httpdのイメージを元にapache01というコンテナを起動するぞ、8080でアクセスしてきたらコンテナの80に繋ぐぞっていうコマンドです。</dd>
  <dd>・--nameはコンテナ名、-pはポートのマッピング、-dはバックグラウンドで実行するオプション</dd>
</dl>

<bold>http://localhost:8080/</bold>にアクセスして、こんな画面になれば立ち上げ成功です。

![スクリーンショット 2024-02-18 16.51.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/8a547ab5-7eae-b018-153e-979953140dca.png)

docker psを打ち込んでみると先ほど設定した内容でコンテナが動いていることが確認できます。

```
docker ps
```
![スクリーンショット 2024-02-18 16.52.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/4d6ab738-ba23-d554-baa9-2ad601ffb04d.png)

次の検証に移るので停止させましょう。

```
docker stop apache01
```
docker ps -aで停止したコンテナを確認できます

![スクリーンショット 2024-02-18 16.56.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/2d986a61-75be-e757-8b45-4498aa33c364.png)

# Dockerfileでイメージをカスタマイズしコンテナを立ち上げる
イメージを引っ張ってきたけど、ほんとはフレームワークも入っているイメージがほしいんだよなぁ〜とかそういう悩みがある時は、Dockerfileに書けばカスタムできちゃうっていうお話です。
今回はあっさり系で進めちゃうので最後のコマンドはほぼ同じになります。

Visual Studio Codeを立ち上げて検証用のプロジェクト（docker-test）を開きましょう。
Dockerfileを作成して、下記のように作成してください。
EXPOSEには公開するポート番号の明示のみのため80を記載します。
コンテナ名は設定できないためスキップします。

``` Dockerfile
FROM httpd
#RUN 
#CMD [ "" ]
EXPOSE 80
#COPY
#ADD
#ENTRYPOINT
#WORKDIR
```

作成できたらDockerfileを元にイメージを作成します。ベースをカスタムし再作成する工程ですね。

```
docker build -t image-apache02 .
```

![スクリーンショット 2024-02-18 18.01.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/9f944278-7145-ea20-538a-87165cca1af4.png)


イメージが出来上がったことを確認しましょう。

```
docker image ls
```

![スクリーンショット 2024-02-18 18.00.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/b1ed2afa-ac9b-1b63-f060-4ebedf4b2937.png)

イメージに書いてある情報を見ながら[REPOSITORY:TAG]を指定しコンテナを立ち上げます！
```
docker run --name apache02 -p 8080:80 -d image-apache02:latest
```
<bold>http://localhost:8080/</bold>にアクセスして立ち上がっていることも確認。

![スクリーンショット 2024-02-18 16.51.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/8a547ab5-7eae-b018-153e-979953140dca.png)

docker psを打ち込んでコンテナ名が今回のものであることも確認します。

```
docker ps
```

![スクリーンショット 2024-02-18 18.08.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/af543aba-650c-0a23-e284-2c9060c8318b.png)

IMAGEやNAMESが今回のものになっていることを確認できたら、
次の検証に移るので停止させましょう。
```
docker stop apache02
```
docker ps -aで停止したコンテナを確認します。前回のとほぼ同様なものがあることを確認できました。

![スクリーンショット 2024-02-18 18.10.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/dd2e4d3c-fd6a-69fe-742a-3d084d17ddd3.png)

# compose.ymlでコンテナを立ち上げる
今までのhttpdサーバーの設定は単純だったのでコマンドが簡潔にすみましたが、DBのユーザー設定をしたいやPATH 環境変数の設定をしたいとか、なんやかんやあった場合、コマンドに入れると冗長になり間違いの温床になります。
compose.ymlはコンテナの立ち上げ時にコードベースで独自設定ができるので、一旦作成すればどこでも同じコンテナができるわけです。

Visual Studio Codeで検証用のプロジェクトを開いているかと思います。
compose.ymlを作成して、下記のように作成してください。
ymlファイル全体に言えることかもしれないですが、スペースや改行も処理の判定対象になっているので注意しましょう。

``` yml
services:
 web:
  image: httpd
  container_name: apache03
  ports: 
    - "8080:80"
```

これで準備完了です。下記のコマンドを実行しコンテナを立ち上げます。
```
docker compose up -d
```
<bold>http://localhost:8080/</bold>にアクセスして〜以下略

docker psを打ち込んでコンテナ名が今回のものであることも確認。あっという間にできました。
![スクリーンショット 2024-02-18 18.44.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/f3ff373a-1feb-0f49-4659-220cb6ea8ca5.png)

次の検証に移るので停止させましょう。
```
docker stop apache03
```

# compose.ymlで複数台コンテナを立ち上げてみる
compose.ymlのいいところはイメージまたはDockerfileをビルドし複数コンテナを立ち上げられるところにあると思います。
コンテナ間のネットワークもcompose.ymlに書き込めばチャチャっとやってくれるので最高です。

※参考書籍のsection10に沿ってやっていきます。※

構築するものはPHP+Apache+MariaDBです。
PHPからコネクション要求して繋がれば連携できているっていう構成ですね！

今までに作ってきたものを修正して構築していきます。
#### ⚫︎Dockerfile
RUNコマンドでは、
・パッケージリスト更新
・PHPの一部のライブラリが必要とするためOnigurumaの開発バージョンをインストール（ユーザー操作介入なし）
・PHP拡張機能をコンパイルしてインストールするコマンド
・PHPからMySQLデータベースへの接続を可能にするPDO（PHP Data Objects）ドライバのインストール
を行っています。

``` Dockerfile
FROM php:8.0-apache
RUN apt-get update && apt-get install -y libonig-dev && docker-php-ext-install pdo_mysql

```
#### ⚫︎Compose.yml
<dl>
  <dt>build: .</dt>
  <dd>指定の位置にあるDockerfileをbuildしてコンテナのイメージとして使いますよって意味です。</dd>
  <dt>depends_on</dt>
  <dd>コンテナの依存先です。今回はdbコンテナが起動を開始した後にphpコンテナが起動を開始します。</dd>
</dl>


volumesに二通りの書き方があってむむっとなりました。:frowning2:
<dl>
  <dt>コンテナ内に書いてあるVolumes</dt>
  <dd>バインドマウント</dd>
  <dt>最下部に書いてあるVolumes</dt>
  <dd>名前付きボリュームといいDocker側でデータを永続的に保管できたり、コンテナ間で共有できる</dd>
</dl>

内部で作られているデータを外に吐き出す場所という認識程度。
大事なデータとかは名前付きボリュームに出して、プロジェクト切り替えても同じデータを見ることができるとかが、ポイントなのかな？？（なんとなくありがたみがわかる程度・・・）

``` yml
services:
 db:
  image: mariadb:10.7
  environment:
   MARIADB_ROOT_PASSWORD: rootpass
   MARIADB_DATABASE: testdb
   MARIADB_USER: testuser
   MARIADB_PASSWORD: testpass
  volumes:
   - db-data:/var/lib/mysql
 php:
  build: .
  depends_on: 
    - db
  ports: 
    - "8080:80"
  volumes:
    - ./src:/var/www/html
volumes:
 db-data:
 ```

 #### ⚫︎dbsample.php

srcフォルダを作ってその配下に作成しましょう。

![スクリーンショット 2024-02-18 21.07.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/14adcb9c-30f7-5bdb-94f8-a069547f26e4.png)
 
 脳死コピペになってしまいそうだったので公式ドキュメントを見て書き方を変えてみることに・・・。

 https://www.php.net/manual/ja/pdo.connections.php

DBコネクション閉じないのかな？と思ったけど参照元がなくなる（nullとか）か、スクリプトが終了する（exit)と勝手に閉じるらしい。POD使っとけ！って感じですね。多分。

``` php
<?php
  try {
    $dbh = new PDO('mysql:host=db;dbname=testdb','testuser','testpass');
    echo "OK";
    $dbh = null;
  }catch(PDOException $e){
    echo "NG";
    exit;
  }
?>
```

準備完了！実行します！
```
docker compose up -d
```

docker psを打ち込んでコンテナ名が今回のものであることも確認します。

```
docker ps
```

イメージ名はプロジェクト名-buildコマンドがあるコンテナ名って感じですね。
コンテナ名もそのままではなくてややこしい説明になってしまったかも。

![スクリーンショット 2024-02-18 20.47.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/b4e2bdae-8b0b-9c21-45e1-7948c7287f41.png)

phpを開いて、レスポンスが返ってくるか確認しましょう。
<bold>http://localhost:8080/dbsample.php</bold>にアクセスします。

OKが表示されたら完了です！

![スクリーンショット 2024-02-18 20.51.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/84d7c561-777a-d431-a624-be93de2de77d.png)

複数コンテナを一回で停止させましょう。
```
docker compose stop
```

# 最後に
一つずづ見ていったらどんな役割があるか理解できました。Dockerfileがコンテナを立ち上げていると勘違いしていたのでいい勉強になりました。:sweat:

# おまけ
より大きく実践してみました、

https://qiita.com/mr_noppo/items/1643652347ecfd836889