一、项目框架图
首先创建一个桥接网络:
docker network create ck12
(1)redis
提供celery的消息队列服务
docker命令:
docker run --name ck13_redis --restart=always -d --network ck13 redis:alpine
(2)mariadb
提供后端数据库服务
docker命令:
docker run --name ck13_db --restart=always -d --network ck13 -v ck13_db:/var/lib/mysql -e MARIADB_ROOT_PASSWORD=pythonvip -e MARIADB_DATABASE=lemontest mariadb:latest
(3)django_app
django项目的部署的常用方案是 nginx+gunicorn
需要运行一个python3.8环境的容器,且需要启动的服务:
- celery worker
- celery beate server
- gunicorn
步骤:
1. 切换生产模式配置文件
1.在pro.py生产配置文件中配置如下:
# ------------------------------------------
# @Author:doctor
# @Copyright:international
# @Attention:hurry up!
# @Time:2023/3/16 8:37 PM
# @Project:ck13_backend
# @File:PyCharm
# -------------------------------------------
# 生产配置模块
# 导入公共配置
from .base_settings import *
# 生产配置
DEBUG = False
# 允许的域名与主机
ALLOWED_HOSTS = ['*']
# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'bravetest',
'USER': 'root',
'PASSWORD': 'pythonvip',
'HOST': 'ck13_db', # 不能直接写死为数据库容器的id,因为每次创建容器的ip是不一样的。# 写死不利于自动化部署。# 所以要写成容器的容器名
'PORT': '3306',
}
}
# CORS设置
# # 允许跨域的域名列表
# CORS_ALLOWED_ORIGINS = [
# 'http://localhost:8080'
# ]
# # 允许cookies跨域
# CORS_ALLOW_CREDENTIALS = True
# 运行所有域名跨域
CORS_ALLOW_ALL_ORIGINS = True
# celery配置
# 时区
CELERY_TIMEZONE = TIME_ZONE
CELERY_BROKER_URL = 'redis://k13_redis:6379/0' # 同数据库的配置
# 禁止celery自己的日志器
# 然后在django项目中配置日志器
CELERY_WORKER_HIJACK_ROOT_LOGGER = False
2. 安装gunicorn
django只是一个web框架,开发时运行的服务只做开发时用,部署时会使用WSGI服务器。这里我们选用gunicorn它是一个python语言实现的UNIX系统下的WSGI http服务器。
- 安装 pip install gunicorn
- 启动django服务
在项目根目录下运行
gunicorn -c gunicorn.conf.py project_name.wsgi # 注意gunicorn不支持windows
git remote -v 看下我们代码在哪里
云服务器上拉取代码发现没有git,所以得先下载一个git
下载后复制刚才的git地址去拉取项目,发现没有配公钥,还得配下公钥。
1.云服务器下载git后,输入
ssh-keygen -t ed25519 -C 自己起sshkeyName 3次回车
2,查看公钥
cat ~/.ssh/id_ed25519.pub
3,复制生成后的 ssh key
通过Gitee仓库主页 「管理」->「部署公钥管理」->「添加部署公钥」 ,添加生成的 public key 添加到仓库中
4,首次使用,需要确认并添加主机到本机SSH可信列表,云服务器输入
ssh -T git@gitee.com
然后添加公钥,添加完之后再去云服务器中从gitee拉取项目 。
配置python3.8.10环境,然后把代码映射进去,然后在容器里面装环境
docker pull python:3.8.10-alpine
手动启动一个容器
docker run --name ck13_django --restart=always -it --network ck13 -e ENV=production python:3.8.10-alpine
进去发现他直接进到python编辑了我们直接退出去,发现python依旧还是在运行的。
然后我们 docker exec -it ck13_django sh 进入这个容器,发现我们项目代码没有映射进来,所以我们只能停掉并且先删除ck13_django这个python容器
重新启动一个容器:
docker run --name ck13_django -v /ck13/manual/django_app/:/app/ --restart=always -it --network ck13 -e ENV=production python:3.8.10-alpine /bin/sh
启动成功之后,我们需要安装项目的依赖
/app # pip install -r requirements.txt -i https://pypi.douban.com/simple
期间,下载ruamel.yaml.clib、下载安装mysqlclient包报错,解决方法:
sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
apk update
apk upgrade
apk add --no-cache tzdata mariadb-dev gcc libc-dev
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
echo "Asia/Shanghai" > /etc/timezone
pip install --no-cache-dir -i https://pypi.douban.com/simple -r requirements.txt
启动gunicorn服务,
gunicorn -c gunicorn.conf.py lemontest.wsgi
这里没有结束 说明就是成功的。如果失败了记得去tail 查看log日志。
因为这里没有做端口映射,所以我外网访问不了,所以我们再去打开一个云服务器窗口,还是进入这个容器(等同于在同一个电脑里面)。
curl http://127.0.0.1:8000
# 启动 worker服务
/app # celery -A lemontest worker -l info
因为我需要启动三个进程,这样子去启动不方便管理。所以我们需要再学一个库。
3. 安装 supervisor
在本容器中还需要运行celery的worker服务和beat服务。我们使用supervisor进行进程控制。
安装
pip install supervisor
创建配置文件:
下面的命令会导出默认的配置文件
echo_supervisord_conf > supervisord.conf
supervisord.conf配置文件内容:
[unix_http_server]
file=/tmp/supervisor.sock ; the path to the socket file
[supervisord]
logfile=/tmp/supervisord.log ; main log file; default $CWD/supervisord.log
logfile_maxbytes=50MB ; max main logfile bytes b4 rotation; default 50MB
logfile_backups=10 ; # of main logfile backups; 0 means none, default 10
loglevel=info ; log level; default info; others: debug,warn,trace
pidfile=/tmp/supervisord.pid ; supervisord pidfile; default supervisord.pid
nodaemon=true ; start in foreground if true; default false
silent=false ; no logs to stdout if true; default false
minfds=1024 ; min. avail startup file descriptors; default 1024
minprocs=200 ; min. avail process descriptors;default 200
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket
[program:gunicorn]
command=gunicorn -c gunicorn.conf.py lemontest.wsgi
[program:celery_worker]
command=celery -A lemontest worker -l info
[program:celery_beat]
command=celery -A lemontest beat -l info
启动supervisor
supervisord -c supervisor.conf
我们看到celery_beat在不停的退出,我们在logs目录下查看下日志tail celery.log。
我们数据库还没有迁移
4.重新跑一个,因为上面没映射端口
docker run --name ck13_django -p 9321:8000 -v /ck13/manual/django_app/:/app/ --restart=always -it --network ck13 -e ENV=production python:3.8.10-alpine /bin/sh
重复上面的操作之后,我们可以访问自己云服务器地址:9321端口(记得云服务器安全组中开放9321端口),例如http://123.60.136.121:9321/
页面展示这样子就说明后端配置在云服务器上已经没有问题了。 我们可以把前端BaseUrl改成上面的url,本地前端就能正常调用接口了。
二、dockerfile
dockerfile:
# 指定从哪个镜像开始构建
FROM python:3.8.10-alpine
# 可以给镜像打一些标签,其实就是一个额外的信息
# 对镜像本身功能没有任何影响
LABEL maintainer='daxia'
LABEL description='ck13'
LABEL customer='value'
# 接下来的操作,等价于手动到容器里操作
# 创建/app的目录,并切换进目录下
WORKDIR /app
# 拷贝代码到镜像中
# COPY 宿主机地址 镜像中的地址
# 一般会使用相对路径
# 宿主机的地址,相对Dockerfile的路径
# 镜像中的地址,相对于workdir
COPY . .
# 安装必要的库
# RUN命令会增加镜像的层,所以不要多次使用RUN
# 尽量把命令写到一行
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories && \
apk update && \
apk upgrade && \
apk add --no-cache tzdata mariadb-dev gcc libc-dev && \
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone && \
python -m pip install -i https://pypi.douban.com/simple --upgrade pip && \
pip install --no-cache-dir -i https://pypi.douban.com/simple -r requirements.txt && \
chmod 777 ./entrypoint.sh
# 创建挂载点
# 这里创建挂载点只是在镜像中声明一下
# 以后启动容器的时候,需要创建命名卷,如果不创建的话,docker会创建匿名卷
VOLUME /app/logs/
# 挂载端口
# 标识当前镜像中使用的端口
EXPOSE 8000
# 启动容器时默认启动的命令
# 如果启动一条命令可以使用CMD这个指令
#CMD ['supervisord', '-c', 'supervisor.conf']
#CMD ./entrypoint.sh #一般不用这个避免被覆盖,用ENTRYPOINT
# 当前镜像默认启动的命令有多条
# 1. 数据库迁移
# 2. 创建管理员用户
# 3. 启动supervisord服务
# 当启动容器时,需要执行多条命令的时候 用 ENTRYPOINT
# 可以把多条指令写到shell脚本中,然后再执行
ENTRYPOINT ["./entrypoint.sh"]
enterpoint.sh
#!/bin/sh
# 设置shell若有指令失败立刻退出
# set -e
# 执行数据库迁移
python manage.py makemigrations
# 数据库迁移有可能会失败,原因是数据库可能还没准备好
python manage.py migrate
# 所以加一个判断,如果失败了,就退出,状态返回为1
# 再配合启动容器的restart=always,达到等待数据启动的效果
if [ $? -ne 0 ]; then
echo '数据库连接失败重启'
exit 1
fi
# 创建管理员用户
echo "from django.contrib.auth import get_user_model; User = get_user_model(); User.objects.create_superuser('xinlan', '13888888888', '123456')" | python manage.py shell &> /dev/null
# 启动supervisor
supervisord -c supervisor.conf
删除之前创建的容器,我们重新通过dockerfile去新创建一个。
首先构建镜像:
# -t:给镜像加个tag
docker build -t ck13_django_img .
需要等一会儿~好了之后创建一个容器:
docker run --name ck13_django --network ck13 -e ENV=production -p 9321:8000 -v ck13_log:/app/logs --restart=always -d ck13_django_img
如果有啥问题可以使用下面命令去查日志:
docker logs ck13_django