首先
在上一篇文章的基础上,我将在nginx的Nuxt.js Django REST框架上运行一个应用程序。
配置图
有以下四个容器。
自上次发布以来,我已经添加了一个nginx容器。
?首页显示
①通过nginx 访问nuxt容器
②带nuxt容器的SSR。这时,请点击API以从django获取数据库信息。
③将呈现的页面返回给用户
?当您点击页面中的API时
通过nginx访问django容器,并将结果返回给用户。
环境
Window10 Pro
Docker桌面v2.1.0.5
Python 3.6.9
django 2.2.7
djangorestframework 3.10.3
Nuxt.js v2.11.0
nginx 1.13.12
目录结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | . ├─django │ ├─manage.py │ ├─composeexample │ │ ├─settings.py │ │ ├─urls.py │ │ ├─wsgi.py │ │ └─__init__.py │ └─myapp │ ├─migrations │ ├─admin.py │ ├─apps.py │ ├─models.py │ ├─renderers.py │ ├─serializers.py │ ├─tests.py │ ├─urls.py │ ├─views.py │ └─__init__.py │ ├─docker-compose.yml │ ├─dockerfiles │ ├─django_docker │ │ ├─dockerfile │ │ └─requirements.txt │ └─nuxt_docker │ └─dockerfile │ ├─mysql │ └─conf.d │ ├─nginx │ ├─uwsgi_params │ └─conf │ └─app_nginx.conf │ └─nuxt └─front └─以下略 |
自上次以来的变化
在上一篇文章中,它是在SPA中设置的,但是这次我们将继续在SSR中进行设置。
./nuxt/front/nuxt.config.js
1 2 | export default { mode: 'universal', //SSRに変更 |
建筑nginx
编辑docker-compose.yml
将nginx设置添加到docker-compose.yml中。
分配端口80。
./docker-compose.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | version: '3' services: db: image: mysql:latest restart: always container_name: mysql environment: MYSQL_ROOT_PASSWORD: test MYSQL_USER: test MYSQL_DATABASE: test MYSQL_PASSWORD: test ports: - 3306:3306 expose: - 3306 volumes: - mysqldata:/var/lib/mysql - ./mysql/conf.d:/etc/mysql/conf.d web: container_name: django build: ./dockerfiles/django_docker command: python3 manage.py runserver 0.0.0.0:8000 volumes: - ./django:/code ports: - "8000:8000" depends_on: - db front: container_name: nuxt build: ./dockerfiles/nuxt_docker tty: true volumes: - ./nuxt:/code ports: - "3000:3000" #ここから nginx: image: nginx:1.13 container_name: nginx ports: - "80:80" #ここまで volumes: mysqldata: |
让我们从这里开始一次nginx。
确认docker ps已启动。
1 2 3 4 5 | > docker-compose up -d nginx > docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES aa3fe475db52 nginx:1.13 "nginx -g 'daemon of…" About a minute ago Up About a minute 0.0.0.0:80->80/tcp nginx |
如果访问
http:// localhost /并显示以下屏幕,则说明操作成功。
Django方面的变化
添加nginx配置文件
添加以下目录和文件。
1 2 3 4 5 | . └─nginx ├─uwsgi_params └─conf └─app_nginx.conf |
以下是使用uWSGI的设置。
uwsgi_params
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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的设置。
目标由路径分隔,因此与/ api和/ admin的通信将到达Django容器的端口8000。
除此之外,我将其设置为通过HTTP进入nuxt容器的端口3000。
参考
./nginx/conf/app_nginx.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | upstream django { ip_hash; server web:8000; } server { listen 80; server_name 127.0.0.1; charset utf-8; location / { proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 1m; proxy_connect_timeout 1m; proxy_pass http://nuxt:3000; } location ~* /api|admin/ { uwsgi_pass django; include /etc/nginx/uwsgi_params; } } server_tokens off; |
uWSGI
的介绍
我们将更改设置以在Django上安装uWSGI。
将uwsgi添加到require.txt。
./dockerfiles/django_docker/requirement.txt
1 2 3 4 5 6 | Django>=2.0,<3.0 djangorestframework django-webpack-loader django-cors-headers mysqlclient uwsgi #追加 |
编辑
docker-compose.yml。
将django启动命令从开发运行服务器切换到uwsgi。
--socket:8000 --http:8001
通过nginx访问时,WSGI为8000,
这样,从Nuxt访问时,您可以通过HTTP访问8001。
另外,从nginx容器中显示先前的配置文件。
./docker-compose.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | version: '3' services: db: image: mysql:latest restart: always container_name: mysql environment: MYSQL_ROOT_PASSWORD: test MYSQL_USER: test MYSQL_DATABASE: test MYSQL_PASSWORD: test ports: - 3306:3306 expose: - 3306 volumes: - mysqldata:/var/lib/mysql - ./mysql/conf.d:/etc/mysql/conf.d web: container_name: django build: ./dockerfiles/django_docker ####runserverからuwsgiコマンドに変更 command: uwsgi --socket :8000 --http :8001 --module config.wsgi --py-autoreload 1 -b 32768 #### volumes: - ./django:/code ports: - "8000:8000" depends_on: - db front: container_name: nuxt build: ./dockerfiles/nuxt_docker tty: true ####nuxtの起動コマンドを追加 command: > bash -c 'cd front && yarn dev' #### volumes: - ./nuxt:/code ports: - "3000:3000" nginx: image: nginx:1.13 container_name: nginx ports: - "80:80" ####以下追加 volumes: - ./nginx/conf:/etc/nginx/conf.d - ./nginx/uwsgi_params:/etc/nginx/uwsgi_params depends_on: - web #### volumes: mysqldata: |
将以下内容添加到
setting.py中的ALLOWED_HOSTS。
./django/composeexample/setting.py
1 | ALLOWED_HOSTS = ["localhost","django"] |
Nuxt修复
上次发布时,我使用SPA创建了它,但是我将更改挂载到异步数据以使其成为SSR。
./nuxt/front/pages/index.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | //~略~ <script> import Logo from '~/components/Logo.vue' import axios from 'axios' //追記 export default { components: { Logo }, //ここから data() { return { dat: [] } }, async mounted(){ const url = "/api/get_person/" const response = await this.$axios.get(url) this.dat = response.data } //ここまで //↓↓↓に変更 //ここから async asyncData({ $axios }){ const url = "api/get_person/" const response = await $axios.get(url) return { dat: response.data} //ここまで } </script> //~略~ |
还要修改nuxt.conf.js。
将axios baseURL更改为http:// django:8001,将browserBaseURL更改为http:// localhost。
在SSR(服务器端)期间从Nuxt容器访问API时,使用baseURL,
在浏览器(客户端)中点击API时,会使用browserBaseURL。
当使用Nuxt打API时,请直接转到Django,
对于浏览器,请转到Nginx。
./nuxt/front/nuxt.config.js
1 2 3 4 5 6 7 | export default { //~略~ axios: { baseURL: "http://django:8001", browserBaseURL: "http://localhost", }, //~略~ |
在此状态下构建。
如果启动四个容器,则表示成功。
1 2 3 4 5 6 7 8 | > docker-compose up -d --build > docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 400297780ac2 qiita1_web "uwsgi --socket :800…" 9 minutes ago Up 9 minutes 0.0.0.0:8000->8000/tcp django a7ca824f3526 nginx:1.13 "nginx -g 'daemon of…" 37 minutes ago Up 37 minutes 0.0.0.0:80->80/tcp nginx c96258eee9b0 qiita1_front "docker-entrypoint.s…" 37 minutes ago Up 37 minutes 0.0.0.0:3000->3000/tcp nuxt 58377df67b22 mysql:latest "docker-entrypoint.s…" 37 minutes ago Up 37 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp mysql |
如果访问
http:// localhost并显示TOP页面,则可以通过nginx访问它。
您还可以通过
http:// localhost / api / get_person通过nginx获取API结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | > curl http://localhost/api/get_person StatusCode : 200 StatusDescription : OK Content : {"person_data": [{"id": 1, "person_name": "takashi", "person_age": 26}, {"id": 2, "pe rson_name": "naoto", "person_age": 32}, {"id": 3, "person_name": "tomoko", "person_ag e": 15}]} RawContent : HTTP/1.1 200 OK Connection: keep-alive Allow: GET, HEAD, OPTIONS X-Frame-Options: SAMEORIGIN Vary: Cookie, Origin Content-Length: 179 Content-Type: application/json; charset=utf-8 Date: Fri, 08... Forms : {} Headers : {[Connection, keep-alive], [Allow, GET, HEAD, OPTIONS], [X-Frame-Options, SAMEORIGIN] , [Vary, Cookie, Origin]...} Images : {} InputFields : {} Links : {} ParsedHtml : System.__ComObject RawContentLength : 179 mysql |
这样就完成了初始显示部分。
API编辑
接下来,我们将创建API部分。
由于我上次发布时仅创建了GET端点,因此我还将创建POST端点。
编辑urls.py和view.py。
./django/myapp/views.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | from django.shortcuts import render from django.views.generic import ListView from myapp.models import Person_data from rest_framework import status from rest_framework.generics import ListAPIView, CreateAPIView #追加 from rest_framework.permissions import AllowAny from .renderers import PersonJSONRenderer from .serializers import PersonSerializer # Create your views here. class PersonListApiView(ListAPIView): model = Person_data # モデルを指定 queryset = Person_data.objects.all() permission_classes = (AllowAny, ) renderer_classes = (PersonJSONRenderer, ) serializer_class = PersonSerializer ####以下追加 class PersonCreateApiView(CreateAPIView): model = Person_data queryset = Person_data.objects.all() permission_classes = (AllowAny, ) renderer_classes = (PersonJSONRenderer, ) serializer_class = PersonSerializer |
./django/myapp/urls.py
1 2 3 4 5 6 7 8 | from django.urls import path from .views import PersonListApiView, PersonCreateApiView #追加 urlpatterns = [ path('get_person/', PersonListApiView.as_view()), path('post_person/', PersonCreateApiView.as_view()), #POST追加 ] |
这就是添加API所需的全部。
POST并确认返回了201。
(Windows Power Shell的示例)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | > curl -Method POST -Body @{person_name="takaishi"; person_age=11;} http://localhost/api/post_person/ StatusCode : 201 StatusDescription : Created Content : {"person_data": {"id": 18, "person_name": "takaishi", "person_age": 11}} RawContent : HTTP/1.1 201 Created Connection: keep-alive Allow: POST, OPTIONS X-Frame-Options: SAMEORIGIN Vary: Cookie, Origin Content-Length: 72 Content-Type: application/json; charset=utf-8 Date: Fri, 08 ... Forms : {} Headers : {[Connection, keep-alive], [Allow, POST, OPTIONS], [X-Frame-Options, SAMEO RIGIN], [Vary, Cookie, Origin]...} Images : {} InputFields : {} Links : {} ParsedHtml : System.__ComObject RawContentLength : 72 |
您可以通过更新TOP页面来确认已添加。
在TOP页面
上创建一个表单
创建一个简单的表单,以便您可以从网页进行POST。
./nuxt/front/pages/index.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | <template> <div class="container"> <div> <logo /> <h1 class="title"> front </h1> <h2 class="subtitle"> My doozie Nuxt.js project </h2> <div class="links"> <a href="https://nuxtjs.org/" target="_blank" class="button--green" > Documentation </a> <a href="https://github.com/nuxt/nuxt.js" target="_blank" class="button--grey" > GitHub </a> <div v-for="d in dat.person_data" :key=d.person_name align="center"> <h2> {{d.person_name}} {{d.person_age}} </h2> </div> <!-- ここから追記 --> <input type="text" v-model="name"> <input type="text" v-model="age"> <button v-on:click="post">ADD</button> <!-- ここまで追記 --> </div> </div> </div> </template> <script> import Logo from '~/components/Logo.vue' export default { components: { Logo }, //ここから追記 data() { return { name: '', age: '', } }, methods: { post () { const url = "api/post_person/" axios.defaults.xsrfCookieName = 'csrftoken' axios.defaults.xsrfHeaderName = "X-CSRFTOKEN" axios.post(url, {person_name: this.name , person_age: this.age}) } }, //ここまで追記 async asyncData({ $axios }){ const url = "api/get_person/" const response = await $axios.get(url) return { dat: response.data} } } </script> //~略~ |
现在,您可以从TOP页面进行POST。
您可以键入它,然后按ADD按钮发送POST。
通过刷新页面,渲染将再次运行并更新显示。
参考
使用Docker构建Django Nginx MySQL开发环境。
正确运行时的UWSGI设置备忘录
在EC2上尝试Django Nginx uWSGI