記事の概要
Djangoで作成したWEBアプリケーションを開発・本番環境で動作させる際はいくつかの方法があります。
最近では、Kubernetesが人気となりアプリケーションをコンテナ化する場面も多いです。
本記事では開発・本番環境でどのようにDjangoアプリケーションをのせたDockerコンテナを作るかについて記載します。
前提条件・環境
本記事で使用する環境はCentOS7、Docker、Django2系です。
Dockerさえ動けばDockerコンテナは動くため、OSがWindowsでも問題ありません。
開発環境用Dockerコンテナ作成
使用するDockerファイル
開発環境用に使用するDockerファイルは以下になります。
このDockerファイルではdebian:10をベースにして、Pythonをソースコードからインストールしています。
公式PythonのDockerイメージもあるためそちらを使っても問題ないのですが、勉強のためにこのような構成になっています。
FROM debian:10
# Install Python3.7.7
WORKDIR /work
ADD ./Python-3.7.7.tar.xz .
WORKDIR Python-3.7.7
RUN apt-get update && apt-get install -y \
gcc \
libbz2-dev \
libssl-dev \
libffi-dev \
libsqlite3-dev \
make \
tk-dev \
zlib1g-dev \
apache2-dev \
python3-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN ./configure --enable-shared && \
make && \
make install && \
make distclean && \
./configure && \
make && \
make altbininstall
# Install with pip
COPY ./requirements.txt .
RUN pip3 install --upgrade pip setuptools
RUN pip3 install --upgrade wheel
RUN pip3 install -r requirements.txt
# Deploy App
WORKDIR /
ADD ./deployfiles.tar.xz .
WORKDIR /myapp
CMD ["python3", "manage.py", "runserver", "0.0.0.0:80"]
Dockerファイルの説明
FROM debian:10
まず、Dockerファイルを記載するときはベースとして何を使うか指定します。ここではdebian:10を指定しています。
# Install Python3.7.7
WORKDIR /work
ADD ./Python-3.7.7.tar.xz .
WORKDIR Python-3.7.7
次にPythonのインストールです。
WORKDIRはOSのカレントディレクトリを移動させるような構文です。WORKDIR /workとすればルートディレクトリ(/)直下にworkというディレクトリが作られ(指定したディレクトリがなければ作られます)、そこがカレントディレクトリとなります。
ADDはADD ホストOS上のパス Dockerコンテナ上のパスとすることで指定したホストOS上にあるファイルをDockerコンテナ上のパスへコピー・展開することができます。
ADDはCOPYと異なり、圧縮されたファイルを展開することができます。そのためtarやxzなどのファイルはADDを使ってDockerコンテナ上へコピーすると良いと思います。
RUN apt-get update && apt-get install -y \
gcc \
libbz2-dev \
libssl-dev \
libffi-dev \
libsqlite3-dev \
make \
tk-dev \
zlib1g-dev \
apache2-dev \
python3-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
**RUN**はDockerコンテナ上でコマンドを実行することが出来ます。apt-getを使用し、Pythonのインストールに必要な依存パッケージをインストールしています。
apt-get clean、rm -rf /var/lib/apt/lists/*は不必要なキャッシュやファイルを削除するために実行しています。これを削除することで、作成されるDockerイメージの容量を小さく保てます。
RUN ./configure --enable-shared && \
make && \
make install && \
make distclean && \
./configure && \
make && \
make altbininstall
後は**./configure**、make、make installです。4行ほど余分なものがありますが、これはエラー対応のためにつけています。
※何らかの組み合わせの問題だとは思うのですが、私が実行したときはこのようにしなければなりませんでした。もしかすると不要かもしれません。
# Install with pip
COPY ./requirements.txt .
RUN pip3 install --upgrade pip setuptools
RUN pip3 install --upgrade wheel
RUN pip3 install -r requirements.txt
Pythonのインストールが終わったら、Pythonパッケージのインストールを行います。ここではpipコマンドを使用してrequirements.txtに記載されているパッケージをインストールします。
**COPYはADD**と似ていて、COPY ホストOS上のパス Dockerコンテナ上のパスとすることでホストOS上にあるファイルをDockerコンテナ上のパスへコピーできます。こちらは文字通りコピーしかしません。
後は**RUNでpipのアップグレードを行い、requirements.txtに基づいてPython**パッケージをインストールします。
# Deploy App
WORKDIR /
ADD ./deployfiles.tar.xz .
WORKDIR /myapp
CMD ["python3", "manage.py", "runserver", "0.0.0.0:80"]
最後に自分が作ったアプリケーションをDockerコンテナへ加えます。
deployfiles.tar.xzはmyappというディレクトリを圧縮したもので、myapp直下にmanage.pyがあります。
CMDはDockerコンテナが起動するときに実行するコマンドを設定する構文です。これはPythonのリスト形式のように記載でき、各要素は半角スペースで結合されます。つまり、以下のようなコマンドになります。
CMD ["python3", "manage.py", "runserver", "0.0.0.0:80"]
↓
python3 manage.py runserver 0.0.0.0:80
Dockerイメージのビルド
Dockerイメージをビルドするには以下のコマンドを実行します。
docker build -t test/myapp .
-tオプションはDockerイメージへタグを付けるために使用します。タグを付ければ管理がしやすくなります。
コマンドの最後にはDockerファイルのパスを入れます。ここでは**カレントディレクトリ(.)**を指定しています。
デフォルトではDockerfileという名前のファイルを指定されたパスから探すため、上記で作成したファイル名はDockerfileとしておきます。
作成したイメージを確認するには以下のコマンドを実行します。
docker image ls
Dockerコンテナの起動
DockerイメージからDockerコンテナを起動するには以下のコマンドを実行します。
docker run --name myapp -d -p 80:80 -v /work/db.sqlite3:/myapp/db.sqlite3 test/myapp:latest
--nameオプションはDockerコンテナへ名前をつけます。これは後でこのDockerコンテナを停止、起動、削除したくなったりしたときに便利です。名前は一意なものになるため、名前をつけておけば名前を指定するだけで停止、起動、削除が出来ます。名前がない場合はコンテナIDを指定します。
-dオプションはバックグラウンドでコンテナを実行します。これをつけなかった場合は、Dockerコンテナの標準出力がコンソール上に表示されます。Ctrl + cで抜けられます。ほとんどの場合はバックグラウンドで動かすと思うのでつけておきます。
-pオプションはホストOSのポートとDockerコンテナのポートを紐付けます。ホストOSのポート:Dockerコンテナのポートとします。今回はDjangoのプロセスをDockerコンテナの80番ポートを使用して公開しているため80を指定します。
-vオプションはホストOSのボリューム(DockerボリュームまたはホストOS上のファイルパス)とDockerコンテナのファイルパスを紐付けます。コンテナは終了したときにデータを保持しません。そのため、残しておきたいデータは外部に保管する必要があります。推奨はDockerボリュームですが開発環境のためホスト上OSのファイルパスへデータを保存させます。ここではdb.sqlite3をホストOSからDockerコンテナへ紐付けています。
test/myappは元になるDockerイメージの指定です。latestというのはバージョン名でDockerイメージをビルドしたときに何も指定しなければlatestになります。docker image lsで出力されるTAG列を参照することで確認できます。
正常に起動されているかどうかを確認するには以下のコマンドを実行します。
docker ps
STATUS列がUPになっていれば正常に起動しています。
何も出力されない場合は**-aをつけて停止中のプロセスも確認します。もしDockerコンテナ**のログを確認したい場合は以下のコマンドを実行します。
docker logs [コンテナ名またはコンテナID]
エラーを確認して対応します。
Djangoアプリケーションへの接続
Dockerを起動しているホストOS上のIPアドレスの公開したポート番号へアクセスします。
本番環境用Dockerコンテナ作成
使用するDockerファイル
本番環境用に使用するDockerファイルは以下になります。
開発環境と違い、python3 manage.py runserverでプロセスを立ち上げるわけにはいきません。Apacheなどの上で動作させるほうが安定します。
ここではベースとしてhttpd:2.4を使用しています。Apache Web サーバの公式Dockerイメージです。
ApacheでDjangoを実行するためには**mod_wsgiというモジュールをApacheへ組み込む必要があります。そのためPython**、**mod_wsgi**をインストールしています。
FROM httpd:2.4
# Install Python3.7.7
WORKDIR /work
ADD ./Python-3.7.7.tar.xz .
WORKDIR Python-3.7.7
RUN apt-get update && apt-get install -y \
gcc \
libbz2-dev \
libssl-dev \
libffi-dev \
libsqlite3-dev \
make \
tk-dev \
zlib1g-dev \
apache2-dev \
python3-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN ./configure --enable-shared && \
make && \
make install && \
make distclean && \
./configure && \
make && \
make altbininstall
# Install with pip
COPY ./requirements.txt .
RUN pip3 install --upgrade pip setuptools
RUN pip3 install --upgrade wheel
RUN pip3 install -r requirements.txt
# install ModWsgi
WORKDIR /work
ADD ./mod_wsgi-4.7.1.tar.gz .
WORKDIR mod_wsgi-4.7.1
RUN ./configure \
--with-apxs=/usr/local/apache2/bin/apxs \
--with-python=/usr/local/bin/python3.7 && \
make && \
make install
# Set Apache
WORKDIR /usr/local/apache2/conf
COPY ./httpd.conf .
COPY ./server.crt .
COPY ./server.key .
COPY ./wsgi.conf ./extra
COPY ./httpd-ssl.conf ./extra
Dockerファイルの説明
FROM httpd:2.4
ベースとして**httpd:2.4**を指定しています。
# Install Python3.7.7
WORKDIR /work
ADD ./Python-3.7.7.tar.xz .
WORKDIR Python-3.7.7
RUN apt-get update && apt-get install -y \
gcc \
libbz2-dev \
libssl-dev \
libffi-dev \
libsqlite3-dev \
make \
tk-dev \
zlib1g-dev \
apache2-dev \
python3-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN ./configure --enable-shared && \
make && \
make install && \
make distclean && \
./configure && \
make && \
make altbininstall
開発環境と同様にPythonをインストールします。
# Install with pip
COPY ./requirements.txt .
RUN pip3 install --upgrade pip setuptools
RUN pip3 install --upgrade wheel
RUN pip3 install -r requirements.txt
開発環境と同様にpipでrequirements.txtに基づいたPythonパッケージをインストールします。
# install ModWsgi
WORKDIR /work
ADD ./mod_wsgi-4.7.1.tar.gz .
WORKDIR mod_wsgi-4.7.1
RUN ./configure \
--with-apxs=/usr/local/apache2/bin/apxs \
--with-python=/usr/local/bin/python3.7 && \
make && \
make install
ApacheでDjangoを動作させるために**mod_wsgi**をインストールします。
# Set Apache
WORKDIR /usr/local/apache2/conf
COPY ./httpd.conf .
COPY ./server.crt .
COPY ./server.key .
COPY ./wsgi.conf ./extra
COPY ./httpd-ssl.conf ./extra
最後にApacheの各種configファイル、証明書関連ファイルをコピーします。
Dockerイメージのビルド
開発環境と同様です。
Dockerボリュームの作成
**Dockerボリューム**を作成するには以下のコマンドを実行します。
docker volume create --name volume-name
--nameで指定した名前で**Dockerボリュームが作成されます。このボリュームはDockerコンテナ**と紐付けます。
Dockerボリュームの寿命はDockerコンテナと異なります。Dockerコンテナがなくなっても**Dockerボリューム**は存在し続けるため、データを永続化できます。
Dockerコンテナの起動
DockerイメージからDockerコンテナを起動するには以下のコマンドを実行します。
docker run --name myapp -d -p 443:443 -v volume-name:/myapp test/myapp
-vオプションだけ開発環境とは異なります。ここではホストOS上のファイルパスではなく、Dockerボリュームを指定しています。volume-nameという名前のDockerボリュームがDockerコンテナ上の**/myappと紐付きます。これで/myapp上にあるデータがDockerボリューム**へ保存されます。
Djangoアプリケーションへの接続
開発環境と同様です。