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