WebARENAロゴ

WebARENAの使い方 – (アプリケーション構築 django)

前回の記事で、WebArenaのDocker上にnginxでリバースプロキシを構築しました。今回は、そのバックエンドにDjangoのWEBアプリケーションを構築します。

リバースプロキシ側のconfファイルは、追加するアプリケーションに合わせて、追加する必要があります。

また、事前にアプリケーション用のサブドメインも取得が必要です。今回は「https://fx.xxxxx.com」のサブドメインでアクセスできることを目指して、環境を構築していきます。

WebARENA(VPSクラウド)

全体像

リバースプロキシ側のconfファイル

リバースプロキシ側のconfフォルダに、fx.conf(今回のサブドメイン用の設定)を追加します。

dc-proxy
│  docker-compose.yml
│
└─proxy
    │  Dockerfile
    │
    ├─etc
    │  └─nginx
    │      └─conf
    │              default.conf
    │              fx.conf      ←追加★
    └─html
            index.html

ファイルの中身な以下となります。ここで記載した値は、追加アプリケーション側のnginxのdefault.confと合わせる必要があります(後述)。

server{

    listen 443 default_server ssl;
    server_name fx.xxxxx.com;

    ssl on;
    ssl_certificate     /etc/letsencrypt/live/dc.xxxxx.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/dc.xxxxx.com/privkey.pem;

    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    location / {
        proxy_pass   http://fx:8000;
    }

    location ^~ /.well-known/acme-challenge/ {
        allow all;
        root /var/www/html;
        try_files $uri =404;
    }

}

ポイント

  • server_nameは、外からリクエストされるサブドメイン名を記載する。当然、お名前.comなどでに登録し、名前解決できるようにしておく。
  • location / は、追加アプリケーションのnginxの待ち受け口に合わせる。http://までは固定値で、その後が「コンテナ名+ポート番号」になる。コンテナ名もポート番号も、docker-compose.ymlに記載。

追加アプリケーション(Django)の構成

フォルダ構成

フォルダ構成をいかに記載します。

django-posgres
 │  docker-compose.yml ・・・(a)
 │  Dockerfile       ・・・(b) 
 │  manage.py 
 │  requirements.txt   ・・・(c) 
 │          
 ├─config
 ├─djangofx
 │     django.ini    ・・・(d) 
 │     settings.py   ・・・(e) 
 │     urls.py
 │     uwsgi.log     ・・・(f)  
 │     wsgi.py
 │          
 ├─nginx
 │  │  default.conf    ・・・(g)   
 │  │  Dockerfile      ・・・(h)  
 │  │  uwsgi_params     ・・・(i)   
 │  │  
 │  ├─conf
 │  ├─html
 │  │      index.html
 │  └─log
 │          access.log
 │          error.log
 │          uwsgi.log
 └─static

docker-compose.yml ・・・(a)

ポイント

もともと、DjangoとPostgreSQLのみで実行するようdocker-composeを構成しており、「docker-compose up」で「command: python3 manage.py runserver 0.0.0.0:8000」によるアプリ起動をしていました。

しかし、リバースプロキシのnginxと連携させるために、djangoの前面にwebサーバとして「nginx」を配置し、そのnginxとdjangoの橋渡しとして 「uwsgi」を配置する構成に変更しました。以下に、その変更点のポイントを記載します。

version: '3'

services:
  db:
    image: postgres
    environment:
        TZ: "Asia/Tokyo"
  web:
    # Dockerfile が存在するディレクトリの相対パスを指定する
    build: .
    # コンテナ実行時に実行するコマンド
    command: uwsgi --ini ./djangofx/django.ini
    # コンテナの /code を、ホストのカレントディレクトリにマウントする
    volumes:
      - .:/code
      - '/var/run/uwsgi:/var/run/uwsgi'
    # ポートフォワーディング
    # ports:
     # ホストのポート:コンテナのポート
     #  - "8000:8000"
    depends_on:
      - db

  nginx:
    build: ./nginx
    tty: true
    image: fx
    container_name: fx
    environment:
      VIRTUAL_HOST: fx.localhost
    volumes:
      - '/etc/letsencrypt:/etc/letsencrypt'
      - '/var/run/uwsgi:/var/run/uwsgi'
    depends_on:
      - web
networks:
  default:
    external:
      name: dc_proxy_nw
  • [web]command: uwsgi –ini ./djangofx/django.ini (uwsgiを起動)
  • [web]ports:のコメントアウト(nginxがコンテナのポートで待ち構える)
  • [web]volumesに’/var/run/uwsgi:/var/run/uwsgi’を追加
  • [nginx]container_name: fx
  • [nginx]VIRTUAL_HOST: fx.localhost (これがリバースプロキシのconfファイルと紐づく)
  • [nginx]volumes:’/etc/letsencrypt:/etc/letsencrypt’でSSLファイル
  • [nginx]volumes: ‘/var/run/uwsgi:/var/run/uwsgi’
  • [networks]は、リバースプロキシ構築時に作成したネットワークと同じネットワークを使用

Dockerfile      ・・・(b)

nginx/uwsgiの追加による変更はなし。Django単体で動かしていた時のままです。

# ベースイメージ
FROM python:3
# Docker コンテナ内で使える環境変数を指定
ENV PYTHONUNBUFFERED 1
# イメージビルド時に mkdir /code する
RUN mkdir /code
# この後の指令は /code で実行する
WORKDIR /code
# requirements.txt をイメージ内の /code/ ディレクトリにコピーする
ADD requirements.txt /code/
RUN pip install -r requirements.txt
# カレントディレクトリ配下を /code 配下にコピーする
ADD . /code/

requirements.txt   ・・・(c)

uwsgiを追加しました。

# Production
# =============================================================================
uwsgi
numpy
scipy
scikit-learn
pandas
plotly
stockstats
Django>=2.0
psycopg2
oandapyV20
configparser
pytz
# =============================================================================

django.ini    ・・・(d)

uwsgiの追加にあわせて設定を追記しています。

[uwsgi]
#----------
socket = /var/run/uwsgi/uwsgi.sock
#----------
socket = 127.0.0.1:8001
#----------
chmod-socket = 666
module = djangofx.wsgi
wsgi-file = djangofx/wsgi.py
logto = ./nginx/log/uwsgi.log
py-autoreload = 1
master = true
processes = 4
threads = 2

#pidfile = ./djangofx/uwsgi.pid

ポイント

  • socket = /var/run/uwsgi/uwsgi.sock (nginxとの連携で使用するため、nginxの設定であるdefault.confと設定値を合わせる必要がある。)
  • chmod-socket = 666
  • wsgi-file = djangofx/wsgi.py
  • logto = ./nginx/log/uwsgi.log

settings.py   ・・・(e)

nginx/uwsgiの追加による変更はなし。

"""
Django settings for djangofx project.

Generated by 'django-admin startproject' using Django 2.2.1.

For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '(at(ou(a$6@-=8r+d8@#$au_b+08i%e@54@#43p^3u^fc09xog'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

#ALLOWED_HOSTS = ['localhost','140.227.164.62','dc.shiroshika.com']
ALLOWED_HOSTS = ['*']


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'ohlcv',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'djangofx.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'djangofx.wsgi.application'


# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases

# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
#     }
# }
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'postgres',
        'USER': 'postgres',
        'HOST': 'db',
        'PORT': 5432,
    }
}

# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/

LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

ポイント

  • ALLOWED_HOSTS = [‘*’] セキュリティ上よくないけど。。。

uwsgi.log     ・・・(f)

django.ini で設定されたパスに、uwsgiのログが出力されています。

default.conf   ・・・(g)

nginx/uwsgiの連携で重要な設定を記載。

upstream django {
    server unix:/var/run/uwsgi/uwsgi.sock;
}

server{
    listen 8000;
    server_name fx.localhost;

    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    location / {
        include /etc/nginx/uwsgi_params;
        uwsgi_pass django;
    }
}

ポイント

  • upstreamは、nginxとuwsgiの連携で使っているソケットファイルの格納場所。これはdjango.iniに記載した「 socket = /var/run/uwsgi/uwsgi.sock 」と一致させる。
    • 後日談ですが、このuwsgi.sockファイルは、作成するアプリケーション毎に、ファイルを別々にしておく必要があります。そうしないと、別々のドメインでログインしても、同じアプリケーションに転送されることになります。
  • serverは、リバースプロキシとnginxが連携するための設定を記載。この設定(ポート番号:8000やserver_name)が、リバースプロキシ側のconfファイルに記載されることになる。
  • リクエストが「/」で来た時の設定をlocation / に記載。この時、uwsgiの「uwsgi_params」が必要(下記の(i))。uwsgi_passは、「upstream django 」に連携する動きになる。

Dockerfile   ・・・(h)

  • uwsgi_paramsを所定のフォルダへコピーする。 default.confで記載した指定パス通りに配置する。
  • /etc/nginxの権限を設定(実行時にエラーが出たので追加した)
FROM nginx
COPY default.conf /etc/nginx/conf.d/default.conf
COPY uwsgi_params /etc/nginx/uwsgi_params
COPY html/index.html /etc/nginx/html/index.html
RUN chmod o+w /etc/nginx;
RUN chmod o+x /etc/nginx/html;
RUN chmod o+r /etc/nginx/html/index.html;
RUN chmod o+r /etc/nginx/uwsgi_params;
RUN apt-get update && apt-get install -y \
        wget && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

uwsgi_params ・・・(i)

固定値。何も考えない。

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;

追加したアプリケーションの起動

bitbucketのGitへpush

上記をGitへ登録します。

git add .
git commit -m "init"
git push origin master

VPS(WebArena)にソースをクローン

上記をGit(bitbuckt/Github)にアップしたら、VPS(WebArena)でクローンします。 SSHで接続します。

ssh -p ****** *****@***.***.***.*** -i .\id_rsa_webarena_********

ソースを管理するフォルダへ移動し、ソースをダウンロードします。

git clone git@bitbucket.org:*******/dc-proxy.git

Docker-composeの起動

docker-compose.ymlが格納されたフォルダへ移動し、docker-compose upを実行します。

$ docker-compose up

ブラウザから「https://fx.xxxxx.com」へアクセスして表示されれば成功です。

今回作成したアプリケーションの関連イメージは以下のようになっています。

docker

networks:
  default:
    external:
      name: dc_proxy_nw
[Not supported by viewer]
         ubuntu(物理サーバ)
[Not supported by viewer]
docker-compose.yml
docker-compose.yml
docker-compose.yml
docker-compose.yml
       
  /etc/nginx/conf
[Not supported by viewer]
/nginx
/nginx
/app1
/app1
default.conf
<span>default.conf</span>
uwsgi.ini
uwsgi.ini<br>
socket = /var/run/uwsgi/app1.sock
socket = /var/run/uwsgi/app1.sock
listen 8000;
server_name app1.localhost;
upstream app1{
    server unix:/var/run/uwsgi/app1.sock;
}
[Not supported by viewer]
docker-compose.yml
docker-compose.yml
/nginx
/nginx
/app2
/app2
default.conf
<span>default.conf</span>
uwsgi.ini
uwsgi.ini<br>
socket = /var/run/uwsgi/app2.sock
socket = /var/run/uwsgi/app2.sock
listen 8100;
server_name app2.localhost;
upstream app2{
    server unix:/var/run/uwsgi/app2.sock
}
[Not supported by viewer]
container1
container1
container2
container2
container1.conf
<span>container1.conf</span>
container2.conf
<span>container2.conf</span>
listen 443;
    server_name app1.xxxxx.com;

location / {
        proxy_pass   http://contanier1:8000;
    }
[Not supported by viewer]

Build multi site using nginx on Docker
① nginx reverse proxy / ② docker container app1 / ③ docker container app2 / ④ docker enviroment / ⑤ VPS server(ubuntu)

<h1><pre id=”tw-target-text” dir=”ltr”><span tabindex=”0″ lang=”en”>Build multi site using nginx on Docker</span></pre><pre id=”tw-target-text” dir=”ltr”><span tabindex=”0″ lang=”en”><font style=”font-size: 19px”>① nginx reverse proxy / ② docker container app1 / ③ docker container app2 / ④ docker enviroment / ⑤ VPS server(ubuntu)</font><br></span></pre></h1><p></p>
1
1
2
2
3
3
4
4
         /var/run/uwsgi
[Not supported by viewer]
app1.sock
<div>app1.sock</div>
app2.sock
<div>app2.sock</div>
container1
container1
listen 443;
    server_name app2.xxxxx.com

location / {
        proxy_pass   http://contanier1:8000;
    }
[Not supported by viewer]

以上が、 WebArenaVPSでマルチサイトを構築する手順になります。

まとめ記事に戻る:WebARENAの使い方 – 最安VPSでサイト構築(Docker + Let’s Encrypt)

About: ken


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください