docker

关注公众号 jb51net

关闭
首页 > 网站技巧 > 服务器 > 云和虚拟化 > docker > docker简单部署Django项目

docker简单部署Django项目实例

作者:沉觞流年

使用Docker部署Django项目需配置Nginx和uWSGI,注意端口冲突并禁用宿主机原有服务,通过自定义bridge网络实现容器间通信,挂载静态文件目录,利用脚本简化部署流程,确保容器与宿主机网络隔离且可互相访问

docker简单部署Django项目

使用docker配置项目,不能与宿主机本身的nginx服务、uWSGI等服务起冲突,可以先将宿主机上的这些服务先禁用,仅通过docker来配置对应的服务;若不想在禁用原有的服务的情况下,需注意端口不要有冲突

docker配置nginx服务

docker拉取nginx镜像docker pull nginx

以挂载目录的方式启动Nginx,将项目静态文件夹挂载到docker_nginx容器下的/usr/share/nginx/html目录下

docker run \
 --name=docker_nginx \
 --privileged=true \
 -v /data/pythonProject/autotpsite/dist:/usr/share/nginx/html \
 -p 8080:80 \
 -d \
 nginx

--privileged=true 关闭安全权限,挂载多个目录时,容器操作文件夹会没有权限

如果该容器仅是一次性使用,可以加上--rm参数

通过访问服务器IP:8080即可查看到对应的静态目录文件

通过docker cp命令,将容器中的nginx的配置文件/etc/nginx拷贝到到宿主机上/data/nginx/conf,方便后续修改,因为容器内没有vi命令不方便修改。

docker cp docker_nginx:/etc/nginx /data/nginx/conf

docker配置后台服务

修改uwsgi配置文件

[uwsgi]
chdir =./
// 项目根目录,配置文件处于项目根目录,因此设置为相对路径即可,复用性更高
module = autotpsite.wsgi:application
// 指定wsgi模块下的application对象
socket = 0.0.0.0:8888
//Nginx使用uwsgi_pass做方向代理时 需要设置成socket
master = true
// 主进程
pidfile = uwsgi8888.pid
// pid 文件,用于脚本启动,停止该进程
daemonize = uwsgi_server.log
// 日志文件
enable-threads = true
// 新增配置--允许多线程
buffer-size = 40960
// 设置请求头最大字节数,用于socket模式

因为容器之间通信协议是http,而之前的nginx是通过socket进行通信,所以这里需要进行修改

[uwsgi]
chdir = ./
// 项目根目录,配置文件处于项目根目录,因此设置为相对路径即可,复用性更高
module = autotpsite.wsgi:application
// 指定wsgi模块下的application对象
http = 0.0.0.0:8888
//对本机8888端口提供服务
master = true
// 主进程
pidfile = ./uwsgi8888.pid
// pid 文件,用于脚本启动,停止该进程
daemonize = ./uwsgi_server.log
// 日志文件,只记录错误信息
disable-logging = true
socket-timeout=10

python容器操作

部署测试平台后台服务 Django+uwsgi

首先服务都依赖Python3.8,所以需要拉取镜像docker pull python:3.8

启动容器-挂载后端目录-无需配置映射端口

docker run \
-it \
-v /data/pythonProject/autotpsite:/opt \
-p 8888:8888 \
--name djangoenv \
-d \
python:3.8

进入容器

docker exec -it djangoenv bash

执行cd /opt命令进入容器挂载的opt目录下,执行ls命令,可以发现,opt目录下的文件,与宿主机/data/project/autotpsite目录下的文件是一致的

安装虚拟环境

执行安装库操作

如果是Pipfile文件,需要通过pipenv命令进行安装对应的库,则需要先安装pipenv,不过这种方式需要python版本与Pipfile文件中的python版本一致

pip install pipenv -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

如果是通过requirements.txt文件的,则执行pip命令安装对应的库即可

pip install -r requirements.txt -i 
http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

如果换源方式下载库异常,可以配置pip.conf文件

mkdir -p /root/.config/pip && touch /root/.config/pip/pip.conf && echo "
[global]\ntimeout = 60\nindex-url = https://pypi.doubanio.com/simple\ntrusted-host = pypi.doubanio.com" > /root/.config/pip/pip.conf

执行命令python manage.py runserver,测试一下能否正常启动,注意配置文件的数据库 IP是否正确,否则可能连接不上

安装uWSGI服务

安装uWSGI服务

pip install uwsgi -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

执行uwsgi uwsgi.ini命令启动uWSGI,可通过ps -ef |grep uwsgi命令查看进程是否启动成功,通过tail -100f uwsgi_server.log命令查看是否有异常日志

脚本一键部署

为了下次方便随时启动新容器,可以把容器内部的操作写成shell ,执行vim auto_deploy.sh命令,编写脚本文件

auto_deploy.sh

cd opt/ && pip install -r requirements.txt -i http://pypi.douban.com/simple/ --
trusted-host pypi.douban.com && pip install uwsgi -i 
http://pypi.douban.com/simple/ --trusted-host pypi.douban.com && uwsgi uwsgi.ini 
&& tail -f > /dev/null

将文件保存到宿主机的对应/data/project/autotpsite目录下

下次重启启动容器时,可以带上该脚本文件进行执行,就不用再手动输入命令去安装虚拟环境和uWSGI服务了

docker run \
-it \
-p 8888:8888 \
-v /data/pythonProject/autotpsite:/opt \
--name djangoenv \
-d \
python:3.8 \
sh /opt/auto_deploy.sh

可通过docker logs -f djangoenv查看容器运行的日志情况

修改nginx配置

修改nginx的配置文件,前面映射.出来了,所以不用进入容器内部去修改了,直接在宿主机下修改/data/nginx/conf目录下,找到对应的配置文件进行修改即可/conf.d/default.conf,执行命令vim default.conf编辑配置文件,在server块中添加下方内容

location ~/(api/|jira/) {
    proxy_pass    http://192.168.119.70:8888;
    # proxy_pass    http://127.0.0.1:8888;
}

重启nginx容器

docker restart docker_nginx

其中192.168.119.70:8888为宿主机的ip+端口,该种方式是通过nginx访问宿主机的方式来访问对应的docker后台服务djangoenv,如果前端页面接口返回正常信息,说明使用docker部署Django后台服务成功

docker网络配置

proxy_pass设置为http://127.0.0.1:8888无法访问,是因为容器的网络是和主机隔离的,有自己的一套网络

docker网络知识

查看主机的网络发现有个docker0网卡,这个是docker使用的网卡,docker就通过这个网卡来进行网络通信。

[root@localhost ~]# ip addr
# 其他网卡
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
group default
   link/ether 02:42:f6:c3:5a:f4 brd ff:ff:ff:ff:ff:ff
   inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
   inet6 fe80::42:f6ff:fec3:5af4/64 scope link

docker run 创建 Docker 容器时,可以用 --net 选项指定容器的网络模式,Docker 有以下 4 种网络模式:

通过docker network ls命令可查看容器有哪些网络

[root@localhost ~]# docker network ls
NETWORK ID     NAME     DRIVER   SCOPE
9f606136c768   bridge   bridge   local
c7fca13d33a9   host     host     local
b590d278d4b1   none     null     local

默认情况容器是挂载在bridge网络的,所以可以查看bridge网络的信息,查询到相关容器的内部IP,让后通过内部IP互相访问。

执行docker network inspect bridge命令查看docker容器网络信息

# ....其他信息.....
"Containers": {
            "3220d0e521dc0d9ed1e62bbf06f3db6d13722878fd64162f24013f9a876e902b": {
                "Name": "docker_nginx",
                "EndpointID": "9a167c7df70e7259ea01467edc0527a4f7b6f8a72791c22b894b26a91fc52e44",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            },
            "671b14ffd0a9d92af2b30d3220b046934422307c9353f929f980f6042ce548c6": {
                "Name": "djangoenv",
                "EndpointID": "da589a787022042ed23ca33442fab05a8edaafaafe2c6e5fb69a727ee1092aaa",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            }
        },

这里可以看到后台服务djangoenv的IP是172.17.0.3/16,将nginx配置文件default.conf中的127.0.0.1改为172.17.0.3

location ~/(api/|jira/) {
    # proxy_pass    http://192.168.119.70:8888;
    proxy_pass    http://172.17.0.3:8888;
    # proxy_pass    http://127.0.0.1:8888;
}

重启nginx服务后,接口依旧不会报错,这是属于bridge网络模式下容器之间互相通信的一种配置方式

docker restart docker_nginx

bridge模式

bridge 模式是 Docker 默认的网络设置,此模式会为每一个容器分配 Network Namespace、设置 IP 等,并将一个主机上的 Docker 容器连接到一个虚拟网桥上。

当 Docker server 启动时,会在主机上创 建一个名为 docker0 的虚拟网桥,此主机上启动的 Docker 容器会连接到这个虚拟网桥上。虚拟网桥的 工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。

接下来就要 为容器分配 IP 了,Docker 会从 RFC1918 所定义的私有 IP 网段中,选择一个和宿主机不同的IP地址和 子网分配给 docker0,连接到 docker0 的容器就从这个子网中选择一个未占用的 IP 使用。

如一般 Docker 会使用 172.17.0.0/16 这个网段,并将 172.17.42.1/16 分配给 docker0 网桥(在主机上使用 ifconfig 命令是可以看到 docker0 的,可以认为它是网桥的管理接口,在宿主机上作为一块虚拟网卡使用)

host 模式

如果启动容器的时候使用 host 模式,那么这个容器将不会获得一个独立的 Network Namespace,而是和宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口。

例如,我们在 10.10.101.105/24 的机器上用 host 模式启动一个含有 web 应用的 Docker 容器,监听 tcp 80 端口。当我们在容器中执行任何类似 ifconfig 命令查看网络环境时,看到的都是宿主机上的信 息。而外界访问容器中的应用,则直接使用 10.10.101.105:80 即可,不用任何 NAT 转换,就如直接跑 在宿主机中一样。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。

container 模式

这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。

同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。

none模式

这个模式和前两个不同。在这种模式下,Docker 容器拥有自己的 Network Namespace,但是,并不为 Docker容器进行任何网络配置。也就是说,这个 Docker 容器没有网卡、IP、路由等信息。需要我们自己为 Docker 容器添加网卡、配置 IP 等。

docker相关网络命令

容器通信

容器通信可以采用的有四种方案:

通过容器 IP 访问,作为写死的IP一旦容器重启就失效了,因此只作为临时调试方案。第二种 和第三种也太麻烦不用。

采用第四种自定义network方案,实现容器互相通信。采用的是bridge网络驱动模式,这个是docker默认的网络驱动模式,安全性高,性能好。

1、首先创建自定义网络

docker network create -d bridge mynetwork

默认是bridge驱动模式,所以也可以简写成

docker network create mynetwork

2、将将Nginx和Django后端项目容器加载到新网络中,注意容器只能同时存在1个网络中,即从默认的网络重新挂载到新建的网络上。

docker network connect mynetwork docker_nginx

docker network connect mynetwork djangoenv

为了不受到bridge网络下的影响,先移除在bridge驱动模式网络下的docker_nginxdjangoenv容器

docker network disconnect bridge docker_nginx

docker network disconnect bridge djangoenv

此时执行docker exec-it docker_nginx bash 命令进入docker_nginx容器,尝试用后端的容器名进行通信

curl http://djangoenv:8888/index.html

3、修改nginx配置文件,对server块内容进行修改

location ~/(api/|jira/){
     proxy_pass     http://djangoenv:8888;
 }

重启nginx服务,接口依旧不会报错,

docker restart docker_nginx

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文