初体验!!!——关于在Docker中部署Django这件事

呕心沥血的第一篇学习相关博文


下载和安装Docker

家庭版windows似乎不能直接安装,因为不能支持hyper-V,而我又恰好是家庭版,只能被迫安装toolbox。

但是!为了不安装toolbox(不知道为什么有这份坚持)我特意去某宝花了15买了一个家庭版升级专业版的产品序列号,然后升级完发现是未激活状态,这种事情怎么能忍!于是果断挂vpn连校园网下载正版破解软件(挂vpn的时候一定要记得关代理!!我开着全局代理挂vpn失败了十几分钟还找不到原因,真的是人类迷惑行为)

下面放一张激活后的截图

计算机基本信息

接着,上老师给的网站下载Docker for windows

下载Docker

然后安装,安装之前记得打开计算机的Hyper-V选项

开启Hyper-V

验证是否安装完成 ,在命令行中输入Docker -v,发现有如下输出,说明安装成功

docker -v

第一步——拉取并运行 hello-world

到了这一步,我们首先要明确三个概念:层(layer)、镜像(image)和容器(container)

以下内容参考链接 https://www.cnblogs.com/bethal/p/5942369.html

实际上Docker的层(Layer)可以视为是按照Dockerfile中指定的方式叠加到旧镜像上去的镜像,每安装一个软件,就在现有的镜像的基础上增加一层。

镜像

镜像(Image)就是一堆只读层(read-only layer)的统一视角,也许这个定义有些难以理解,下面的这张图能够帮助读者理解镜像的定义。

从左边我们看到了多个只读层,它们重叠在一起。除了最下面一层,其它层都会有一个指针指向下一层(下面的图更清晰地展现出这一特征)。这些层是Docker内部的实现细节,并且能够 在运行Docker的文件系统上访问到。

右边的图像展现出统一文件系统(union file system)的视角,该技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。

容器

容器(container)的定义和镜像(image)几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。

在运行Docker create命令之后,容器=镜像+读写层。并且容器的定义并没有提及是否要运行容器。(即:create但未run的容器也是容器)虽然我们经常说的容器就指运行中的容器,但是那种应该叫做运行态容器。

当运行Docker commit命令之后,会将该容器内的读写层转化为一个可读层,如此该容器便成为了一个不可修改的镜像文件了
而所谓Docker built的过程即是对Dockerfile中命令的逐条run和commit,如此反复生成一个镜像

OK,知识基础完毕,回到实验中,输入docker images,查看当前Docker中的镜像

docker images1

表明目前Docker中没有镜像,根据ppt上的提示,我们先拉取一个hello-world镜像

哦对了,在拉取之前记得换源(换代理应该也行,我后面会提到换代理的事情)

更改镜像源
docker pull hello-world

这时如果查看Docker images将得到如下的反馈

docker images2

说明拉取成功

然后使用run命令使之运行起来

(如绿框中所示,向我们展示了这个镜像是来自哪里、怎么被包装、走得哪个路口最后送到我们面前的,追根溯源、吃得放心(误))

出现如上反馈,表示镜像(应该说是容器)运行成功!


在本地部署好一个django项目

这里我选择的是我个人博客的主页来做django框架的内容(只做框架不配置服务器了),如下所示

个人主站
ctrl+s下载下来html页面,保留其中的链接,修改不需要的部分(比如绿框中所示,因为我的博客是由wordpress生成的,单纯下载由php生成的静态html网页的话使用起来会有错误)

下载后的html文件会带有一个“xxx_file”文件夹,其中包含html文件中链接的css、js和图片等资源文件。

在拥有静态网页之后,在本地命令行中使用django-admin startproject命令新建一个django项目,设该项目的root路径为./,新建文件夹./template,将刚刚下载的静态页面放进去。在一系列操作结束之后,用tree /f >> tree.txt 命令获取文件结构如下

./
│ db.sqlite3
manage.py
│ tree.txt

├─.idea(内含pycharm编译器对django项目的描述,略)

├─templates(自己新建的,里面放刚刚下载的静态页面)
│ │ 1.html
│ │
│ └─1_files(内含1.html中所链接的css、js、图片等资源文件,略)

└─wzy2017211900
 │ asgi.py
 │ settings.py
 │ urls.py
 │ view.py
 │ wsgi.py
 │ __init__.py
 │
 └─__pycache__(内含编译后的python文件,略)

(文件树前空一行的表示文件夹,标注粗体的是待会需要修改的部分)

修改settings

此时先修改settings.py,改变页面模板的加载root路径(应该只需要添加或更改绿框中那一行)

修改view

修改view.py,如下所示(这里不细讲django的运行机制了,其实应该从urls.py改起,但是由于这里只用这一个页面所以一切从简了)

好,我们现在有了一个只有一个页面的简单django项目了

但是注意,这时如果直接启动Django访问页面的话看到的应该是如下的样子:

链接失效的项目

这里显然是html文件无法链接到它的资源文件

(注:这里能链接上这个大图图片的原因,经过我使用F12审查元素大法查看之后,似乎是因为这个图片本身就是一个指向我博客的图床的链接,并不是从本地资源文件中打开的(本地资源文件中也没有),而是在打开网页的时候从我博客的图床上加载上去的,所以这里的路径问题影响不到它,作为对比,可以看见该网页的网页图标(绿框中所示)是没有图片显示的,这个显然就是资源文件没有链接的现象。)

向settings中添加静态文件路径

上网查阅资料之后得知django中的资源文件需要在setting.py中声明静态资源文件存放处,不然傻傻的django会找不到路径,如下所示:

然后修改1.html中的链接格式,主要有两点,一是在文件中添加

{% load static %}

二是将连接资源文件的路径从

“xxxx/templates/1_files/wangziyu.css”格式

改成

“{% static “wangziyu.css” %}”格式

(wangziyu.css只是举个栗子,而且这里用pycharm或者vscode自带的ctrl+f的正则模式就很好批量替换处理了)

如上述方法,不用很仔细看页面内容就能将一个下载下来的静态html改成符合Django框架的样子。

最后所得结果如下所示:

本地django部署完毕

good!


在Docker中构建基础环境

做完上面一步也别忘记我们的最终目的:将django项目部署到Docker中去。所以我们这一步要先在Docker中搭建好基础设施(我一开始以为只需要下载个django就可以了,最后结果发现这个Docker拉取下来的ubuntu镜像是真nmd空荡荡啊!)

大家应该还记得在第2步的hello-world中有这样一句:

ambitious!

恰好我王某人就很ambitious!(而且单用Dockerfile跑django似乎有点束手束脚,一旦有个地方出错了都不好控制)

说个题外话,-it实际上是-i和-t两个option的合写(因为这俩经常一起用),-i指采用交互模式运行容器,-t指在伪终端中运行容器,除此之外后面还会用到:-v :挂载盘符,-p:端口映射。其余的option详见百度。

docker run -it ubuntu bash走起!

docker run -it ubuntu bash

接下来就是下载各种包配置各种环境,在配置之前我们先挂一个代理防止配置过程中网络出错(我这里使用的代理是v2rayN)

打开任务管理器,看看我们可爱的代理程序的PID号(那个v2ray_privoxy.exe就是):2080

查看代理PID

然后新建一个cmd,查看PID为2080的进程占用了哪个端口号:1081

填入代理

最后在Docker的settings(先右击docker小图标,出现的菜单里有settings这一项)里填入代理地址

查看代理端口号

然后写入如下命令(就是一般地在ubuntu中配置环境的步骤)

apt-get update(不做这一步的话可能后面有的包找不到)

apt-get install python3.6 python3-pip(安装Python,注意版本)

pip3 install virtualenv安装虚拟环境控制(使用虚拟环境来做版本管理是一个好习惯)

virtualenv python3(新建一个虚拟环境)

进入virtualenv

source /python3/bin/activate 进入Python虚拟环境

pip install django 在虚拟环境中安装django

到这一步,这个容器的内部环境就算是配置成功了。

下面说一下如何退出系统:

退出系统有两种方式,一种是ctrl+d或者是exit命令,这种方法会退出容器中的bash命令行,并且很贴心地帮你把刚刚运行中的容器stop掉(也就是说你用docker ps看不见它了,得需要docker ps -a才能看见,如果想要再启动得先docker start 容器id 再 docker attach 容器id )

另外一种是先ctrl+p再ctrl+q,这样子可以让容器处于运行态,仅仅退出伪终端,这时可以通过docker ps看见其正在运行,想要回去直接docker attach 容器id 即可。

(&再插一句题外话,如果有很多未运行且无用的容器(在不熟悉docker运行方式的时候经常会新建很多垃圾容器,停止的容器并没有被删除,停止的容器也是容器),当你想把它们都删掉,但是苦于每个容器的id太长而不想一个个手敲的话,可以用到docker -a -q命令。该命令会返回给你所有“被创建但未处于运行态”的容器的id,

在DOS里使用

for /F %i in (‘docker ps -a -q’ ) do (docker rm %i)命令

或在bash(如果你是在linux系统里运行docker的话)里使用

docker rm $(docker ps -a -q) 命令

都可以删除掉之前产生的所有的垃圾了)

如果还是害怕以后会把辛辛苦苦搭建好的环境弄崩,不妨使用docker commit将容器转成一个镜像(做版本管理啥的。。。虽然这里不太需要)方便日后回退。


挂载盘符启动

好,建好基础环境之后接下来就是将在第4步中搭建的Django框架项目放进docker容器里了。

问:将本机的Django项目放进docker容器里一共分几步?

我瞎说的

我一开始以为是需要将整个文件夹复制粘贴过去(毕竟虚拟机是这样子的),上网一查才发现人家居然可以挂载盘符!(所谓挂载盘符其实应该叫volume映射,就是将本地的某个文件夹直接分享(或者叫映射)到容器内部,实在是非常方便,早知道是这样我就不用提前在外面搭建好django了,直接放进docker里搭建也是一样的)

挂载的步骤是在docker run命令中进行的,命令如下

docker run -v 你本机需要分享的文件夹路径:容器内映射出来生成的文件夹 镜像ID

本机的文件夹路径如果含有:的话(比如C:/wangziyu_file这样子)需要使用/C/wangziyu_file的格式代替。

既然是需要镜像ID,我们要先将之前配好环境的容器commit成一个镜像。

在运行这个命令之前先需要在docker的settings里开启Shared Drives不然会报如下错误:

未开启驱动器共享报错

在settings中开启驱动器共享截图(需要输入用户名和密码)

开启驱动器共享
(注意,在开启共享的时候docker会停止运行并开始更新,此时要保证docker中没有运行着什么重要进程的容器。)

然后就可以在docker中看见我们的django程序了

挂载盘符后效果

进入Python虚拟环境(因为django在虚拟环境里面,不进去的话运行不了)运行一下看看

挂载盘符启动django框架

good!运行成功!


映射端口

在docker里面搭建好django还不是结束,毕竟我们要看看效果是不是和本机运行一样,因为docker内部显然无法给出可视化反馈,只好从外部来看看是否搭建成功。

but!这个时候问题来了,到底要访问什么ip什么端口呢?

根据以往经验肯定,这里给出的127.0.0.1:8000其实是指docker中运行着的ubuntu系统的8000端口,而不是本机的8000端口。但是这个ubuntu系统的端口并没有一个实际的物理承载,也就是说这个端口是一个虚拟的端口。所以我们要将其和我们本机的端口进行映射,好让我们对其进行访问

映射的步骤也是在docker run 命令中进行的,命令格式如下

docker run -p 127.0.0.1:端口号(本机端口):容器端口 镜像ID

注意这里映射的是“容器端口”而不是“容器中运行的ubuntu系统的端口”,所以在manage.py runserver的时候需要注意:django应该部署到 0.0.0.0:被映射的容器端口 而非 127.0.0.1:被映射的容器端口 。原因你懂的。

开启端口映射后启动django框架

外部访问,成果

部署成功

搭建成功,眼泪流出来。


Subscribe
提醒
guest
0 评论
Inline Feedbacks
View all comments