やってみたこと
- djangoチュートリアルで制作したpolls appを、dockerで立ち上げてみようとふと思ったのでやってみました。
- pollsアプリは、
python3 manage.py runserver 8000
によって、localhost:8000
で起動します。それをdockerコンテナからやってみようという話です。
- pollsアプリは、
前提
- 今回は敢えて、
Dockerfile
とdocker-compose.yml
の両方を最低限レベルで使ってdjangoのアプリケーションを構築します。これらのファイルを使った方が、今後汎用的に覚えられる(いじってみれる)だろうという期待も込めて(笑) - dockerコンテナの中から
python manage.py runserver
で開発サーバを起動してみる、という実験をします。実際にはおそらくあまりこんな使い道はないのでは、、、その辺はお気にせずお読みください笑- 開発用サーバーは、Django付属のWebサーバーです。開発中に便利なツールであって、運用環境では使用しないことが推奨されています。
- djangoチュートリアルでpollsアプリケーションを制作したmysiteプロジェクトを、以下ディレクトリ構造で配置。
.
├── docker
│ ├── docker-compose.yml
│ └── Dockerfile
└── web
├── mysite
│ ├── mysite
│ ├── polls
│ ├── db.sqlite3
│ └── manage.py
└── requirements.txt
-
mysiteとpollsディレクトリ以下は、チュートリアルにも詳細な記載があります。何がどう関係してくるのか把握したい方はぜひ。
-
チュートリアル作成における記事はこちら:
手順
- docker関連ファイルの準備
- イメージ作成・コンテナ起動
- コンテナの中に入って
manage.py
を確認 - Dockerコンテナから開発サーバを起動
docker関連ファイルの準備
- まずは
Dockerfile
に以下のように記載します。
# python:3.8の公式 image をベースの image として設定
FROM python:3.8
# 作業ディレクトリの作成
RUN mkdir /mysite
# 作業ディレクトリの設定(以後の RUN は WORKDIR で実行)
WORKDIR /mysite
# カレントディレクトリにある資産をコンテナ上の指定のディレクトリにコピーする
ADD web /mysite
# pipでrequirements.txtに指定されているパッケージを追加する
RUN pip install -r requirements.txt
# 起動(今回はなし)
# CMD python3 manage.py runserver 0.0.0.0:8000
- 今回はpython3.8のイメージをベースとしています。マイナーバージョンを指定しないとビルド時点の最新python stable versionがインストールされます。
- ちなみに、何も指定しないと以下のエラーが出てきます。
failed to solve: rpc error: code = Unknown desc = failed to solve with frontend dockerfile.v0: failed to create LLB definition: no build stage in current context
-
requirements.txt
には以下のように記載します。ビルド時にインストールしたいライブラリ(python package)を記述します。- こちらもdjangoアプリで使う必要最低限のものだけ記述します。
Django==4.1
requests
- そして
docker-compose.yml
には以下のように記載します。- 今回は必要最低限のものしか記載していません。
version: '3'
services:
mysite:
build:
context: ../
dockerfile: ./docker/Dockerfile # Dockerfileのディレクトリを指定します
volumes:
- '../web:/mysite'
ports:
- "8000:8000" # 左側が外部からのアクセス時のポート番号:右側がdockerコンテナからアクセスする時のポート番号。ホストの8000番からコンテナの8000番へポートフォワードしています
container_name: docker_mysite
tty: true # ポート待受とかしていないコンテナの場合、trueに設定しておくとコンテナが起動し続けます
working_dir: '/mysite'
イメージ作成・コンテナ起動
- 以下のコマンドでイメージ作成&コンテナ起動します。
$ docker compose up -d
-
-d
オプションはデーモンモードで起動し、プロセスをバックグラウンドで動作させることができます。- アクセスログの内容やエラーなどを確認したい場合は、
-d
を外して実行します。
- アクセスログの内容やエラーなどを確認したい場合は、
- 起動しているコンテナを以下のコマンドで確認できます。UPなので起動していますね。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7f730b3c105f docker-mysite "python3" About a minute ago Up About a minute 0.0.0.0:8000->8000/tcp docker_mysite
-
docker-compose.yml
で指定した8000ポートにつながっていることがわかります。 -
$ docker compose ps
でもコンテナがRUNNINGかどうか分かります。 - また、以下のコマンドにより、
requirement.txt
に記述したモジュールがインストールされているかどうか確認できます。
$ docker exec -it docker_mysite pip list
Package Version
------------------ ---------
asgiref 3.6.0
backports.zoneinfo 0.2.1
certifi 2022.12.7
charset-normalizer 3.1.0
Django 4.1
idna 3.4
pip 22.0.4
requests 2.28.2
setuptools 57.5.0
sqlparse 0.4.3
urllib3 1.26.14
wheel 0.38.4
コンテナの中に入ってmanage.py
を確認
- 以下のコマンドで
docker_mysite
コンテナに入ります。
$ docker exec -it docker_mysite bash
- CONTAINER IDでも入れるので、以下のコマンドでもOKです。
$ docker exec -it 7f730b3c105f bash
- まだコンテナが立ち上がっていない場合は、以下が返ってきます。その場合は、
docker compose up -d
を行いましょう。
Error response from daemon: Container xxxxxxxx is not running
- また、そもそもコンテナが存在していない時は、以下のメッセージが返ってきます。こちらの場合も、
docker-compose.yml
があるところでdocker compose up -d
を行いましょう。
Error: No such container: xxxxxxxx
- コンテナの中に入れたら、以下のようなプロンプトが出てきます。
root@7f730b3c105f:/mysite#
-
ls -a
で直下を確認します。ローカル環境で作成したディレクトリがCOPYされていることがわかります。
root@7f730b3c105f:/mysite# ls -a
. .. .DS_Store mysite requirements.txt
-
manage.py
があるディレクトリに移動します。
$ cd mysite
- ここで
ls -a
をすれば同じくローカルと同様の状況が確認できるはずです。
Dockerコンテナから開発サーバを起動
- 以下のコマンド実施により、8000ポートで立ち上げることができます。
root@7f730b3c105f:/mysite# cd mysite
root@7f730b3c105f:/mysite/mysite# python3 manage.py runserver 0:8000
- ポイントは
0
です。以下の参考記事に記載がありますが、0を指定することにより、ホスト側からlocalhost:8000
でアクセスが可能になります。0.0.0.0
でも同じです。 - ローカル環境から普通に開発サーバを起動する場合、
python manage.py runserver
コマンドで可能ですので、例えば8000ポートで開きたい場合はpython3 manage.py runserver 8000
とすれば以下のように出力されて開発サーバーが立ち上がると思います。
Django version 4.1.3, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
[09/Mar/2023 08:51:01] "GET / HTTP/1.1" 200 145
- ただしdockerコンテナでDjangoの開発サーバーを起動する場合は、ホスト側からアクセスする必要があるので、
0:8000
のようになります。 - また、当然ですが、
docker-compose.yml
で指定したポートでコンテナが立ち上がるので、python3 manage.py runserver 0:8000
の8000を8001とかにしてアクセスしてもつながりません。逆に、docker-compose.yml
で8001を指定していれば、python3 manage.py runserver 0:8001
としてあげる必要があります(コンテナが起動している場合は一度downして、書き換えてからupします)。 - ということで、
python3 manage.py runserver 0:8000
を実行すると以下のように返ってきます。HTTPステータスコードも200なので正常です。
Django version 4.1, using settings 'mysite.settings'
Starting development server at http://0:8000/
Quit the server with CONTROL-C.
[09/Mar/2023 08:55:32] "GET / HTTP/1.1" 200 145
-
dockerコンテナが起動してある状態で
http://localhost:8000/
にアクセスすると無事に繋がったことがわかります。
-
「dockerからじゃなくて、普通にローカルでいじれば良いのでは?w」って感じですが、ふと「これってできるのかな?」と思ったのでやってみました(笑)。せっかく作ったので、これを色々いじってみる実験もしてみます。