使用Docker部署Django应用的过程和心得


之前部署Web应用,没用docker,直接在服务器上部署,使用了django+nginx+supervisor+gunicorn部署博客应用。但后来了解了docker,为其“Build,Ship and Run Any App,Anywhere”的思想所折服,觉得这个太牛逼了,所以我也尝试一下自己用docker部署Web应用。本篇文章为了记录我用docker部署web应用的过程和心得。

Django常见的两种部署方式:

  1. Django + Nginx + uWSGI

  2. Django+ Nginx + Gunicorn

采用用 uWSGI 配合 Nginx的部署方式

构建的容器:

  1. Django+nginx+uwsgi 容器 (dockerfiles/django-uwsgi-nginx)
  2. MySQL容器 (mysql:5.6)

 

下载好镜像, 就是要运行容器. 在这之前需要为容器自定义创建专属网络

1.创建专属网络

docker network create django_network

 

后面的服务都会使用这个专属网络进行通信,主机名就是域名地址,通信地址直接填主机名,docker提供了域名解析,所以我settings.py的数据库配置如下:

# 配置mysql
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'djmyblog',
        'USER': '用户',
        'PASSWORD': '密码',
        'HOST': 'django_mysql',  # 这就是数据库容器名  通过域名解析
        'PORT': '端口',
    }
}

2.部署Mysql

docker run -d -p 3307:3306 --network django_network --name django_mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.6
# 说明下参数意义
# -p 映射端口:docker内部端口: 端口映射,只有将容器端口映射到外部,外部才能访问
# -e 环境变量,指定一些服务内读取的变量,以初始化服务,这里的变量意义从字面上不难理解
# --network 指定容器所在网络,需要互相访问的容器记得指定到同一个网络!
# --name 容器名,这个名字在同一个容器网络里是可以直接当成域名访问的!

3.部署web服务

 docker run -d --network django_network --name django_web -p 80:80 -p 443:443 -v /home:/home  dockerfiles/django-uwsgi-nginx
# 说明下参数意义
# -p 映射端口:docker内部端口: 端口映射,只有将容器端口映射到外部,外部才能访问
# -v 数据卷,可以将主机上的某个目录与容器的某个目录关联起来,容器上的挂载点下的内容就是主机的这个目录下的内容
# --network 指定容器所在网络,需要互相访问的容器记得指定到同一个网络!
# --name 容器名,这个名字在同一个容器网络里是可以直接当成域名访问的!

4.Nginx配置(nginx目录)

 

接下是配置 Nginx 来处理用户请求。

先在服务器的 /etc/nginx/sites-available/ 目录下新建一个配置文件,文件名我一般就设置为域名。写上下面的配置内容:

server {
        charset utf-8;
        listen 80;
        server_name blog;

        location /static {
                # 写静态文件夹路径
                alias /home/django-blog/blogproject/static;
        }
        location /media {
                # 上传图片路径
                alias /home/django-blog/blogproject/media;
        }
        location / {
                proxy_set_header Host $host;
                proxy_pass http://0.0.0.0:8000;
                 # 设置请求头,传递原始请求ip给 gunicorn 服务器
                proxy_set_header X-Real-IP $remote_addr;
        }
        location /static/look_girl_models {
                 add_header Access-Control-Allow-Origin https://paugram.com;
        }

        location ~ .*\.(js|css|png|jpg|gif)$ {
                root /home/django-blog/blogproject; #站点根目录
                if (-f $request_filename) {
                    expires 1d;
                break;
                }
        }

}

在 /etc/nginx/sites-available/ 放置了配置文件,接下来需要创建一个符号链接,把这个配置文件加入到启用的网站列表中去,被启用网站的目录在 /etc/nginx/sites-enabled/,你可以理解为从 sites-available/ 目录下发送了一个配置文件的快捷方式到 sites-enabled/ 目录。具体命令如下:

sudo ln -s /etc/nginx/sites-available/myblog /etc/nginx/sites-enabled/myblog

5. 使用 Gunicorn

Gunicorn 一般用来管理多个进程,有进程挂了Gunicorn 可以把它拉起来,防止服务器长时间停止服务,还可以动态调整 worker 的数量,请求多的时候增加 worker 的数量,请求少的时候减少。

安装 Gunicorn:

pip install gunicorn

用 Gunicorn 启动服务器进程:

# 需要在项目目录下
gunicorn --bind 0.0.0.0:8000 blogproject.wsgi:application

6. 进程管理工具 Supervisor 

supervisor-app.conf 配置信息

# gunicorn
[program: gunicorn-app]
# 项目目录
directory = /home/django-blog/blogproject
# 命令
command = nohup gunicorn --bind 0.0.0.0:8000 blogproject.wsgi:application  > /dev/null 2>&1

# nginx
[program:nginx-app]
command = /usr/sbin/nginx

7. 运行项目

# 这时候你可以使用supervisorctl命令
supervisorctl start all

# 查看运行状态命令 
supervisorctl status
#gunicorn-app                     RUNNING   pid 128, uptime 0:45:08
#nginx-app                        RUNNING   pid 129, uptime 0:45:08

这里为什么要使用Supervisor, 因为以后每次部署项目就不需要在运行各个组件. 只需要一个命令就可以将项目起来, 很方便.

 

部署的时候踩的坑的问题

docker 容器中乱码解决办法(真实解决!!!) 

进入web容器找到项目, 在运行web是报错了, settint.py文件里的中文注释全部乱码

解决方法:

LANG=C.UTF-8

然后再激活:

source /etc/profile 

然而实际上这样显示是没有出问题了,但是我的hdfs命令却失效了!!!

提示command not find

然而发现不使用激活环境激活语句,直接也就可以看到中文正常显示了,或者使用这样进行环境变量的设置:

export LANG=C.UTF-8

但是有个问题就是每次进入容器都要执行一次 export LANG=C.UTF-8 确实很麻烦

这里就需要修改Linux的配置文件 

.bashrc             当你登入shell时执行

需要vim添加 .bashrc 文件

# vim打开配置文件
vim ~/.bashrc  


# 在文件最后添加
​export LANG=C.UTF-8

​