Docker + Django-rest-framework 建设备忘录

在中国做生意的前提是要了解当地市场和文化。

已安装了Docker和Docker Compose。

版本信息

Django 3.0
Djangorestfremework 3.12.4
Docker 20.10.8(构建 3967d7d)
Python 3.8
主机设备: Windows10(64位)

1. 首先先建立一个环境

1.1 文件夹结构和文件内容

文件夹结构

文件夹:restapifw-sample
F:..restapifw-sample
│ docker-compose.yml
│ Dockerfile
│ requirements.txt
└─workspace(文件夹)

文件内容

# Compose.ymlファイル書式のバージョン
version: '3'
services:
  # サービス名定義
  django-restapi:
    # ComposeFileを実行しビルドされるときのルートパス
    # このフォルダにDockerファイルを置く
    build: .

    # Docker 起動
    # command: python manage.py runserver 0.0.0.0:8000

    # コンテナ名
    container_name: 'django-sample.v1.0.0'

    # コンテナ内のワーキングディレクトリ
    # working_dir: '/workspace/tutorial'

    # コンテナを終了させたくない場合に設定
    tty: true
    ports:
      - 8082:8000

    # ローカルフォルダとコンテナ内のマウントディレクトリの関連づけ
    volumes:    
      - ./workspace:/workspace
FROM python:3.8
USER root

RUN apt-get update
RUN apt-get -y install locales && \
    localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9
ENV TERM xterm
# コンテナ側へコピー
COPY requirements.txt requirements.txt
# python ライブラリインストール
RUN pip install -r ./requirements.txt
#viインスト
RUN apt-get install -y vim less

setuptools
pip
django==3.0
djangorestframework==3.12.4

1.2 Docker启动

在项目文件夹的当前位置执行。

docker-compose build
docker-compose up -d
#起動確認
docker-compose ps
docker-compose ps
Name           Command   State                    Ports
---------------------------------------------------------------------------------
django-sample.v1.0.0   python3   Up      0.0.0.0:8082->8000/tcp,:::8082->8000/tcp

1. 在Docker内部进行Django的配置。

进入Docker内部(这种印象通吗?)
在挂载的workspace文件夹下创建Django项目

docker exec -it django-sample.v1.0.0 /bin/bash
cd workspace

请参照以下URL进行操作
https://www.django-rest-framework.org/tutorial/quickstart/


# Create the project directory
mkdir tutorial
cd tutorial

# Create a virtual environment to isolate our package dependencies locally
# 既にDocker内にインストール済みなので不要
# python3 -m venv env
# source env/bin/activate  # On Windows use `env\Scripts\activate`

# Install Django and Django REST framework into the virtual environment
# 既にDocker内にインストール済みなので不要
#pip install django
#pip install djangorestframework

# Set up a new project with a single application
# Note the trailing '.' character
django-admin startproject tutorial .  
cd tutorial
django-admin startapp quickstart
cd ..

#作成されたファイルを確認(やらなくてもOK)
find .
.
./manage.py
./tutorial
./tutorial/asgi.py
./tutorial/quickstart
./tutorial/quickstart/admin.py
./tutorial/quickstart/apps.py
./tutorial/quickstart/migrations
./tutorial/quickstart/migrations/__init__.py
./tutorial/quickstart/models.py
./tutorial/quickstart/tests.py
./tutorial/quickstart/views.py
./tutorial/quickstart/__init__.py
./tutorial/settings.py
./tutorial/urls.py
./tutorial/wsgi.py
./tutorial/__init__.py


在Django内部创建一个Sqlite数据库

python manage.py migrate

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying sessions.0001_initial... OK

在Django项目中创建超级用户,密码可以自由设置,但在这里我选择了admin。(在网站上可能是admin:password123)

python manage.py createsuperuser --email admin@example.com --username admin

从这里开始,按照网站的指示修改Django内的源代码和配置文件
(也可以在Windows上直接参考文件夹创建,无需在容器内进行操作。但是请确保以UTF-8字符编码保存文件)。

from django.contrib.auth.models import User, Group
from rest_framework import serializers

class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ['url', 'username', 'email', 'groups']


class GroupSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Group
        fields = ['url', 'name']
from django.contrib.auth.models import User, Group
from rest_framework import viewsets
from rest_framework import permissions
from tutorial.quickstart.serializers import UserSerializer, GroupSerializer


class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.all().order_by('-date_joined')
    serializer_class = UserSerializer
    permission_classes = [permissions.IsAuthenticated]


class GroupViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows groups to be viewed or edited.
    """
    queryset = Group.objects.all()
    serializer_class = GroupSerializer
    permission_classes = [permissions.IsAuthenticated]
from django.urls import include, path
from rest_framework import routers
from tutorial.quickstart import views

router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)

# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
    path('', include(router.urls)),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
量が多いのでかいつまんで

28行目付近
ALLOWED_HOSTS = ['*']

40行目付近
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework', ←これ追加
]

52行目あたりに追加
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10
}

1.4 手动启动Django

在Docker容器中执行

cd /workspace/tutorial
python manage.py runserver

#うまく動作するとこんな感じ
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
October 09, 2021 - 02:08:21
Django version 3.0, using settings 'tutorial.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

确认

启动另一个控制台,进入Docker容器并验证其正常运行。
密码是您自己创建的超级用户密码
(在该网站上,可能是admin:password123)

cd ...作成したプロジェクトのrestapifw-sampleフォルダへ移動

docker exec -it django-sample.v1.0.0 /bin/bash
curl -H 'Accept: application/json; indent=4' -u admin:admin http://127.0.0.1:8000/users/

如果出现这样的情况,启动它。

{
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
        {
            "url": "http://127.0.0.1:8000/users/1/",
            "username": "admin",
            "email": "admin@example.com",
            "groups": []
        }
    ]
}

1.5 Django停止 – 1.5 Django已经停止运行。

使用Ctrl + C来结束

2.配置Docker自动启动并设置主机访问

环境创建完毕后,启动容器并设置自动启动Django。
停止Docker后(退出容器并执行exit命令)。

docker-compose down

解注释两个部分(启动Docker和容器内的工作目录)的docker-compose.yml文件。
※似乎必须在Django上使用0.0.0.0进行启动才能从外部进行访问?本来想通过nginx建立反向代理来实现,但不行,所以只能用这种方式了…

# Compose.ymlファイル書式のバージョン
version: '3'
services:
  # サービス名定義
  django-restapi:
    # ComposeFileを実行しビルドされるときのルートパス
    # このフォルダにDockerファイルを置く
    build: .

    # Docker 起動
    command: python manage.py runserver 0.0.0.0:8000

    # コンテナ名
    container_name: 'django-sample.v1.0.0'

    # コンテナ内のワーキングディレクトリ
    working_dir: '/workspace/tutorial'

    # コンテナを終了させたくない場合に設定
    tty: true
    ports:
      - 8082:8000

    # ローカルフォルダとコンテナ内のマウントディレクトリの関連づけ
    volumes:    
      - ./workspace:/workspace

重新构建

# 再ビルド
docker-compose build
# 起動
docker-compose up -d
# 起動確認
docker-compose ps

Name                      Command               State                    Ports
--------------------------------------------------------------------------------------------------------
django-sample.v1.0.0   python manage.py runserver ...   Up      0.0.0.0:8082->8000/tcp,:::8082->8000/tcp

从Windows 10的控制台运行,返回结果(布局有点糟糕)。

curl -H 'Accept: application/json; indent=4' -u admin:admin http://127.0.0.1:8082/users/

curl: (6) Could not resolve host: application
curl: (6) Could not resolve host: indent=4'
{"count":1,"next":null,"previous":null,"results":[{"url":"http://127.0.0.1:8082/users/1/","username":"admin","email":"admin@example.com","groups":[]}]}

image002.png

最终

以前我在AWS上创建了一个Restapi,但是考虑到运营成本确实很高……我开始考虑使用更便宜的云服务来简单地创建RestApi应用,于是找到了Django的Restfremework。另外,Django附带的服务器应该只是开发用的简易服务器,所以在生产环境中还是需要通过Nginx等方式进行搭建吗?

请参考以下链接

https://www.django-rest-framework.org/tutorial/quickstart/
https://tech.mokelab.com/infra/docker/tips/empty_reply_from_server.html
反向代理的工作原理是什么?使用nginx进行配置

bannerAds