Raspberry Pi 3 Model BでNginx+PostgreSQL+Django環境構築
どうも,筆者です.
前回,Docker のインストールを行った. workspacememory.hatenablog.com
今回は,Dockerfile と docker-compose.yml を使って Nginx+PostgreSQL +Django 環境を構築する. 参考1 参考2
構成
.
│ docker-compose.yml
│
├─django
│ Dockerfile
│ requirements.txt
│ uwsgi.ini
│
├─logs
│ access.log
│ error.log
│ uwsgi.log
│
├─nginx
│ │ Dockerfile
│ │
│ ├─cache
│ ├─conf
│ │ default.conf
│ │ nginx.conf
│ │ uwsgi_params
│ │
│ └─dockerApp
│ nginx
│ wakeup.sh
│
├─postgresql
│ Dockerfile
│
├─src
│ │ manage.py
│ │
│ └─membership_system
│ │ settings.py
│ │ urls.py
│ │ wsgi.py
│ │ __init__.py
│ │
│ └─__pycache__
│ settings.cpython-36.pyc
│ urls.cpython-36.pyc
│ __init__.cpython-36.pyc
│
└─static
└─admin
├─css
│ │ autocomplete.css
│ │ base.css
│ │ changelists.css
│ │ dashboard.css
│ │ fonts.css
│ │ forms.css
│ │ login.css
│ │ responsive.css
│ │ responsive_rtl.css
│ │ rtl.css
│ │ widgets.css
│ │
│ └─vendor
│ └─select2
│ LICENSE-SELECT2.md
│ select2.css
│ select2.min.css
│
├─fonts
│ LICENSE.txt
│ README.txt
│ Roboto-Bold-webfont.woff
│ Roboto-Light-webfont.woff
│ Roboto-Regular-webfont.woff
│
├─img
│ │ calendar-icons.svg
│ │ icon-addlink.svg
│ │ icon-alert.svg
│ │ icon-calendar.svg
│ │ icon-changelink.svg
│ │ icon-clock.svg
│ │ icon-deletelink.svg
│ │ icon-no.svg
│ │ icon-unknown-alt.svg
│ │ icon-unknown.svg
│ │ icon-yes.svg
│ │ inline-delete.svg
│ │ LICENSE
│ │ README.txt
│ │ search.svg
│ │ selector-icons.svg
│ │ sorting-icons.svg
│ │ tooltag-add.svg
│ │ tooltag-arrowright.svg
│ │
│ └─gis
│ move_vertex_off.svg
│ move_vertex_on.svg
│
└─js
│ actions.js
│ actions.min.js
│ autocomplete.js
│ calendar.js
│ cancel.js
│ change_form.js
│ collapse.js
│ collapse.min.js
│ core.js
│ inlines.js
│ inlines.min.js
│ jquery.init.js
│ popup_response.js
│ prepopulate.js
│ prepopulate.min.js
│ prepopulate_init.js
│ SelectBox.js
│ SelectFilter2.js
│ timeparse.js
│ urlify.js
│
├─admin
│ DateTimeShortcuts.js
│ RelatedObjectLookups.js
│
└─vendor
├─jquery
│ jquery.js
│ jquery.min.js
│ LICENSE-JQUERY.txt
│
├─select2
│ │ LICENSE-SELECT2.md
│ │ select2.full.js
│ │ select2.full.min.js
│ │
│ └─i18n
│ ar.js
│ az.js
│ bg.js
│ ca.js
│ cs.js
│ da.js
│ de.js
│ el.js
│ en.js
│ es.js
│ et.js
│ eu.js
│ fa.js
│ fi.js
│ fr.js
│ gl.js
│ he.js
│ hi.js
│ hr.js
│ hu.js
│ id.js
│ is.js
│ it.js
│ ja.js
│ km.js
│ ko.js
│ lt.js
│ lv.js
│ mk.js
│ ms.js
│ nb.js
│ nl.js
│ pl.js
│ pt-BR.js
│ pt.js
│ ro.js
│ ru.js
│ sk.js
│ sr-Cyrl.js
│ sr.js
│ sv.js
│ th.js
│ tr.js
│ uk.js
│ vi.js
│ zh-CN.js
│ zh-TW.js
│
└─xregexp
LICENSE-XREGEXP.txt
xregexp.js
xregexp.min.js
docker-compose.yml
docker-compose コマンドを実行する際に利用するdocker-compose.ymlファイルを以下に示す.
version: '3.4' volumes: # DBデータの永続化 postgresql.volume: name: postgresql.volume services: # nginxの設定 nginx: # ビルド対象 build: context: ./nginx # Dockerfile名 dockerfile: Dockerfile # イメージ名 image: custom_nginx # コンテナ名 container_name: nginx restart: always # 環境変数の設定 environment: TZ: Asia/Tokyo # ポートの設定(DockerfileのEXPOSEとそろえる) ports: - "18082:18082" # nginxのconfigファイル等の関連付け volumes: - ./nginx/conf/default.conf:/etc/nginx/conf.d/default.conf:ro - ./nginx/cache:/var/cache/nginx - ./logs/access.log:/var/log/nginx/access.log - ./logs/error.log:/var/log/nginx/error.log - ./static:/static:ro # 依存関係の記述 depends_on: - django # DBの設定 db: # ビルド対象 build: context: ./postgresql # Dockerfile名 dockerfile: Dockerfile # イメージ名 image: custom_postgres # コンテナ名 container_name: postgresql restart: always environment: POSTGRES_DB: djangodb POSTGRES_USER: postgres POSTGRES_PASSWORD: 1234 POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --locale=ja_JP.UTF-8" # ポートの設定(外部には公開しない) expose: - "5432" # 設定ファイルとデータ格納先の関連付け volumes: - postgresql.volume:/var/lib/postgresql/data # djangoの設定 django: # ビルド対象 build: context: ./django # Dockerfile名 dockerfile: Dockerfile # イメージ名 image: django_with_uwsgi # コンテナ名 container_name: django restart: always # 利用するアプリの関連付け volumes: - ./src:/code - ./static:/static:ro - ./logs/uwsgi.log:/var/log/uwsgi.log working_dir: /code # ポートの設定(外部には公開しない) expose: - "8081" # 依存関係の記述 depends_on: - db
Django の設定
ここでは,Django の設定内容について説明する.
Dockerfile
Django のイメージファイルを作成する際に利用する Dockerfile を以下に示す.
FROM resin/raspberry-pi-alpine:3.6 # Pythonで利用する環境変数の設定 # バイナリレイヤ下での標準出力とエラー出力を抑制 ENV PYTHONUNBUFFERED 1 # アプリケーション用のディレクトリの作成 RUN mkdir /code && mkdir /static # requirements.txtを追加 ADD requirements.txt /code/ # パッケージ群のインストール RUN apk update \ # タイムゾーンの設定 && apk add --no-cache bash tzdata pcre-dev \ && cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \ # PostgreSQL用のライブラリをインストール && apk add --no-cache postgresql-dev \ # 一時的に必要なパッケージをインストール && apk add --no-cache \ --virtual .build-temp shadow \ gcc libc-dev linux-headers \ musl-dev python3-dev libffi-dev libressl-dev \ # Python3をインストール && apk add --no-cache python3 \ # pip install && python3 -m ensurepip \ && rm -r /usr/lib/python*/ensurepip \ && pip3 install --upgrade pip setuptools \ # requirements.txtに記載されたライブラリ群をインストール && pip3 install -r /code/requirements.txt \ # シンボリックリンク && if [[ ! -e /usr/bin/python ]]; then ln -sf /usr/bin/python3 /usr/bin/python; fi \ # ユーザとグループの追加(Nginxと連動するため統一) && useradd -s /sbin/nologin -M -d /dev/null nginx \ # 一時的に必要だったパッケージを削除 && apk del .build-temp \ && rm -rf /root/.cache /var/cache/apk/* # uWSGIの設定ファイルをコピー COPY ./uwsgi.ini /uwsgi.ini # ログ出力先の設定 RUN echo -n > /var/log/uwsgi.log # 内部で利用するポートの設定 EXPOSE 8081 # コマンド実行 CMD ["uwsgi", "--ini", "/uwsgi.ini", "--logto", "/var/log/uwsgi.log"]
Django で利用する設定ファイル
Django の環境構築時に利用する設定ファイルを以下に示す.
requirements.txt
Django==2.0.7 uwsgi==2.0.17 psycopg2==2.8.2 psycopg2-binary==2.8.2 hashids==1.2.0 django-betterforms==1.2 django-bootstrap4==0.0.6 django-crispy-forms==1.7.2 django-filter==2.1.0 django-extra-views==0.11.0 django-widgets-improved==1.5.0
uwsgi.ini
[uwsgi] user = nginx uid = nginx gid = nginx chdir = /code module = membership_system.wsgi:application master = true enable-threads = true thunder-lock = true max-requests = 1000 processes = 1 threads = 2 vacuum = true socket = :8081 close-on-exec = true die-on-term = true
docker-compose の設定(対応箇所の抜粋)
対応する docker-compose の設定情報を以下に示す.今回は,8081 番のポートで待ち受ける.このポートは外部に公開しない.
# djangoの設定 django: # ビルド対象 build: context: ./django # Dockerfile名 dockerfile: Dockerfile # イメージ名 image: django_with_uwsgi # コンテナ名 container_name: django restart: always # 利用するアプリの関連付け volumes: - ./src:/code - ./static:/static:ro - ./logs/uwsgi.log:/var/log/uwsgi.log working_dir: /code # ポートの設定(外部には公開しない) expose: - "8081" # 依存関係の記述 depends_on: - db
PostgreSQL の設定
ここでは,PostgreSQL の設定内容について説明する. 参考
Dockerfile
Django のイメージファイルを作成する際に利用する Dockerfile を以下に示す.
FROM postgres:latest RUN localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8 ENV LANG ja_JP.UTF-8
docker-compose の設定(対応箇所の抜粋)
対応する docker-compose の設定情報を以下に示す.今回は,5432 番のポートで待ち受ける.このポートは外部に公開しない.
volumes: # DBデータの永続化 postgresql.volume: name: postgresql.volume
# DBの設定 db: # ビルド対象 build: context: ./postgresql # Dockerfile名 dockerfile: Dockerfile # イメージ名 image: custom_postgres # コンテナ名 container_name: postgresql restart: always environment: POSTGRES_DB: djangodb POSTGRES_USER: postgres POSTGRES_PASSWORD: 1234 POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --locale=ja_JP.UTF-8" # ポートの設定(外部には公開しない) expose: - "5432" # 設定ファイルとデータ格納先の関連付け volumes: - postgresql.volume:/var/lib/postgresql/data
また,ユーザ名とパスワードは以下のようにした.そのまま利用する際は,適宜変更すること.
| 項目 | 内容 |
|---|---|
| ユーザ名 | postgres |
| パスワード | 1234 |
Nginx の設定
ここでは,Nginx の設定内容について説明する.
Dockerfile
Nginx のイメージファイルを作成する際に利用する Dockerfile を以下に示す.
FROM resin/raspberry-pi-alpine:3.6 # Nginxのバージョン指定 ENV NGINX_VERSION 1.14.0 # Nginxのインストール RUN apk update \ && apk add --no-cache pcre-dev openssl-dev bash shadow tzdata \ && useradd -s /sbin/nologin -M -d /dev/null nginx \ && cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \ && apk add --no-cache --virtual build-dependencies build-base curl \ && curl -SLO http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \ && tar xzvf nginx-${NGINX_VERSION}.tar.gz \ && cd nginx-${NGINX_VERSION} \ && ./configure \ --user=nginx \ --group=nginx \ --with-http_ssl_module \ --with-http_realip_module \ --with-http_addition_module \ --with-http_sub_module \ --with-http_dav_module \ --with-http_flv_module \ --with-http_mp4_module \ --with-http_gunzip_module \ --with-http_gzip_static_module \ --with-http_random_index_module \ --with-http_secure_link_module \ --with-http_stub_status_module \ --with-http_auth_request_module \ --with-threads \ --with-stream \ --with-stream_ssl_module \ --with-http_slice_module \ --with-mail \ --with-mail_ssl_module \ --with-file-aio \ --with-http_v2_module \ --prefix=/usr/share/nginx \ --sbin-path=/usr/local/sbin/nginx \ --conf-path=/etc/nginx/nginx.conf \ --pid-path=/var/run/nginx.pid \ --http-log-path=/var/log/nginx/access.log \ --error-log-path=/var/log/nginx/error.log \ && make \ && make install \ && echo -n > /var/log/nginx/access.log \ && echo -n > /var/log/nginx/error.log \ && cd / \ && apk del build-dependencies shadow \ && rm -rf nginx-${NGINX_VERSION} nginx-${NGINX_VERSION}.tar.gz /var/cache/apk/* # static directory for django RUN mkdir /static # volumeの設定 VOLUME /var/cache/nginx # 設定の書き換え COPY ./conf/nginx.conf /etc/nginx/nginx.conf COPY ./conf/uwsgi_params /etc/nginx/uwsgi_params # 内部で利用するポートの設定 EXPOSE 18082 # 利用するシェルスクリプトをコンテナに配置 COPY ./dockerApp/wakeup.sh /wakeup.sh COPY ./dockerApp/nginx /etc/init.d/nginx RUN chmod a+x /wakeup.sh /etc/init.d/nginx # entrypoint: 何もしない ENTRYPOINT [""] # コマンド実行 CMD ["/wakeup.sh"]
また,利用する shell script を以下に示す.
nginx
#!/bin/bash set -e PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DESC="nginx daemon" NAME=nginx DAEMON=/usr/local/sbin/${NAME} SCRIPTNAME=/etc/init.d/${NAME} # if daemon file not found, exit script. test -x ${DAEMON} || exit 0 d_start() { ${DAEMON} || echo -n " already running" } d_stop() { ${DAEMON} -s quit || echo -n " not running" } d_reload() { ${DAEMON} -s reload || echo -n " could not reload" } case "$1" in start) echo -n "Starting ${DESC}: ${NAME}" d_start sleep 3 echo "." ;; stop) echo -n "Stopping ${DESC}: ${NAME}" d_stop sleep 3 echo "." ;; reload) echo -n "Reloading ${DESC}: configuration..." d_reload sleep 3 echo "reloaded." ;; restart) echo -n "Restarting ${DESC}: ${NAME}" d_stop sleep 5 d_start echo "." ;; *) echo "Usage: ${SCRIPTNAME} {start|stop|restart|reload}" >&2 exit 3 ;; esac exit 0
wakeup.sh
#!/bin/bash # Nginx start /etc/init.d/nginx start # hook SIGTERM trap_TERM() { echo SIGTERM ACCEPTED. exit 0 } trap 'trap_TERM' TERM # loop while : do sleep 5 done
uWSGI の設定ファイル
Nginx で受けたリクエストを Django に投げる際の uWSGI の設定ファイルを以下に示す.
uwsgi_params
uwsgi_param QUERY_STRING $query_string; uwsgi_param REQUEST_METHOD $request_method; uwsgi_param CONTENT_TYPE $content_type; uwsgi_param CONTENT_LENGTH $content_length; uwsgi_param REQUEST_URI $request_uri; uwsgi_param PATH_INFO $document_uri; uwsgi_param DOCUMENT_ROOT $document_root; uwsgi_param SERVER_PROTOCOL $server_protocol; uwsgi_param REQUEST_SCHEME $scheme; uwsgi_param HTTPS $https if_not_empty; uwsgi_param REMOTE_ADDR $remote_addr; uwsgi_param REMOTE_PORT $remote_port; uwsgi_param SERVER_PORT $server_port; uwsgi_param SERVER_NAME $server_name;
Nginx の設定ファイル
Nginx のコンフィグファイルを以下に示す.
nginx.conf
# user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; server_names_hash_bucket_size 64; sendfile on; keepalive_timeout 65; include /etc/nginx/conf.d/*.conf; }
default.conf
# the upstream component nginx needs to connect to upstream call_django { ip_hash; server django:8081; } # configuration of the server server { listen 18082; server_name _; server_tokens off; charset utf-8; access_log /var/log/nginx/access.log combined; error_log /var/log/nginx/error.log error; # max upload size client_max_body_size 64M; # adjust to taste location /static { alias /static; } # Finally, send all non-media requests to the Django server. location / { # avoid requests that are neither GET nor POST if ( $request_method !~ ^(GET|POST)$ ) { return 444; } # setting include /etc/nginx/uwsgi_params; # the uwsgi_params file you installed uwsgi_pass call_django; } }
docker-compose の設定(対応箇所の抜粋)
対応する docker-compose の設定情報を以下に示す.今回は,18082 番のポートで待ち受ける.
nginx: # ビルド対象 build: context: ./nginx # Dockerfile名 dockerfile: Dockerfile # イメージ名 image: custom_nginx # コンテナ名 container_name: nginx restart: always # 環境変数の設定 environment: TZ: Asia/Tokyo # ポートの設定(DockerfileのEXPOSEとそろえる) ports: - "18082:18082" # nginxのconfigファイル等の関連付け volumes: - ./nginx/conf/default.conf:/etc/nginx/conf.d/default.conf:ro - ./nginx/cache:/var/cache/nginx - ./logs/access.log:/var/log/nginx/access.log - ./logs/error.log:/var/log/nginx/error.log - ./static:/static:ro # 依存関係の記述 depends_on: - django
Docker Image 作成
Docker Image 作成のため,下記を実行する.
docker-compose build
log ファイルの作成
実行ログを記録するための log ファイルを作成する.
touch logs/uwsgi.log logs/access.log logs/error.log
Django のプロジェクトを作成
Django のプロジェクトを作成するため,下記のコマンドを実行する. 参考
# コンテナの作成 docker-compose up -d # django のコンテナに入る docker exec -it django bash # プロジェクトの作成 django-admin startproject membership_system . # コンテナから抜ける exit # 所有者の変更 sudo chown pi:pi -R src/
Django の設定
setting.py の編集
setting.py を修正する.
修正前
ALLOWED_HOSTS = [] # Database # https://docs.djangoproject.com/en/2.0/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } }
修正後
ALLOWED_HOSTS = ['localhost'] # Database # https://docs.djangoproject.com/en/2.0/ref/settings/#databases # 修正 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'djangodb', 'USER': 'postgres', 'PASSWORD': '1234', 'HOST': 'db', 'PORT': 5432, } }
マイグレーションの実行
下記のコマンドを実行する.
docker exec -it django bash # コンテナ内で作業 ./manage.py makemigrations ./manage.py migrate ./manage.py createsuperuser # いい感じに設定する #Username (leave blank to use 'root'): admin #Email address: admin@localhost #Password: #Password (again): # コンテナから抜ける exit
ページに接続する
ブラウザを開いて下記を入力する.「The install worked successfully! Congratulations!」が表示されれば成功.
http://(ホスト名orIPアドレス):18082
その他設定
タイムゾーンや言語,静的ファイルの設定を行う.
変更前
# Internationalization # https://docs.djangoproject.com/en/2.0/topics/i18n/ LANGUAGE_CODE = 'en_US' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/2.0/howto/static-files/ STATIC_URL = '/static/'
変更後
# Internationalization
# https://docs.djangoproject.com/en/2.0/topics/i18n/
LANGUAGE_CODE = 'ja-JP'
TIME_ZONE = 'Asia/Tokyo'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = '/static'
# static フォルダの読み込み専用を取り外す volumes: - ./src:/code # - ./static:/static:ro - ./static:/static - ./logs/uwsgi.log:/var/log/uwsgi.log working_dir: /code # コンテナの作り直し docker rm -f $(docker ps -aq) # コンテナの作成 docker-compose up -d docker exec -it django bash # コンテナ内で作業 ./manage.py collectstatic # コンテナから抜ける exit