たぶん動くから！DockerでnginxからHTMLページを表示しよう！

#はじめに
この記事では `Dockerfile` を用いた起動と `docker-compose` を用いた起動で `nginx` で `HTML` ファイルを表示するまでを記しています。
初心者のため間違い等ございましたらご指摘いただけると幸いです。

#環境
macOS Catalina version 10.15.6
Docker version 19.03.13
Visual Studio Code version 1.42.1

#前提条件
Dockerをインストールしていること。
インストールしていない場合は以下のリンクを参考にインストールしてみてください。
[たぶん動くから！Docker始めてみよう！](https://qiita.com/leafeon00000/items/a2d694ac52b542c76e01)

#Dockerfileを使った方法
`Dockerfile` を使った基本的な方法で起動していきます。
##フォルダ構成
以下の様なフォルダ構成にしました。

```none:フォルダ構成
root/
├── Dockerfile
├── conf
│   └── default.conf
└── src
    ├── css
    │   └── topPage.css
    ├── js
    │   └── topPage.js
    ├── nextPage.html
    └── topPage.html
```

##各ファイル
各ファイルは以下の通りです。

```dockerfile:Dockerfile
FROM nginx:latest

ADD ./conf/default.conf /etc/nginx/conf.d/default.conf
ADD ./src /usr/share/nginx/html

RUN echo "start nginx"
```
* `FROM nginx:latest` : `FROM` はDockerのイメージのベースとなるものの指定です。今回は `nginx` の最新版を使うという意味です。
* `ADD {ローカルパス} {コンテナパス}` : ローカルパスのものをコンテナパスに追加します。
* `RUN` : Dockerビルド時にDockerのコンテナ内で実行するコマンドを指定します。

```conf:/conf/default.conf
server {
        listen 80;
        listen 443;
        server_name localhost;

        root /usr/share/nginx/html;
        index topPage.html topPage.html;

        location / {
                try_files $uri $uri/ /src/index.html$query_string;
        }

        error_page   500 502 503 504  /50x.html;
                 location = /50x.html {
                   root   /usr/share/nginx/html;
        }
}
```
`default.conf` は `nginx` で用いる設定ファイルです。
当記事では深くは触れません。

```html:/src/topPage.html
<html>
  <meta charset="utf-8" />
  <link rel="stylesheet" href="./css/topPage.css">
  <script src="./js/topPage.js"></script>
  <body>
    <h1 style="color:red;">Hello Enginx with Docker!!</h1>
    <a href="./nextPage.html">next</a>
  </br>
  <p>css!</p>
  <button type="button" onclick="execute()">実行！!!
  </button>
  <div id="output"></div>
  </body>
</html>
```
```html:src.nextPage.html
<html>
<body>
  <h1>nextPage!</h1>
  <a href="./topPage.html">back</a>
</body>
</html>
```
CSSとJavaScriptは動作するかどうかの確認のため適当に作成します。

```css:/src/css/topPage.css
p {
  color : red;
}
```
```js:/src/js/topPage.js
function execute() {
  var elem = document.getElementById("output");
  var now = new Date();
  var hour = now.getHours();
  var min = now.getMinutes();
  elem.innerHTML = "ただいまの時刻は" + hour + ":" + min + "です";
}
```

##Dockerfileを使った起動
ファイルが用意できたらターミナルで `Dockerfile` が配置されているディレクトリへ移動し、 `docker build` コマンドでコンテナイメージを作成します。

```sh
$ docker build -t app:0.0.1 .
```
* `-t` : タグ付けすることができます。タグ付することでコンテナの起動やイメージを削除するときにタグ名が割り当てられるので管理が楽になります。また、`:`コロンで区切ることでバージョンを指定することもできます。
* `.` : `Dockerfile` が配置されているパスを指定します。今回は `Dockerfile` の配置されているディレクトリでコマンドを叩いているので `.` ですね。

コンテナイメージが作成できているかを確認します。

```sh
$ docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
app                     0.0.1               8ddbfbb33917        14 hours ago        133MB
```
`app` というコンテナイメージでバージョンが `0.0.1` の物が作成されていますね。

次にコンテナイメージから `docker container run` コマンドで実際にコンテナを起動させます。

```sh
$ docker container run --name app --rm -d -p 8080:80 app:0.0.1
```
* `--name app` : appという名前で起動します。こちらもコンテナイメージをビルドするときと同じく、イメージ名を指定すると管理が楽になるので指定します。
* `--rm` : コンテナを停止した際に自動的にコンテナを削除してくれます。
* `-d` : コンテナをバックグラウンドで実行します。
* `-p {ローカルポート}:{コンテナポート}` : ローカルのポートをコンテナのポートに転送します。
* `app:0.0.1` : 起動するコンテナイメージを指定します。

起動しているか確認します

```sh
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
f64c1f7ef410        app:0.0.1           "/docker-entrypoint.…"   7 seconds ago       Up 6 seconds        0.0.0.0:8080->80/tcp   app
```
コンテナは起動している様ですね。
http://localhost:8080/ へアクセスしてみます。

|![スクリーンショット 2020-10-18 14.56.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547651/28d93ee2-fa32-d1e7-0bdd-92911bdc1a31.png)|
|:-:|

画面が表示され、CSSが動作していることも確認できますね！

「実行」ボタンを押してみます。

|![スクリーンショット 2020-10-18 14.57.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547651/c624bdb7-9111-9f57-9b9f-9b971a40c0f3.png)|
|:-:|
JavaScriptも動作していますね！

「next」リンクをクリックしてみましょう。

|![スクリーンショット 2020-10-18 14.58.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547651/1bcf5397-46ab-d171-78ed-e95cd7ddf9a5.png)|
|:-:|
nextPageへのページ遷移もできましたね！

起動中のコンテナ内に入りたい場合は `docker exec` コマンドを使用します。

```sh
$ docker exec -it app bash -p
``` 

コンテナを停止させ、コンテナ一覧を確認します。

```sh
$ docker stop app
app
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                         PORTS               NAMES
```
停止していますね。
* `-a` : `-a`オプションは停止中のコンテナも表示してくれます。起動時に `--rm` オプションを付けていたので停止時に自動的にコンテナを削除してくれていますね。 `--rm` オプションを付けなかった場合どんどん停止されたコンテナが溜まっていくので注意です。削除したい場合は `docker rm {CONTAINER ID}` で削除してください。
 

#docker-composeを使った方法
`docker-conmpose` はDockerをインストールすると一緒に入っています。
本来はwebサーバーやDBサーバー等、複数のコンテナの管理に用いると便利なのですが、~~私の技術が足りないため~~今回はnginxのみを乗せた `docker-compose` を作成します。

##フォルダ構成
docker-compose.ymlを追加し、先ほどのDockerfileの構成をnginxフォルダ内に格納しました。

```none:フォルダ構成
root/
├── docker-compose.yml
└── nginx
    ├── Dockerfile
    ├── conf
    │   ├── default.conf
    │   └── nginx.conf
    └── src
        ├── css
        │   └── topPage.css
        ├── js
        │   └── topPage.js
        ├── nextPage.html
        └── topPage.html
```

##docker-compose.yml
`docker-compose.yml` でコンテナのイメージビルドからコンテナ起動までを定義します。

```docker:docker-compose.yml
version: '3'               #このdocker-compose.ymlファイルの"書式"のバージョン
services:                  #サービスについて定義する。
  nginx:                   #nginxについて定義するという宣言。
    build: ./nginx         #Dockerfileのパス
    image: app:0.0.2       #イメージ名を指定
    container_name: "app"  #コンテナ名を指定
    ports:                 #ポート公開内容を指定する。
      - "8080:80"          #コンテナ側で80だとホスト側で8080となる。
    volumes:               #ホストのフォルダをコンテナに追加する。 ホスト側:コンテナ側
      - ./nginx/conf/default.conf:/etc/nginx/conf.d/default.conf  #コンフィグファイルをコピー
      - ./nginx/src:/usr/share/nginx/html         #ソースをコピー
```
`volumes` は `Dockerfile` で記述している部分と被るので省略可能です。

DBサーバーや他のサービスに等を増やしたい場合は `nginx` と同列に追記していきます。


##docker-composeを使った起動
`docker-compose.yml` が配置されているフォルダに移動し `docker-compose up` コマンドを使用します。

```sh
$ docker-compose up -d
Starting app        ... done
$ docker ps
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS              PORTS                               NAMES
94af0a7f210d        docker_plactice_nginx   "/docker-entrypoint.…"   2 minutes ago       Up About a minute   0.0.0.0:8080->80/tcp                app
```
起動が確認できますね！
`Dockerfile` での起動でポート等指定していたのに対し、 `docker-compose` での起動は楽ですね！

停止するときは `docker-compose down` コマンドを使います。

```sh 
$ docker-compose down
Stopping app        ... done
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
```
起動中のコンテナはありませんね。

#終わりに
当記事では `docker-compose` の便利さが全然引き出せていない状態で終わってしまいました。 
今回は私の中で一旦整理したいという目的もあり、中途半端になって申し訳ありません。
次回は `docker-compose` で複数のコンテナの同時起動の記事が書けたらいいなぁ…。