LoginSignup
4
1

More than 5 years have passed since last update.

NGINX Unit+Django(WSGI) Dockerコンテナ構築

Last updated at Posted at 2019-02-18

DjangoをNGINX/Unitで公開するためのDockerコンテナを作成します。

内容

  • 前記事Windows10+WSL+Docker環境を構築
  • NGINX/Unit+Djangoのコンテナを構築

カスタマイズ

NGINX/Unitとは?

公式サイトに記載の通り、(誤解を恐れず表現すると)NGINXの動的アプリサーバ版です。
WSGIに沿ってPythonスクリプトを記述することで、動的アプリを公開できます。

  • WSGIに準拠したスクリプトを直接起動できる (中間モジュールを必要としない)
  • 設定更新を動的に実施できる(ソケットに流し込む)

Djangoとは?

DjangoはPythonの代表的フルスタックフレームワークです。

用意するもの

名称 内容
Docker Dokerfile Dockerイメージのレシピ
unit.conf.json NGINX Unitの設定
entrypoint.sh コンテナ起動スクリプト
requirements.pip pip freezeの出力
.docerignore 参考サイト
コンテンツ Pythonスクリプト Djangoで作成

src/
├── Dockerfile
├── .dockerignore
├── unit.conf.json
├── entrypoint.sh
├── requirements.pip
└── xxx/ (Django)
   ├── xxx
   |   ├── wsgi.py
   |   └── etc...
   └── polls

※DjangoははじめてのDjangoあたりを参考に学習してください。
※ディレクトリツリーキレイに書きたい

Dokerfile

公式イメージDockerfileを参考にしつつ作成します。
公式はDebianでPythonバージョンも古いため、UbuntuイメージにNGINX/Unitを導入する形にします。
ENVにユーザーとパスワードを記述している点が気になる方は、適宜ARGに置き換えてください。

FROM ubuntu:cosmic
ENV UBUNTU_VER cosmic
ENV PY_VER 3.6

SHELL ["/bin/bash", "-c"]
ENV DEBCONF_NOWARNINGS yes

LABEL MAINTAINER="auther"
LABEL version="1.0"
LABEL description=""

ENV CONTENTS ./project
ENV EXPOSE_PORT 8000

ENV USER api
ENV PASSWORD pass
ENV HOME /home/${USER}
ENV PROJECT_NAME xxx
ENV PROJECT_DIR ${HOME}/${PROJECT_NAME}

# initialize
RUN : "locale setting and base package" && \
    set -o pipefail && \
    perl -p -i.bak -e 's%https?://(?!security)[^ \t]+%http://ubuntutym.u-toyama.ac.jp/ubuntu/%g' /etc/apt/sources.list && \
    apt-get -y clean && apt-get -y update && \
    apt-get -qy install \
    sudo \
    tzdata \
    ca-certificates \
    gnupg \
    curl && \
    update-locale LANG=ja_JP.UTF-8 && \
    ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    : "create user" && \
    useradd -m -s /bin/bash ${USER} && \
    gpasswd -a ${USER} sudo && \
    echo "${USER}:${PASSWORD}" | chpasswd && \
    echo "Defaults visiblepw" >> /etc/sudoers && \
    echo "${USER} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

# copy project
WORKDIR ${HOME}

COPY ${CONTENTS} ${HOME}/${PROJECT_NAME}
COPY unit.conf.json ${HOME}
COPY entrypoint.sh ${HOME}
COPY requirements.pip ${HOME}

RUN set -o pipefail && \
    sed \
        -e "s#%%HOME%%#$HOME#g" \
        -e "s#%%PJ%%#$PROJECT_NAME#g" \
        -e "s#%%PORT%%#$EXPOSE_PORT#g" \
        -e "s#%%PYVER%%#$PY_VER#g" \
        ${HOME}/unit.conf.json > ${HOME}/unit-conf.json && \
    chown -R ${USER}:${USER} ${PROJECT_DIR} && \
    chown ${USER}:${USER} ${HOME}/unit.conf.json && \
    chown ${USER}:${USER} ${HOME}/entrypoint.sh && \
    chown ${USER}:${USER} ${HOME}/requirements.pip && \
    ln -sf /dev/stdout ${HOME}/unit.log && \
    chmod 774 ${HOME}/entrypoint.sh

# install Project Package
WORKDIR /root
RUN set -o pipefail && \
    : "nginx unit repogitory" && \
    curl -fsSL "https://nginx.org/keys/nginx_signing.key" | apt-key add - && \
    echo "deb https://packages.nginx.org/unit/ubuntu/ ${UBUNTU_VER} unit" > /root/unit.list && \
    echo "deb-src https://packages.nginx.org/unit/ubuntu/ ${UBUNTU_VER} unit" >> /root/unit.list && \
    cp /root/unit.list /etc/apt/sources.list.d/unit.list && \
    : "project packages" && \
    apt-get -y update && apt-get -qy install \
    unit \
    unit-python${PY_VER} \
    python3 \
    python3-pip

# pip
USER ${USER}
WORKDIR ${HOME}
RUN pip3 install -r ${HOME}/requirements.pip

# start unitd
STOPSIGNAL SIGTERM
EXPOSE ${EXPOSE_PORT}

CMD ["sh", "./entrypoint.sh"]

unit.conf.json

公式ドキュメントを参考にNGINX/Unitの設定を記述したjson形式のファイルを用意します。
"%%"で囲んでいる箇所はdockerfile内で置換しています。

{
  "listeners": {
    "*:%%PORT%%": {
      "application": "%%PJ%%"
    }
  },  
  "applications": {
    "%%PJ%%": {
      "type": "python %%PYVER%%",
      "processes": 5,
      "working_directory": "%%HOME%%/%%PJ%%/",
      "path": "%%HOME%%/%%PJ%%/",
      "module": "%%PJ%%.wsgi",
      "user": "api",
      "group": "api",
      "limits": {
          "timeout": 10,
          "requests": 1000
      }
    }
  },
  "settings": {
      "http": {
          "header_read_timeout": 10,
          "body_read_timeout": 10,
          "send_timeout": 10,
          "idle_timeout": 120,
          "max_body_size": 6291456
      }
  },
  "access_log": "%%HOME%%/access.log"
}

entrypoint.sh

コンテナ生成後に実行するシェルスクリプトです。Dockerfile末尾で実行しています。
NGINX Unitを実行する方法は他にもありますが、今回はシンプルに実行します。

#!/bin/sh

sudo unitd --control unix:./control.unit.sock --log ./unit.log
sudo curl -fsSL -X PUT -d @./unit-conf.json --unix-socket ./control.unit.sock "http://localhost/config/"
sudo tail -f ./access.log

おまけ: requirements.pip

Django==2.1.5
pytz==2018.9

ビルドとコンテナ起動

コンテナイメージのビルドをおこない、起動します。
curl等で疎通確認をおこないます。

$ docker build --no-cache ./ -t proj/api
$ docker run -d --name api -p 8080:8000 proj/api
$ curl http://localhost:8080/polls/

次の記事

ベースイメージ 用途
NGINX Unit APIサーバ
mysql MySQLサーバ ←ココ
redis Redisサーバ
まとめる docker compose
  • 上記イメージをDockerfileを記述してビルド
  • Docker Composeで取りまとめる
4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1