docker简单部署Django项目实例
作者:沉觞流年
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 种网络模式:
- bridge 模式,使用
--net=bridge指定,默认设置。 - host 模式,使用
--net=host指定。 - container 模式,使用
--net=container:NAMEorID指定。 - none 模式,使用
--net=none指定。
通过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相关网络命令
- 查看所有docker网络
docker network ls - 创建网络
docker network create 网络名 - 查看网络信息
docker network inspect 网络名 - 加入网络
docker network connect 网络名 容器名 - 移除网络
docker network remove 网络名(当前网络下没有挂载容器) - 移除网络下的容器
docker network disconnect 网络名 容器名
容器通信
容器通信可以采用的有四种方案:
- 通过容器 IP 访问:容器重启后,IP 会发生变化,比较麻烦。
- 通过宿主机的 ip:port 的方式访问:如果宿主机 IP 改变,就得每个应用都得改一遍,并且还要绑定端口,麻烦。
- 通过 link 建立链接:相互依赖的太紧,不利于维护。
- 自定义 network: 在同一个桥接网络中的容器可以相互访问,即使切换了宿主机,也不影响,因为可以通过容器名来表示对方的IP。
通过容器 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_nginx和djangoenv容器
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
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
