【Docker】画面表示しない時に見る場所『Python×Django×Nginx×MySQL』

【Docker】画面表示しない時に見る場所『Python×Django×Nginx×MySQL』

【Docker】画面表示しない時に見る場所『Python×Django×Nginx×MySQL』

今回コンテナづくりで四苦八苦したので備忘録化したいと思います。

現象としては Dockerfile作ってコンテナ立ち上げて、全てDoneになるのに画面が出ない コレです。

やってはいけない確認不足

今回の事例は【思い込み】が大きなFactorです。

Dockerを介さない『Python×Django×Nginx×MySQL』構築の場合、Python×Djangoに不備があってもNginxがエラーをアナウンスしてくれます。が、Dockerの場合、両方のコンテナが止まるんですね。
私の場合、この「コンテナの状況確認」を怠ったがためにハマりました。

最初に確認すべき箇所

まずは作成したコンテナが動いているかを確認します。

コンテナの状況を【sudo docker ps -a】で確認して、この中のSTATUSを見ます。

上の例だとnginxとweb_app が 『Exited (終了しました)』と止まっています。
その為、この状態で接続を行うと「IPで接続が拒否されました」とブラウザにアナウンスされます。
コンテナが止まっていればURLにACCESSしたところで動くわけがないですよね。

Dockerコンテナは存在しないものを動かそうとするとExitedする

無いものを動かそうとスタンバっていても意味はないですから妥当な措置ですよね。
ただ、この事を知っていると場合分けが格段に楽になります。

例えばNGINX。これはdocker-composeで下の様に書いてました。

app(Python×Docker)で処理したページをNGINXに渡して表示してもらうとなるわけですが、この際のページが存在しないとどうなるか。ちょっと実験してみます。

実験の方法と概要

  1. Pythonコンテナを通さないで直接index.htmlを閲覧するコンテナを作る
  2. 直接index.htmlを閲覧させるけど、index.htmlを削除(無い状態に)してコンテナを作る
  3. index.htmlが存在する状態で直接index.htmlを閲覧させるコンテナを作り、その後index.htmlを削除する
  4. 直接index.htmlを閲覧、index.htmlも存在する状態だけどportsを8000:8000としてコンテナを作る

いずれもindex.htmlを直接参照なのでdocker-composeをappコンテナに影響のない形に作り変えます。

index.htmlはdocker-compose.ymlと同列に配置しました。

Docker
├─ docker-compose.yml
└─ index.html

直接index.htmlを閲覧するコンテナを作る

概要に書いた姿そのままでコンテナを作ります。

そうすると、8000ポートに index.htmlが表示されます。
この段階でわかる事はNGINXのコンテナ作成に問題が無いと言う事。
imageを使っているので問題が無いのは「当たり前」ですけどね。

index.htmlを削除してからコンテナを作る

docker-compose.ymlは実験1から変更せず、index.htmlを削除します。
これでコンテナを作成すると「IPで接続が拒否されました」とアナウンスされます。

フォルダ構成をみるとindex.htmlという空のディレクトリが作成されていました。
これは、docker-compose.yml内でvolumes に ./index.htmlと読み込ませていた為『存在しない⇒作成する』と流れたためです。
ちなみに、【sudo docker ps -a】でコンテナ状況を確認すると『STATUS Created』となっていました。
このステータスは「作成はされたけど一度も動いてないよ」と言う事です。
このステータスが出た場合、状況によってはですが『Exited(※一度動いて終了した)』より質が悪いかもしれません。

コンテナ作成後にindex.htmlを削除する

個人的にはこの結果が予想外でおもしろかったです。

1の実験の後、index.htmlファイルを削除してみました。
そうしたところ、存在しないのにindex.htmlのページが出現しました。
ブラウザのキャッシュかと思いキャッシュ削除しても同じ結果。

これはDockerの構築では勘違いの元になるかもしれません。
要注意です。

portsを8000:8000に変更してコンテナを作る

「IPで接続が拒否されました」とアナウンスされました。
nginx標準のconfigは80番がベースなので、configと違う8000を指定されてもわからないと言う事なのでしょう。

statusは『Exited』でした。

この実験から見える事

「コンテナを立ち上げたのにWEBサイトが表示されない」その時のメッセージが「IPで接続が拒否されました」の場合、ついついNginxの設定を見に行ってしまいます。

もちろん、例4の様に【Nginx.confの設定が原因】の場合もあると思います。
しかし、例2の様に【ファイルが存在しない】場合もある点にも注意が必要です。

Nginxのコンテナステータスが『Exited』の場合【表示すべきものが無い】事を意味している

これを知っている事が結構大切だったりします。

今回の反省点

私はコンテナのステータス確認を怠ったため、pythonコンテナが『Exited』にもかかわらずNGINXのコンフィグばかり弄ってました。表示すべきDjangoのページが止まってたら何やってもNginxは止まりますよね【表示すべきものが無い】わけですから。

そして、その根本原因はDjangoのプロジェクトを作っていないからという…。
勝手にNginxとPythonコンテナが出来ればファイルが無くてもNGINXのNOTFOUNDが出ると思い込んでたんですよね。

 表示すべきものが無い時。NGINXコンテナは終了する 

肝に銘じないとと思った次第です。

まとめ

確認作業と問題の場合分けは大切です。
プログラムって何かと【順番/手順】が色々と影響してきます。
「注意しないとなぁ」「思い込みはダメだなぁ」と改めて実感した事例でした。