Docker ComposeでDjango(uwsgi)とMySQL,Nginxの環境構築方法をまとめます。
画面はバックエンドのViewで描画しますが、Vue.jsの環境を用意することで画面の一部をコンポーネントとして描画するようにしています。
今回はindex画面(ロケットが描画されている画面)と管理画面を立ち上げた後、アプリケーションディレクトリを作りアプリケーションのindexページの描画設定を行うところまでまとめています。
開発環境
Python:3.7
Django:2.2
Vue.js:2.6.0
MySQL:5.7
Nginx:1.17.0
uWSGI:2.0.18
参考
Docker-Composeで作るDjango開発環境(Django + MySQL + uWSGI + Nginx)
フォルダ構成
複雑になっていますが、下記のような構成になっています。
project/
│
├──app/
│ │
│ ├──src/
│ │ │
│ │ ├──myapp/
│ │ │ │
│ │ │ ├──__pycache__/
│ │ │ │
│ │ │ ├──migrations
│ │ │ │ │
│ │ │ │ ├──__pycache__/
│ │ │ │ ├──__init__.py
│ │ │ │ └──0001_initial.py
│ │ │ │
│ │ │ ├──templates
│ │ │ │ │
│ │ │ │ ├──myapp/
│ │ │ │ │ │
│ │ │ │ │ └──index.html
│ │ │ │ │
│ │ │ │ └──layout.html
│ │ │ │
│ │ │ ├──__init__.py
│ │ │ ├──admin.py
│ │ │ ├──apps.py
│ │ │ ├──models.py
│ │ │ ├──tests.py
│ │ │ ├──urls.py
│ │ │ └──views.py
│ │ │
│ │ ├──project/
│ │ │ │
│ │ │ ├──__init__.py
│ │ │ ├──settings.py
│ │ │ ├──urls.py
│ │ │ └──wsgi.py
│ │ │
│ │ ├──static/
│ │ │ │
│ │ │ ├──css/
│ │ │ │ │
│ │ │ │ └──app.css
│ │ │ │
│ │ │ ├──img/
│ │ │ │
│ │ │ └──js/
│ │ │ │
│ │ │ ├──components/
│ │ │ └──app.js
│ │ │
│ │ ├──manage.py
│ │ ├──package-lock.json
│ │ ├──package.json
│ │ └──webpack.config.js
│ │
│ ├──static/
│ │ │
│ │ ├──admin/ *管理対象外
│ │ └──bundles/ *管理対象外
│ │
│ ├──Dockerfile
│ └──requirements.txt
│
├──mysql/
│ │
│ ├──mysql_data/ *管理対象外
│ │
│ ├──sql/
│ │ │
│ │ └──initialize.sql
│ │
│ ├──Dockerfile
│ └──my.cnf
│
├──nginx/
│ │
│ ├──Dockerfile
│ ├──nginx.cnf
│ └──iwsgi_params
│
├──.editorconfig
├──.env_example
├──.gitignore
├──docker-compose.yml
└──Readme.md
環境構築
docker-comopose.ymlの内容
.envでポート番号等の設定を行なっています。
DockerファイルやDB作成用のSQLは参考のものを流用しています。
- uwsgiコンテナにはnpmをインストールする様に編集しています。
version: "3.5"
services:
uwsgi:
build: ./app
container_name: project_uwsgi
volumes:
- ./app:/var/www/
expose:
- "${UWSGI_PORT}"
depends_on:
- db
ports:
- "${UWSGI_PORT}:${UWSGI_PORT}"
tty: true
environment:
TZ: "Asia/Tokyo"
APP_URL: ${APP_URL}
APP_ENV: ${APP_ENV}
DB_USER: ${DB_USER}
DB_PASSWORD: ${DB_PASSWORD}
DB_HOST: ${DB_HOST}
DB_DATABASE: ${DB_DATABASE}
nginx:
build: ./nginx
container_name: project_nginx
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/uwsgi_params:/etc/nginx/uwsgi_params
- ./app/static:/static
depends_on:
- uwsgi
ports:
- "${NGINX_HOST_HTTP_PORT}:${NGINX_HOST_HTTP_PORT}"
- "${NGINX_HOST_HTTPS_PORT}:${NGINX_HOST_HTTPS_PORT}"
environment:
TZ: "Asia/Tokyo"
db:
build: ./mysql
container_name: project_db
volumes:
- ./mysql/mysql_data:/var/lib/mysql # データの永続化
- ./mysql/sql:/docker-entrypoint-initdb.d
ports:
- "${MYSQL_PORT}:${MYSQL_PORT}"
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
TZ: "Asia/Tokyo"
requirements.txtの内容
Django==2.1.1
uwsgi==2.0.18
mysqlclient==1.4.6
django-webpack-loader==0.6.0
Pillow==6.2.1
実際の環境構築手順
docker-composeコマンドでstartprojectの実行
$ docker-compose run uwsgi django-admin.py startproject project .
settings.pyに下記の事項をそれぞれ所定の箇所に記載する
DB設定
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'db_name',
'USER': 'user_name',
'PASSWORD': 'user_pass',
'HOST': 'db_port',
'PORT': '3306',
'OPTIONS': {
'charset': 'utf8mb4'
},
}
}
文字コード、タイムゾーン
LANGUAGE_CODE = 'ja_JP.UTF-8'
TIME_ZONE = 'Asia/Tokyo'
collectstaticコマンド実行時に静的ファイルを集める場所を指定
STATIC_ROOT = '/var/www/static'
トップページに表示する画像などを格納するパスの設定「/static」
webpackでビルドしたファイルの格納場所の指定
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
WEBPACK_LOADER = {
'DEFAULT': {
'BUNDLE_DIR_NAME': 'bundles/',
'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
}
}
マイグレーションの実行
$ docker-compose run uwsgi ./manage.py makemigrations
$ docker-compose run uwsgi ./manage.py migrate
管理画面作成
管理者名、メールアドレス、パスワードを作成する
$ docker-compose run uwsgi ./manage.py createsuperuser
任意の値を設定する。
管理者画面のCSS設定
settings.pyに「STATIC_ROOT」の記述をした状態で下記を実行する
$ docker-compose run uwsgi ./manage.py collectstatic
npm環境の構築
(uwsgiコンテナにて)Dockerファイルで特にnpmの設定をしていない場合、下記の手順でnpmをインストールします。
apt install -y nodejs npm
npm install -g n
n stable
apt purge -y nodejs npm
Vue.jsのインストール
webpackなどもこのタイミングでインストールしておきます。
npm install --save-dev webpack webpack-cli webpack-bundle-tracker
npm install --save-dev vue-loader
npm install --save-dev style-loader css-loader sass-loader
npm install --save vue
npm install --save-dev @babel/core @babel/preset-env
npm install --save-dev babel-loader
npm installの実行
下記のようなpackage.jsonを予め用意しておけばnpm installコマンドだけでインストール出来ます。
$ docker-compose run uwsgi npm install
package.jsonの内容
場所:app/src/package.json
{
"name": "app",
"version": "1.0.0",
"description": "### myapp application.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "node_modules/.bin/webpack --mode development",
"build": "node_modules/.bin/webpack --mode production",
"watch": "node_modules/.bin/webpack --watch -d"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.7.4",
"@babel/preset-env": "^7.7.4",
"babel-loader": "^8.0.6",
"css-loader": "^3.2.1",
"sass-loader": "^8.0.0",
"style-loader": "^1.0.1",
"vue-loader": "^15.7.2",
"vue-template-compiler": "^2.6.10",
"webpack": "^4.41.2",
"webpack-bundle-tracker": "^0.4.3",
"webpack-cli": "^3.3.10"
},
"dependencies": {
"vue": "^2.6.10"
}
}
webpack.config.jsの作成
var path = require("path");
var webpack = require('webpack');
var BundleTracker = require('webpack-bundle-tracker');
var VueLoaderPlugin = require('vue-loader/lib/plugin');
var env = process.env.NODE_ENV;
module.exports = {
context: __dirname,
entry: './static/js/app.js',
output: {
filename: "[name]-[hash].js",
path: path.resolve('../static/bundles/'),
// publicPath: '/'
},
plugins: [
new BundleTracker({filename: './webpack-stats.json'}),
// .vueファイルを読み込めるようにする
new VueLoaderPlugin()
],
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
},
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
},
{
test: /\.css$/,
use: [
"vue-style-loader",
'style-loader',
{
loader: 'css-loader',
options: {
url: false,
sourceMap: true
}
}
]
},
]
},
resolve: {
extensions: ['.js', '.vue'],
modules: [
"node_modules"
],
alias: {
'vue': path.resolve('./node_modules/vue/dist/vue.js'),
}
},
}
アセットコンパイル
$ docker-compose run uwsgi npm run dev
コンテナの起動
$ docker-compose up -d
ブラウザでチェック
http://localhost
これでindexの画面(ロケットが表示されている画面)と管理画面が見れるようになります!
アプリケーションの新規作成
$ docker-compose run uwsgi ./manage.py startapp myapp
project/settings.pyの「INSTALLED_APPS」に作成したアプリケーション名を追記すること。
INSTALLED_APPS = {
...
'myapp',
...
}
sttings.pyの「INSTALLED_APPS」に下記を追記
INSTALLED_APPS = {
...
'webpack_loader',
'myapp',
...
}
アセットコンパイル
$ docker-compose run uwsgi npm run dev
myappアプリケーションのページをブラウザで表示する為の設定は下記の通りです。
myapp/urls.pyの作成
touch app/src/myapp/urls.py
下記の通り編集
from django.urls import path
from . import views
app_name = 'myapp'
urlpatterns = [
path('', views.index, name='index'),
]
myapp/views.pyの編集
from django.http import HttpResponse
from django.template import loader
def index(request):
template = loader.get_template('myapp/index.html')
context = {}
return HttpResponse(template.render(context, request))
project/urls.pyの編集
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('myapp.urls')),
]
あとは「/app/src/myapp/templates/myapp」ディレクトリにindex.htmlを作成することでmyappのindexページ(URL:localhost)をブラウザから開くことが出来るようになります。
jsファイルやcssファイルを追加して編集した際は随時npm runでビルドをします。
補足:不要ファイルの削除
環境を再構築したい時は下記のコマンドで既存のものを削除します。
$ docker-compose down --rmi all
$ unlink app/src/myapp
$ rm -rf app/src/node_modules
$ rm -rf app/src/project
$ rm -rf app/src/manage.py
$ rm -rf app/static/*
$ rm -rf mysql/mysql_data
まとめ
Laravelだと比較的直ぐにアセットのビルド環境を構築出来ていたのですが、Djangoの場合だとWebpackの設定ファイルを作るところから始めたのが新鮮で楽しかったです!
上記の内容でならアプリケーションコンテナでnpm run buildを実行することでVue.jsの画面を作成することが出来ますが、やはりフロントの環境をPythonのアプリケーションに混ぜると煩雑になり管理しにくくなります。
今回まとめた方法はあくまでViewをサーバーサイドで持ちたいと言う場合に使えそうな手段ですが、今後環境を構築するのならフロントエンドとバックエンドに分けて構築しようと思いました。