四十四、docker手动部署后端

一、项目框架图

 首先创建一个桥接网络:

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地址去拉取项目,发现没有配公钥,还得配下公钥。

生成/添加SSH公钥 - Gitee.com

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值