后端项目部署
根据分析的项目部署架构,后端需要需要mysql和redis。所有在此需要先把这些外部工具先预装。
一、安装mysql镜像
之前使用的mysql版本是5.7版本的。
# 如果之前的mysql已经镜像没有下载,则下载命令如下:
docker image pull mysql:5.7
# -e 设置容器内部的环境变量,一个容器在创建的时候,可以多个不同的环境
# 启动mysql容器,MYSQL_ROOT_PASSWORD 指代的就是mysql的root用户的登录密码
docker run -itd -p3306:3306 -e MYSQL_ROOT_PASSWORD=123456 --name=mysql mysql:5.7
docker container exec -it mysql bash
mysql -uroot -p
create database luffcc charset=utf8mb4;
# 如果需要多台mysql容器安装在一台服务器中,那么容器内部的端口可以不用设置,但是真实物理系统的端口必须要修改,保证端口唯一!
# docker run -itd -p3307:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
# docker run -itd -p3308:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
# 可以在任意一个外部网路中,远程链接到数据库中
# 注意使用命令远程链接mysql,必须使用的地方有mysql
mysql -hIP -P端口 -uroot -p密码
mysql -uroot -p123456 -h8.131.88.74
docker container run的选项:
-e 就是设置容器内部的环境变量, 在docker容器的使用过程中, 有部分容器需要配置环境的,这些环境变量都是有下载镜像时官方指定的。
把本地的数据导入到容器的mysql数据库中
# 远程链接数据库
mysql -uroot -p123456 -h8.131.88.74
# 把本地的数据库导出到桌面
mysqldump -uroot -p123456 luffy(本地) > ~/Desktop/data.sql
# 如果阿里云本机装了mysql客户端,可以直接通过本机的指令,将输入导入到容器中
# 可以在自己的电脑上,通过终端指令直接导入备份数据
# 把桌面下导出的数据库文件导入到docker容器中的mysql数据库
mysql -uroot -p123456 -h8.131.88.74 luffcc < ~/Desktop/data.sql
二、安装redis容器
# 需要在docker中下载redis和mysql的容器
docker pull redis
# 创建redis容器并运行redis
docker run -itd -p6379:6379 --name=redis redis
# 可以进入到容器中,进行测试redis是否已经成功启动
docker container exec -it redis bash
# 容器内部,执行 redis-cli
三、后端项目部署到docker容器中
1.把后端项目进行部署前的处理
1. 现在的配置,保存在dev.py中,不管数据库密码或者redis的地址或者配置信息都是属于开发阶段,
项目上线以后,肯定换成公司的。所以一定会修改,我们需要把dev.py的内容复制到prod.py中,
并修改对应的配置信息
ALLOWED_HOSTS = ['www.cwj666.xyz', 'www.cwj888.xyz']
CORS_ORIGIN_WHITELIST = (
'http://www.cwj666.xyz',
)
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"HOST": "8.131.88.74",
"PORT": 3306,
"USER": "root",
"PASSWORD": "123456",
"NAME": "luffcc",
}
}
redis替换地址
"LOCATION": "redis://8.131.88.74:6379/0",
...
支付宝:
"return_url": "http://www.cwj666.xyz/payment/result", # 同步回调地址
"notify_url": "http://www.cwj888.xyz/payment/result/", # 异步结果通知
wsgi.py
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'lyapi.settings.prod')
2. 在本地开发时,我们使用的框架运行在debug模式下的,但是项目上线时,会关闭debug,所以我们如果关闭了debug模式,则drf框架会不再提供静态文件的浏览服务,也就是之前xadmin,drf的接口页面的图片,样式或者js文件都不能访问到了。我们需要收集这些文件到外界,后面通过nginx来对外提供浏览服务
3. 原来的drf项目是运行在python内置的提供的web服务器中,wsgiref
在项目上线的时候,我们不能使用这个模块来提供对外服务!
不支持多线程,性能不好,本身在安全性上并不完善,python提供这个模块仅供学习和开发测试使用。
runserver 不能用于生产,改成uwsgi
4. 原来drf项目在本地开发时,其实要运行这个项目,我们是安装了很多的以来模块。
将来项目上线了,我们也肯定需要把本地的模块同步到线上服务器!否则项目跑不起来
2.修改现有的配置文件
在项目中复制开发配置文件dev.py 到生产配置prod.py
修改配置中的地址,删除之前的一些日志文件
"""
Django settings for lyapi project.
Generated by 'django-admin startproject' using Django 2.2.
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 = '7q4a*v$s#g#a@6vi)97o%x+33tbv--z20_61vte!@d-_9&6g*9'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
ALLOWED_HOSTS = ['www.cwj666.xyz', 'www.cwj888.xyz']
import sys
# print(sys.path)
sys.path.insert(0, os.path.join(BASE_DIR,'apps'))
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'xadmin',
'crispy_forms',
'reversion',
'corsheaders',
'django_filters',
'ckeditor', # 富文本编辑器
'ckeditor_uploader', # 富文本编辑器上传图片模块
'home',
'users',
'course',
'cart',
'order',
'coupon',
'payment',
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'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',
]
AUTH_USER_MODEL = 'users.User'
# CORS组的配置信息
CORS_ORIGIN_WHITELIST = (
#'www.luffycity.cn:8080', #如果这样写不行的话,就加上协议(http://www.luffycity.cn:8080,因为不同的corsheaders版本可能有不同的要求)
'http://www.cwj666.xyz',
)
CORS_ALLOW_CREDENTIALS = False # 是否允许ajax跨域请求时携带cookie,False表示不用,我们后面也用不到cookie,所以关掉它就可以了,以防有人通过cookie来搞我们的网
ROOT_URLCONF = 'lyapi.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR , 'templates']
,
'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 = 'lyapi.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'),
# }
# }
# 富文本编辑器ckeditor配置
CKEDITOR_CONFIGS = {
'default': {
'toolbar': 'full', # 工具条功能,full表示全部,Basic表示基本功能,功能少很多,还有个Custom自定义功能选项
'height': 300, # 编辑器高度
# 'width': 300, # 编辑器宽
},
}
CKEDITOR_UPLOAD_PATH = '' # 上传图片保存路径,留空则调用django的文件上传功能
XX = 'oo'
# 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 = 'zh-Hans'
# 修改时区
TIME_ZONE = 'Asia/Shanghai'
# LANGUAGE_CODE = 'en-us'
# TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
# USE_TZ = True
USE_TZ = False
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
STATIC_URL = '/static/'
# 项目中存储上传文件的根目录[暂时配置],注意,uploads目录需要手动创建否则上传文件时报错
MEDIA_ROOT=os.path.join(BASE_DIR,"uploads") #
# 访问上传文件的url地址前缀
MEDIA_URL ="/media/"
STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'static')
# 日志配置
LOGGING = {
'version': 1, #使用的python内置的logging模块,那么python可能会对它进行升级,所以需要写一个版本号,目前就是1版本
'disable_existing_loggers': False, #是否去掉目前项目中其他地方中以及使用的日志功能,但是将来我们可能会引入第三方的模块,里面可能内置了日志功能,所以尽量不要关闭。
'formatters': { #日志记录格式
'verbose': { #levelname等级,asctime记录时间,module表示日志发生的文件名称,lineno行号,message错误信息
'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'
},
'simple': {
'format': '%(levelname)s %(module)s %(lineno)d %(message)s'
},
},
'filters': { #过滤器:可以对日志进行输出时的过滤用的
'require_debug_true': { #在debug=True下产生的一些日志信息,要不要记录日志,需要的话就在handlers中加上这个过滤器,不需要就不加
'()': 'django.utils.log.RequireDebugTrue',
},
'require_debug_false': { #和上面相反
'()': 'django.utils.log.RequireDebugFalse',
},
},
'handlers': { #日志处理方式,日志实例
'console': { #在控制台输出时的实例
'level': 'DEBUG', #日志等级;debug是最低等级,那么只要比它高等级的信息都会被记录
'filters': ['require_debug_true'], #在debug=True下才会打印在控制台
'class': 'logging.StreamHandler', #使用的python的logging模块中的StreamHandler来进行输出
'formatter': 'simple'
},
'file': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
# 日志位置,日志文件名,日志保存目录必须手动创建
'filename': os.path.join(os.path.dirname(BASE_DIR), "logs/luffy.log"), #注意,你的文件应该有读写权限。
# 日志文件的最大值,这里我们设置300M
'maxBytes': 300 * 1024 * 1024,
# 日志文件的数量,设置最大日志数量为10
'backupCount': 10,
# 日志格式:详细格式
'formatter': 'verbose',
'encoding': 'utf-8', # 设置默认编码,否则打印出来汉字乱码
},
},
# 日志对象
'loggers': {
'django': { #和django结合起来使用,将django中之前的日志输出内容的时候,按照我们的日志配置进行输出,
'handlers': ['console', 'file'], #将来项目上线,把console去掉
'propagate': True, #冒泡:是否将日志信息记录冒泡给其他的日志处理系统,工作中都是True,不然django这个日志系统捕获到日志信息之后,其他模块中可能也有日志记录功能的模块,就获取不到这个日志信息了
},
}
}
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication', #jwt认证
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
# 异常处理
'EXCEPTION_HANDLER': 'lyapi.utils.exceptions.custom_exception_handler',
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',),
}
import datetime
JWT_AUTH = {
# 'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300),
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
'JWT_RESPONSE_PAYLOAD_HANDLER': 'users.utils.jwt_response_payload_handler',
}
AUTHENTICATION_BACKENDS = [
'users.utils.CustomeModelBackend',
]
#####
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"HOST": "8.131.88.74",
"PORT": 3306,
"USER": "root",
"PASSWORD": "123456",
"NAME": "luffcc",
}
}
FSQ = {
'URL':"https://ssl.captcha.qq.com/ticket/verify",
'appid':'2041284967',
'app_serect_key':'0FrDthTnnU8vG-jSwz7DOAA**',
}
# 设置redis缓存
CACHES = {
# 默认缓存
"default": {
"BACKEND": "django_redis.cache.RedisCache",
# 项目上线时,需要调整这里的路径
"LOCATION": "redis://8.131.88.74:6379/0",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
},
# 提供给xadmin或者admin的session存储
"session": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://8.131.88.74:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
},
# 提供存储短信验证码
"sms_code":{
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://8.131.88.74:6379/2",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
},
},
"cart":{
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://8.131.88.74:6379/3",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
},
}
}
# 设置xadmin用户登录时,登录信息session保存到redis
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "session"
SMS_INFO = {
'ACCID':'8aaf0708754a3ef2017563ddb22d0773',
'ACCTOKEN':'0b41612bc8a8429d84b5d37f29178743',
'APPID':'8aaf0708754a3ef2017563ddb3110779',
'TID': 1,
}
# 支付宝配置信息
ALIAPY_CONFIG = {
# "gateway_url": "https://openapi.alipay.com/gateway.do?", # 真实支付宝网关地址
"gateway_url": "https://openapi.alipaydev.com/gateway.do?", # 沙箱支付宝网关地址
"appid": "2016110100783756", # 沙箱中那个应用id
"app_notify_url": None,
"app_private_key_path": os.path.join(BASE_DIR, "apps/payment/keys/app_private_key.pem"),
"alipay_public_key_path": os.path.join(BASE_DIR, "apps/payment/keys/alipay_public_key.pem"),
"sign_type": "RSA2",
"debug": False,
"return_url": "http://www.cwj666.xyz/payment/result", # 同步回调地址
"notify_url": "http://www.cwj888.xyz/payment/result/", # 异步结果通知
}
POLYV_CONF = {
'userid':'348e998797',
'secretKey':'JLyFq9TN0w',
'tokenUrl':'https://hls.videocc.net/service/v1/token'
}
3.从服务端项目中收集静态文件
当Django运行在生产环境中,我们会关闭debug调试,那么项目将不再提供静态文件的支持,需要将静态文件交给静态文件的nginx服务器来提供访问。
我们先收集所有静态文件。项目中的静态文件除了我们使用的上传文件之外,django本身还有自己的静态文件,如rest_framework、xadmin、admin、ckeditor等。我们需要收集这些静态文件,集中一起放到静态文件服务器中。
我们要将收集的静态文件放到项目的static目录中,所以先创建目录static。
Django提供了收集静态文件的方法。先在配置文件中配置收集之后存放的目录
settings/prod.py和dev.py ,代码:
STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'static')
因为目前在本地我们依然使用了dev.py文件运行项目,所以我们在本地项目收集静态文件就需要把配置信息同步到dev.py
在终端下执行收集命令
python manage.py collectstatic
-------------------------------------------------------------未完得续…