【超初心者】Docker を使用して自作 Web サイトを表示してみた
1. はじめに
Webページが表示される仕組みの続編になります。(別に読まなくても大丈夫なように記事は執筆しました。)
本記事では、「Web サイトが表示される原理」、「Docker での Web サーバーの構築」、「Web サイトの作成」の順に説明して、自ら作成した Web サイトが表示されるところまでを体験することが目標になります。
かなり初心者向けの記事になります。
(結果的に、自作の Web サイトを表示することが目的なのに、Docker の使い方の記事みたいになってしまいました、、、)
1-1. Why Docker?
Web サイトを作成するためには Web サーバーが必要になりますが、今回の目標を達成するには凝った機能は必要なく、ただ URL でアクセスしたときにコンテンツを返却してくれるだけで十分であるため、手軽に Web サーバーを構築できるを利用できる Docker を使ってみようと思いました。
(なお、筆者は Docker は初めて触ります。)
本記事を投稿する上で、以下の記事がとても参考になりました。
Docker 公式 httpd イメージを利用して Docker を体験してみよう
結局、本記事は、ほぼその記事の丸写しになってしまいましたが、備忘録もかねて投稿いたします。
2. 事前に知っておきたい知識
ご存知の方は飛ばしていただいて結構です。
2-1. Web ページが表示される仕組み
細かい説明は省きますが、図で表すと以下のようになります。(参照元ページ)
本記事では図の右側のWebサーバーをローカル PC 上の Docker のコンテナ上で稼働させます。
なお、今回はローカル PC 上のコンテナに直接アクセスするため、DNS サーバーによる名前解決は行いません。
(つまり、今回は ① と ② は扱いません。いきなり ③ → ④ となります。)
2-2. Webサーバー
Web サーバーとはクライアントからの要求に対し、Web ページを閲覧するために必要なデータを転送するサーバーのことです。
「クライアントからの要求」とは、HTTP リクエスト のことで、ブラウザでアクセスする URL をみると「https://〜」となっていると思いますが、その頭文字の http とは HTTP リクエスト であることを意味しております。
つまり、Web サーバーに対して、HTTPリクエスト をすると Web ページを閲覧するために必要なデータ(HTML、CSS、JavaScript、動画、写真など)を転送してくれます。
2-3. ドキュメントルート
ドキュメントルートとは、Web サイトで外部から公開される HTML ファイルや画像データなどが設置される場所のことを指します。
もし、仮にドメインが「http://example.com」である場合、ドキュメントルートに指定したディレクトリに「hogehoge.html」というHTMLファイルを設置していると「http://example.com/hogehoge.html」とブラウザからアクセスすると、Webサーバーはhogehoge.htmlを返却して、ブラウザにhogehoge.htmlの内容が表示されます。
また、「http://example.com」とアクセスした場合、デフォルトでその階層の**「index.html」**を返却するようになっています。
(これを知らないと 「index.html」って何だろう? となってしまうため結構大事かも。。。)
2-4. Web サーバーの種類
Web サーバーにも種類があります。
世界的にシェアが高いのは**「Apache」「Nginx」「IIS」**の3種類です。
まず、IIS は Windows サーバー縛りという環境でなければ使うことがないでしょう。
そうなると「Apache」と「Nginx」の2択になりますが、Nginx の方が処理が軽く大量のリクエストを処理するのに向いていおり、さらにリバーシプロキシ機能までついているおまけ付きであり、現在では Nginx の方が人気らしいです。
どちらを使うかは case-by-case であるので状況に応じて使い分けてください。
比較する記事がネットには溢れていました。(個人的にはこちらがわかりやすかったです。)
今回は単に手元で Web サーバーとして動けば何でもよかったので、Apache でも Nginx でもどちらでもよかったのですが、参考にした記事が Apache の httpd の Docker イメージを使用していたので、そちらを採用しました。
「httpd」って何?って思う方もいらっしゃると思いますが、「Apache で Web サーバーとしての機能をする常駐のプログラムのこと」だと思っていただければ大丈夫です。(参考記事)
2-5. Docker
Docker についてここでは詳しく説明しませんが、Docker とはコンテナ型の仮想化環境を提供するプラットフォームのことです。
とりあえず、Docker を使えば簡単に開発環境を構築することができるということだけ抑えてもらえれば大丈夫です。
今回は Docker を使用して自身の環境に Web サーバーを構築します。
また、Docker を使用するには自身の環境にインストールする必要があるので、以下の記事などを参考にインストールしてください。
Docker を Mac にインストールする(更新: 2019/7/13)
そもそも Docker について知りたいという方は以下の記事がとても勉強になりましたのでご参考まで。
Docker 入門の前に知っておきたい基礎知識 - 週末勉強会レポート
3. Docker での Web サーバーの構築
Webサーバーとして有名な Apache httpd だけを含んでいる httpd という Docker イメージが公式の Docker Hub リポジトリで公開されています。
今回はこちらを使用します。
<img width="782" alt="スクリーンショット 2020-07-25 22.00.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/eaf5314d-03bd-dc51-3652-fcb996a5a5a0.png">
また今から使用する Docker のコマンドは大きく以下のようになります。(参照元)
3-1. httpd イメージのダウンロード・確認(docker image pull、docker image ls)
まずはローカル環境に Docker イメージを持っておく必要があります。 現在ローカルで持っているイメージを確認するにはdocker image ls
コマンドを実行します。
初期状態では一つも Docker イメージがないはずなので以下のように表示されます。
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
Docker Hub からイメージを取得するには、docker image pull [サービス名]:[タグ名]
とコマンド入力します。
httpd のイメージを pull する際に指定できるタグ名は、Docker Hub のタグ一覧のページから確認することができます。
<img width="711" alt="スクリーンショット 2020-07-25 22.11.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/8e859494-2b0e-fde7-0cd4-4442d177fa44.png">
docker image pull [サービス名]:[タグ名]
と入力する際に、タグ名を省略した場合はデフォルトで latest を指定したことになります。
今回は Apache httpd の最新版をインストールできればよいのでタグ名を指定せずに実行します。
$ docker image pull httpd
Using default tag: latest
latest: Pulling from library/httpd
6ec8c9369e08: Pull complete
819d6e0b29e7: Pull complete
6a237d0d4aa4: Pull complete
cd9a987eec32: Pull complete
fdec8f3f8485: Pull complete
Digest: sha256:2a9ae199b5efc3e818cdb41c790638fc043ffe1aba6bc61ada28ab6356d044c6
Status: Downloaded newer image for httpd:latest
docker.io/library/httpd:latest
docker image ls
コマンドでダウントー度されていることを確認します。
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
httpd latest 9d2a0c6e5b57 2 days ago 166MB
httpd のサービスがあることが確認できるかとおもいます。
3-2. httpd イメージからコンテナを作成・起動する(docker container run)
Docker イメージの取得ができたら、次は実行させます。
イメージからコンテナを作成して起動するには、docker container run (オプション) [イメージ名]
とコマンドを実行します。
$ docker container run -d -p 8080:80 httpd
d2e80c20cfbdcf7aee76772a790821e529bbbdfe07329e9179ea32939cb85797
今回docker container run
コマンドで指定したオプションは-d
と -p 8080:80
のオプションです。
これらについて解説します。
-d
オプションは、コンテナの実行をバックグラウンドで行うオプションです。 このオプションを指定しなかった場合は、ターミナルのコマンド操作が Ctrl+C を実行するまでコンテナに奪われてしまいます。
-p 8080:80
オプションは、コンテナのポート番号とローカルのコンピュータのポート番号を紐づけるオプションです。
今回実行したコンテナは httpd の機能を持っておりコンテナの80番ポートで httpd サービスが開始されるので、ローカルマシンの8080番ポートをコンテナの80番ポートに紐づけたことになります。
一旦、これで Web サーバーである httpd コンテナの実行が完了しましたので、ブラウザで http://localhost:8080 にアクセスしてみてください。
「It work!」の表示がされるはずです。
<img width="417" alt="スクリーンショット 2020-07-25 18.45.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/82bcbd14-00a3-aafb-f803-3f0b28df0459.png">
これは、Web サーバーのドキュメントルートにデフォルトでおいてある index.html (あとで確認します)が返却されてその内容がブラウザに表示されているということです。
たったこれだけで Web サーバーを立てることができるとは、Docker はほんとに素晴らしいですね。
ポート番号についてちょっとした解説
Webサーバーは一般的に80番ポートで http 通信を待ち受けています。
また、ポート8080番は代替 HTTP ポートと呼ばれ、大抵のプロキシサーバは8080番でサービスを待ち受けています。
以下の図で表すと、クライアントAがブラウザ、プロキシサーバーBが自身の Mac の PC、Web サーバーCが Docker コンテナ上で動いている httpd というイメージです。(参照元)
3-3. 実行中のコンテナを確認する(docker container ls)
現在実行中の docker のコンテナの確認はdocker container ls
のコマンド実行によって確認ができます。
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d2e80c20cfbd httpd "httpd-foreground" 4 minutes ago Up 4 minutes 0.0.0.0:8080->80/tcp clever_chatelet
httpdのコンテナプロセスが起動していることが確認できます。
3-4. コンテナの停止・起動(docker container stop、docker container start)
実行中のコンテナを一時的に停止したい場合、docker container stop
コマンドを利用します。 コマンドの引数として、コンテナのIDを指定する必要があります。
コンテナのIDは上記で説明したdocker container ls
のコマンドで確認できます。
docker container stop d2e80c20cfbd
d2e80c20cfbd
docker container ls
のコマンドで先ほど docker container stop
コマンドで指定したプロセスが起動していないことを確認します。
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
停止させたコンテナも表示させたい場合は、docker container ls
コマンドに -a
オプションをつけて実行します。 表示された結果の STATUS の欄に Exited と表示されている点に着目してください。
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d2e80c20cfbd httpd "httpd-foreground" 7 minutes ago Exited (0) About a minute ago clever_chatelet
この停止したコンテナを再度起動したい場合は、docker container start
コマンドにコンテナIDを指定して実行します。ポイントは一度docker container run
したコンテナは、再びdocker container run
するのではなくdocker container start
コマンドによって再起動させます。
そうしないとdocker container run
する度に別のコンテナが生成されて、httpd のコンテナが複数作られることになります。
$ docker container start d2e80c20cfbd
d2e80c20cfbd
起動後にまた docker container ls
コマンドを実行すれば、再度実行中であることがわかります。
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d2e80c20cfbd httpd "httpd-foreground" 9 minutes ago Up About a minute 0.0.0.0:8080->80/tcp clever_chatelet
3-5. コンテナへのログイン
実際にコンテナにログインしてみて、httpd のドキュメントルートの状況を確認してみたいと思います。
コンテナには docker exec -it [コンテナID] /bin/bash
とコマンド実行すると、そのコンテナにログインすることができ、コマンド操作をすることができます。
$ docker exec -it d2e80c20cfbd /bin/bash
root@d2e80c20cfbd:/usr/local/apache2# (指定したコンテナ内のコンソール)
httpd イメージでは、Apache httpd のドキュメントルート(DocumentRoot)は、/usr/local/apache2/htdocs/
となっていますので、そこを確認してみます。
root@d2e80c20cfbd:/usr/local/apache2# cd /usr/local/apache2/htdocs/
root@d2e80c20cfbd:/usr/local/apache2/htdocs# ls
index.html
root@d2e80c20cfbd:/usr/local/apache2/htdocs# cat index.html
<html><body><h1>It works!</h1></body></html>
ドキュメントルートには「It works!」と書かれた index.html という HTML ファイルがあることが確認できますね。
これがさきほど、ブラウザで http://localhost:8080 にアクセスしたときに表示されたものになります。
ちなみに、ログインしたコンテナからは exit
コマンドでログアウトできます。
root@d2e80c20cfbd:/usr/local/apache2/htdocs# exit
exit
$ (Macのコンソール)
4. 自作の Web サイトを作成する
さて、ここまでで Docker を利用して Apache httpd を実行できることはお分かり頂けたでしょう。 しかし一つ問題は、表示できた WEB サイトは Apache httpd デフォルトの「It work!」という画面だということです。
ここでは、もうひと頑張りして、自作の HTML を作成して、それを表示してみようということになります。
自作する HTML ファイルの保存場所についての考察
まず、自作する HTML ファイルの保存場所について考察します。それには Docker コンテナの生存期間について考える必要があります。
そもそも Docker コンテナのような技術はポータビリティの考え方が重要で、「必要な時にコピーして持ってきて起動し、必要なくなったら破棄する」という考え方が根底にあります。「破棄する」とはコンテナやサーバーごと削除してしまうことを指し、その破棄をする時にファイルのバックアップなどの煩わしい事を考える必要がないことも重要です。
よって、コンテナやサーバー内にバックアップしたいようなコンテンツを保存してしまうと面倒となってしまいます。
このような考え方から、いつ破棄されてしまうか分からないコンテナにはコンテンツやログなどの動的なファイルを保存せず、常時起動されていることが確約されているマシンにコンテンツや動的なファイルを保存するのが良いでしょう。
裏を返すと httpd の Docker コンテナのドキュメントルートに直接保存していくということはしないということになります。
今回は起動した Docker コンテナに HTML を保存するのではなく、Docker を起動しているローカルマシン側に HTML を作成して、起動した Docker コンテナからそれを参照するようにします。 そうすることで、Docker コンテナは破棄されても、ローカルマシンにある HTML ファイルには影響がありません。
4-1. Web ページ作成用のディレクトリの作成
ローカル環境に適当なディレクトリ(今回の場合は/tmp/httpdHtdocs
)にHTMLファイルを配置します。
$ cd /tmp
$ mkdir httpdHtdocs
$ cd httpdHtdocs
$ echo "This is test page." > index.html
$ ls
index.html
$ cat index.html
This is test page.
今回、index.html の中身は適当でよいのでとりあえず、「This is test page.」 としました。
4-2. httpd コンテナのドキュメントルートの指定(docker container run -v)
docker run
コマンドでコンテナを起動する際に、-v "[ホストディレクトリの絶対パス]:[コンテナの絶対パス]"
のオプションを指定することでコンテナにローカルマシンのディレクトリをマウントすることができます。
先ほど確認したように、httpd イメージでは、Apache httpd のドキュメントルート(DocumentRoot)は、/usr/local/apache2/htdocs/
となっています。
なので、ホストディレクトリの絶対パスに/tmp/httpdHtdocs
、コンテナの絶対パスに /usr/local/apache2/htdocs/
を指定して、docker container run
コマンドを実行します。
$ docker container run -d -p 8080:80 -v "/tmp/httpdHtdocs:/usr/local/apache2/htdocs/" httpd
c789395b6476f694ac991f7b207d4d1007229f6c5a41f4af8d2dd2bf14ee88f2
docker container ls
コマンドによってコンテナが起動していることの確認します。
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ec4edd39d7ff httpd "httpd-foreground" 16 minutes ago Up 16 minutes 0.0.0.0:8080->80/tcp happy_hoover
この状態でブラウザで http://localhost:8080 にアクセスしてみてください。
マウントする前では、「It work!」とデフォルトのページが表示されていましたが、マウント先の/tmp/httpdHtdocs
がドキュメントルートになっているため、さきほど index.html に記述した「This is test page.」の表示がされるはずです。
<img width="418" alt="スクリーンショット 2020-07-25 19.21.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/9495575d-8346-597b-ba95-e3a268d31e5f.png">
これにて自作 Web サイトの完成です。
おめでとうございます。
5. Web サイトの拡張
これからどうやってWebサイトを拡張していくかはおまかせします。
試しに HTML、CSS、JavaScript のそれぞれのファイルを作成して、HTMLからCSSとJavaScriptのファイルを読み込ませたサンプルを GitHub に投稿してみたので参考にしてみてください。
([こちら]((https://github.com/suguruTakahashi-1234/sample_web_page
))になります。)
もっとこだわっていくとルーティングや、今後ファイルがどんどん増えていくと思うのでディレクトリ構成なども考えていく必要があります。
実際はサンプルのような形でWebサイトを書いていくということなく、フレームワークの React / Vue / Angular を用いてもっといい感じにやっていると思います。
6. Docrker の後片付け
コンテナを無意味に起動しておく必要はないため、必要に応じて以下のコマンドでコンテナの停止・削除、イメージの削除を行ってください。
Docker は簡単に同じ環境を構築することができるので、コマンドの練習も兼ねてためらわずに消してしまいましょう。
6-1. コンテナの停止
docker container stop
コマンドによってコンテナを停止します。
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c789395b6476 httpd "httpd-foreground" 43 minutes ago Up 43 minutes 0.0.0.0:8080->80/tcp focused_ptolemy
$ docker container stop c789395b6476
c789395b6476
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6-2. コンテナの削除
docker container rm
コマンドによってコンテナを停止します。
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c789395b6476 httpd "httpd-foreground" 2 hours ago Exited (0) About an hour ago focused_ptolemy
$ docker container rm c789395b6476
c789395b6476
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6-3. イメージの削除
docker image rm
コマンドによってダウンロードしたDockerイメージは削除できます。
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
httpd latest 9d2a0c6e5b57 2 days ago 166MB
$ docker image rm httpd
Untagged: httpd:latest
Untagged: httpd@sha256:2a9ae199b5efc3e818cdb41c790638fc043ffe1aba6bc61ada28ab6356d044c6
Deleted: sha256:9d2a0c6e5b5714303c7b72793311d155b1652d270a785c25b88197069ba78734
Deleted: sha256:d501b5ad5ac59deebf3d002fda60014429d851340ee8f80dfe745e525aaba281
Deleted: sha256:c0ffe105e5d8c201ddc0fa3aa0d75d1f77c88632a5dabe196b1fb837ac83dd73
Deleted: sha256:58da7575a150b2378511246c3d1091d24319d25db05319a07bcda674d089e3a1
Deleted: sha256:5e73f7688a03b2696608629be23d77a75183cc9ac2a5b622b513a8df5ee04573
Deleted: sha256:95ef25a3204339de1edf47feaa00f60b5ac157a498964790c58c921494ce7ffd
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
6-4. Mac 上での Docker のサービスの停止
デスクトップ上部のタスクバーの Docker のアイコンから停止することが可能です。
<img width="299" alt="スクリーンショット 2020-07-25 21.52.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/890fad75-d016-6747-fbb5-544a8b7713dd.png">
また、『起動しててもよいがメモリをリソースは最小限に抑えたい!』ということであれば、タスクバーの Docker のアイコンから Preferences -> Resources でリソースを調整することができます。
<img width="1042" alt="スクリーンショット 2020-07-25 21.52.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/8a186f16-c977-62f5-7b90-68e1487f940a.png">
7. 最後に
意外と知ってたようで、知らないことが多く記事を書いていてとても勉強になりました。
知識不足を痛感しました。。。
参考
Docker 公式 httpd イメージを利用して Docker を体験してみよう
httpdとは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
ルーティングとURL生成
Webページ表示の仕組みと表示までの流れ
Webサーバはどのように動いているのだろう?~HTTP・URL・クッキー編~
ApacheとNginxについて比較
Docker入門の前に知っておきたい基礎知識 - 週末勉強会レポート
Discussion