Django-Docker容器化部署:Django-Docker-MySQL-Nginx-Gunicorn云端部署

docker简介

目的:可以简单理解为开发人员干了运维的活,开发人员在自己的机器上可以跑,发给运维后,运维却跑不起来。
原因:运维在自己的机器上没有相应的环境和配置。
解决:开发人员将项目的源码以及相对应的环境和配置一起打包给运维。

以上这个流程大概就是docker所做的事情。
在简单一点理解,比如,去鱼店买了一条金鱼,带回家后自己养就死了。那直接把鱼店的水,水草,装饰等一起带回家,就可以养活。


docker简单理解为:一个微量的Linux系统。大概170M左右把,VM虚拟机都4G差不多。

docker三大概念:
镜像:保存在仓库中,比如nginx镜像,redis镜像。
容器:是一个个的镜像实例。相当于一个简易版的Linux环境。
仓库:保存各种镜像,需要的时候直接去拉取。相当于github一样。

简单理解:
	容器相当于类,镜像相当于类的实例对象。
	
	
总结:
	我们把应用程序和项目依赖配置打包形成一个完整的运行环境,这个打包好的运行环境就可以看作是一个镜像文件。只有通过这个镜像文件才能生成Docker容器。镜像文件可以看作是容器的模板。Docker根据镜像文件生成容器的实例。同一个镜像文件,可以生成多个同时在运行的容器实例。	

创建Django项目

在Linux终端中
1.安装Django库
$ pip install django==2.2

2.在一个你喜欢得位置(比如/home/)创建新的 Django 项目
$ django-admin startproject django_app

3.进入项目根目录:
$ cd django_app

注:后面的所有内容全部都在此目录中操作!

4.迁移数据
$ python manage.py migrate

####用Docker构建项目

1.首先确认安装好了docker,安装过程百度
可以使用查看: 
$ docker run hello-world

Unable to find image 'hello-world:latest' locally
...
latest: Pulling from library/hello-world
1b930d010525: Pull complete 
...

Hello from Docker!
This message shows that your installation appears to be working correctly.

2.docker images 查看本地已有的镜像:
$ docker images

REPOSITORY      TAG        IMAGE ID           CREATED           SIZE
hello-world     latest     fce289e99eb9       9 months ago      1.84kB

3.查看本地已有的容器:
$ docker ps -a

CONTAINER ID   IMAGE        ..   CREATED         ..
38cb03a96dca   hello-world  ..   2 minutes ago   ..

4.其他基础命令:
docker rmi [images ID]  # 删除此 ID 的镜像
docker container stop [container ID]  # 停止此 ID 的容器
docker container start [container ID]  # 启动此 ID 的容器
docker container rm [container ID]  # 删除此 ID 的容器

Dockerfile

以下正式开始构建Django容器
Dockerfile
Docker 允许通过文本格式的配置文件来构建镜像,默认名称为 Dockerfile。因此在项目根目录新建文件 Dockerfile,写入:

# 从仓库拉取 带有 python 3.7 的 Linux 环境
FROM python:3.7

# 设置 python 环境变量
ENV PYTHONUNBUFFERED 1

# 创建 code 文件夹并将其设置为工作目录
RUN mkdir /code
WORKDIR /code
# 更新 pip
RUN pip install pip -U
# 将 requirements.txt 复制到容器的 code 目录
ADD requirements.txt /code/
# 安装库
RUN pip install -r requirements.txt
# 将当前目录复制到容器的 code 目录
ADD . /code/

目前项目依赖的唯一库就是 Django,所以在项目根目录创建 requirements.txt 并写入:
django==2.2

注意:前面不是已经安装过 Django 了吗,为什么这里还要安装?原因是前面是在宿主机安装的,容器里是没有 Django 的!

所以目前的文件结构如下:
django_app
  - Dockerfile
  - requirements.txt
  - manage.py
  - django_app
  - db.sqlite3
  
配置文件就写好了,接下来看看 Docker-compose 怎么用。

Docker-compose

在线上环境中,通常不会将项目的所有组件放到同一个容器中;更好的做法是把每个独立的功能装进单独的容器,这样方便复用。比如将 Django 代码放到容器A,将 Mysql 数据库放到容器B,以此类推。

因此同一个服务器上有可能会运行着多个容器,如果每次都靠一条条指令去启动,未免也太繁琐了。 Docker-compose 就是解决这个问题的,它用来编排多个容器,将启动容器的命令统一写到 docker-compose.yml 文件中,以后每次启动这一组容器时,只需要 docker-compose up 就可以了。因此教程也会用 docker-compose 来管理容器。

首先确认 docker-compose 是否安装成功:
$ docker-compose -v
docker-compose version 1.24.1, build 4667896b

确认无误后,在项目根目录创建 docker-compose.yml 并写入:
version: "3"
services:
  app:
    restart: always
    build: .  # '点'代表当前目录
    command: "python3 manage.py runserver 0.0.0.0:8000"
    volumes:
      - .:/code
    ports:
      - "8000:8000"
      
配置就写好了。现在项目的目录结构如下: 
django_app
  - docker-compose.yml
  - Dockerfile
  - requirements.txt
  - manage.py
  - django_app
  - db.sqlite3     

测试

输入指令 docker-compose up 启动容器服务:
$ docker-compose up

Creating network "django_app_default" with the default driver
Building app
Step 1/8 : FROM python:3.7
3.7: Pulling from library/python
4a56a430b2ba: Pull complete
...
6933d3d46042: Pull complete
Digest: sha256:0f0e991a97426db345ca7ec59fa911c8ed27ced27c88ae9966b452bcc6438c2f
Status: Downloaded newer image for python:3.7
 ---> 02d2bb146b3b
Step 1/8 : FROM python:3.7
 ---> 02d2bb146b3b
...
Step 7/8 : RUN pip install -r requirements.txt
 ---> Running in 62a60a3003fe
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Collecting django==2.2 (from -r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/54/85/0bef63668fb170888c1a2970ec897d4528d6072f32dee27653381a332642/Django-2.2-py3-none-any.whl (7.4MB)
...
Installing collected packages: sqlparse, pytz, django
Successfully installed django-2.2 pytz-2019.2 sqlparse-0.3.0
...
Step 8/8 : ADD . /code/
 ---> cb23f483ffb6
Successfully built cb23f483ffb6
Successfully tagged django_app_app:latest
WARNING: Image for service app was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating django_app_app_1 ... done
Attaching to django_app_app_1
app_1  | Watching for file changes with StatReloader
app_1  | Performing system checks...
app_1  | 
app_1  | System check identified no issues (0 silenced).
app_1  | October 05, 2019 - 15:03:15
app_1  | Django version 2.2, using settings 'django_app.settings'
app_1  | Starting development server at http://0.0.0.0:8000/
app_1  | Quit the server with CONTROL-C.


可以看到 Docker 按照配置文件的要求,成功构建了镜像及容器,并启动了容器。

打开浏览器,输入本地 IP 端口 127.0.0.1:8000

下载太慢?

由于众所周知的原因,国内的网络环境非常复杂。在构建镜像时经常需要从国外的远程仓库拉取资源,岿然不动的下载速度真的头疼。

解决方法就是将资源拉取链接修改为国内的镜像源,比如清华的镜像源。

修改 Dockerfile 如下:
FROM python:3.7
ENV PYTHONUNBUFFERED 1

# 添加 Debian 清华镜像源
RUN echo \
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster main contrib non-free\
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster-updates main contrib non-free\
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster-backports main contrib non-free\
deb https://mirrors.tuna.tsinghua.edu.cn/debian-security buster/updates main contrib non-free\
    > /etc/apt/sources.list

RUN mkdir /code
WORKDIR /code
# 添加 pip 清华镜像源
RUN pip install pip -U -i https://pypi.tuna.tsinghua.edu.cn/simple
ADD requirements.txt /code/
# 添加 pip 清华镜像源
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
ADD . /code/s

Django-Docker容器化部署:Django-Docker-MySQL部署

上面我们成功搭建了容器化的 Django 项目,用到的数据库为默认的 Sqlite。Sqlite 虽然简单易用,但是线上部署时通常会选择更高效、更可靠的数据库,比如 MySQL。

本例使用两个容器:
名称叫 app 的 Django 容器
名称叫 db 的 MySQL 容器

所以如何构建 MySQL 镜像?别担心,这么常用的镜像官方已经帮你构建好了,只需要把它从仓库拉取到本地就可以了。

修改上面写的 docker-compose.yml ,增加 MySQL 容器:
version: "3"
services:
  app:
    restart: always
    build: .
    command: bash -c "python3 manage.py migrate && python3 manage.py runserver 0.0.0.0:8000"
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db
  db:
    image: mysql:5.7
    volumes:
      - "./mysql:/var/lib/mysql"
    ports:
      - "3306:3306"
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=mypassword
      - MYSQL_DATABASE=django_app



接下来修改 Dockerfile :
FROM python:3.7
ENV PYTHONUNBUFFERED 1

# 添加这两行
RUN apt-get update
RUN apt-get install python3-dev default-libmysqlclient-dev -y

RUN mkdir /code
WORKDIR /code
RUN pip install pip -U
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/

其他配置
修改 requirements.txt ,增加 MySQL 驱动:
django==2.2
mysqlclient==1.3.14

然后还需要修改 django_app/settings.py ,将数据库设置为 MySQL:
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django_app',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': 'db',
        'PORT': '3306',
    }
}

测试
测试之前,请先确认没有其他程序占用了 3306 端口,比如宿主机安装的 MySQL。
重新生成镜像:
$ docker-compose build

生成并启动容器:
$ docker-compose up

打开浏览器访问 127.0.0.1:8000

Django-Docker容器化部署:Django-Docker-MySQL-Nginx-Gunicorn云端部署

上面我们实现了在 Docker 中添加了 MySQL 数据库,但采用的开发服务器虽然使用便捷,但性能差、可靠性低,无法应用在生产环境中。
本节将实现 Docker + Django + MySQL + Nginx + Gunicorn 容器项目,完成最终的服务器部署。

Docker-compose

在部署到服务器之前,先来尝试本地部署。

在上一章的基础上,继续修改 docker-compose.yml 配置:
version: "3"

services:
  app:
    restart: always
    build: .
    command: bash -c "python3 manage.py collectstatic --no-input && python3 manage.py migrate && gunicorn --timeout=30 --workers=4 --bind :8000 django_app.wsgi:application"
    volumes:
      - .:/code
      - static-volume:/code/collected_static
    expose:
      - "8000"
    depends_on:
      - db
    networks:
      - web_network
      - db_network
  db:
    image: mysql:5.7
    volumes:
      - "./mysql:/var/lib/mysql"
    ports:
      - "3306:3306"
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=mypassword
      - MYSQL_DATABASE=django_app
    networks:
      - db_network
  nginx:
    restart: always
    image: nginx:latest
    ports:
      - "8000:8000"
    volumes:
      - static-volume:/code/collected_static
      - ./config/nginx:/etc/nginx/conf.d
    depends_on:
      - app
    networks:
      - web_network

networks:
  web_network:
    driver: bridge
  db_network:
    driver: bridge

volumes:
  static-volume:

其他配置

首先修改 Nginx 的配置文件,即映射到 nginx 容器的 config/nginx/django_app.conf :
upstream app {
  ip_hash;
  server app:8000;
}

server {
  listen 8000;
  server_name localhost;

  location /static/ {
    autoindex on;
    alias /code/collected_static/;
  }

  location / {
    proxy_pass http://app/;
  }
}
此配置下 Nginx 会监听容器的 8000 端口,并将收到的请求发送到 app 容器(静态文件请求除外)。

在 requirements.txt 文件中增加 gunicorn 库:
django==2.2
mysqlclient==1.3.14
gunicorn==19.9.0

最后修改 django_app/settings.py 的域和静态文件存放目录的配置:
...

ALLOWED_HOSTS = ['*']

...

STATIC_ROOT = os.path.join(BASE_DIR, 'collected_static')
STATIC_URL = '/static/'

所有配置就完成了

测试

测试指令就一条:$ docker-compose up
浏览器访问 127.0.0.1:8000

本地部署成功,下一步服务器部署。

服务器部署

有了本地部署的经验,服务器部署就非常非常简单了。

还是类似的,部署前将 Docker 、 Docker-compose 、 Python3 等工具在服务器上安装好;将项目用 Git 克隆到服务器本地。

接下来把 settings.py、config/nginx/django_app.conf、requirements.txt 相关位置都按教程流程改好;将 docker-compose.yml 和 Dockerfile 复制到服务器。

由于 http 请求默认为 80 端口,所以为了接收公网请求,还需要做一点点修改 docker-compose.yml 的工作:
version: "3"

services:
  app:
    ...
    command: bash -c "... your_project_name.wsgi:application"  # 改为你的项目名称
    ...
  db:
    ...
  nginx:
    ...
    ports:
      - "80:8000"  # 监听 80 端口
    ...

networks:
  ...

volumes:
  ...
  
修改 Gunicorn 绑定的项目名称,以及让宿主机监听公网 http 默认的 80 端口。

此外还要修改 config/nginx/django_app.conf :
upstream your_domain_name {
  ip_hash;
  server app:8000;
}

server {
  ...

  location / {
    proxy_pass http://your_domain_name/;
  }
}

最后,记得将 settings.py 中的 DEBUG 配置修改好:
# DEBUG=True 注释掉
DEBUG=False

这样就可以了!构建镜像并启动容器:
$ docker-compose up

在浏览器中就可以正常访问你的网站了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值