GVKun编程网logo

使用 Docker 部署 Python 应用的一些经验总结(docker部署python web应用)

15

对于使用Docker部署Python应用的一些经验总结感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍docker部署pythonweb应用,并为您提供关于5分钟,教你用Docker部署一个Py

对于使用 Docker 部署 Python 应用的一些经验总结感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍docker部署python web应用,并为您提供关于5 分钟,教你用 Docker 部署一个 Python 应用!、5分钟教会你用Docker部署一个Python应用、Altium Designer16绘制51单片机的一些经验总结、Docker 容器化部署 Python 应用的有用信息。

本文目录一览:

使用 Docker 部署 Python 应用的一些经验总结(docker部署python web应用)

使用 Docker 部署 Python 应用的一些经验总结(docker部署python web应用)

本篇文章源自作者团队在长期开发过程中总结的宝贵经验,其中 Supervisor、Gunicorn 以及 Nginx 更是在使用 Python 开发 Web 应用时最常用的软件,因此对于打算使用 Docker 部署 Python 应用的读者而言,这些最佳实践是很有参考价值。同时希望各位在日常实践过程中,也能将各自踩到过的 “坑” 以及宝贵的经验分享出来,大家共同进步!

我们可以使用 Docker 简单而高效的部署 Python 应用,同时,也有一些最佳实践来帮助我们愉快的完成部署。当然,也不是说这些最佳实践就是完成部署的唯一方式,只不过我们团队发现它们具有高可用性,并且容易维护。注意本文中大多数内容都只是代表我的立场,基于 Docker 的实现方式有很多,你可以随便选择。本文中我不会过多的介绍 Volume,因为它可能需要一个单独的话题来解释。我们通常会使用 Volume 将源代码复制到容器中,而不是在每次运行时都重新构建。

DEBIAN_FRONTEND

Docker 用户应该都很熟悉这个环境变量,它告知操作系统应该从哪儿获得用户输入。如果设置为”noninteractive”,你就可以直接运行命令,而无需向用户请求输入(译者注:所有操作都是非交互式的)。这在运行 apt-get 命令的时候格外有用,因为它会不停的提示用户进行到了哪步并且需要不断确认。非交互模式会选择默认的选项并以最快的速度完成构建。

请确保你只在 Dockerfile 中调用的 RUN 命令中设置了该选项,而不是使用 ENV 命令进行全局的设置,因为 ENV 命令在整个容器运行过程中都会生效,所以当你通过 BASH 和容器进行交互时,如果进行了全局设置那就会出问题。例子如下:

# 正确的做法 - 只为这个命令设置ENV变量
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python3
# 错误地做法 - 为接下来的任何命令都设置ENV变量,包括正在运行地容器
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get install -y python3

requirements.txt

相比于基本的代码(codebase),应用的依赖很少发生变化,因此我们可以在 Dockerfile 中安装项目依赖,这也可以加快之后的构建速度(之后的构建只需要构建变更的代码)。Docker 容器的层级构建可以缓存依赖安装的过程,所以之后的的构建速度会非常快,因为它不需要重新下载和构建依赖。

文件顺序

按照上面的思路(利用缓存)来推断,文件添加到容器的顺序至关重要。我们应该把频繁变更的文件放置到 Dockerfile 的下方,以便充分使用缓存来加速 Docker 的构建过程。例如,应用配置、系统配置和依赖都很少改变,我们就可以把它们放到 Dockerfile 的顶部。而源文件,比如路由文件、视图(views)和数据库代码会经常发生改变,所以我们就可以把它们放在 Dockerfile 的下方,注意是 Docker 配置命令(EXPOSE、ENV 等)的下方。

另外,不要考虑如何将你的文件拷贝到 Docker,它不会加快你的构建速度,因为大多数的文件根本不会用到,比如应用源文件。

应用密钥

之前我们一直不知道如何把应用密钥安全的传递给应用,后来我们发现可以使用 docker run 命令中的 env-file 参数。我们会把所有的密钥和配置都放在 app_config.list 文件中,然后通过这个文件交付给应用。具体如下:

docker run -d -t -env-file app_config.list <image:tag>

这个方法允许我们简单地改变应用设置和密钥,而无需重建一个容器。

注意:请务必确保 app_config.list 在.gitignore 文件的记录中,不然它不会被检录到源文件中。

Gunicorn

我们使用 Gunicorn 作为容器内部的应用服务器,Gunicorn 非常的稳定并且性能很好,它有非常多的配置选项,比如指定 worker 数量和类型(green threads、gevent 等)的能力,你可以根据负载来调整应用,以获得最佳性能。

启动 Gunicorn 很简单:

# 安装
pip3 install gunicorn

# 运行服务器
gunicorn api:app -w 4 -b 127.0.0.1:5000

最后是在 Nginx 后面运行你的应用服务器,这样你可以进行负载均衡。

supervisord

你是不是想过在容器中运行多个进程?我想 Supervisord 绝对是你的最佳辅助工具。假设我们想部署这样一个容器,它包含 Nginx 反向代理以及 Gunicorn 应用。你通过 BASH 脚本可能就能实现,但是让我们想更加简洁一点。

Supevisor 是 “一个进程控制系统,它支持用户在类 UNIX 操作系统上,监视并控制一些进程”。听起来很完美!你需要先在你的 Docker 容器内安装 Supervisor。

RUN DEBIAN_FRONTEND=noninteractive apt-get install -y
supervisor

为了让 Supervisor 知道该运行什么以及如何管理进程,我们接下来需要为它写一个配置文件。

[supervisord]
nodaemon = true  # 这个会让supervisord运行在前端

[program:nginx]  # 你想运行的第一个程序的命名
command = /usr/sbin/nginx  # nginx可执行程序的路径
startsecs = 5  # 如果nginx保持开启5s,我们视为启动成功

[program:app-gunicorn]
command = gunicorn api -w 4 -b 127.0.0.1:5000
startsecs = 5

这是非常基本的配置,它还有很多的配置项,比如控制日志、stdout/stderr 重定向、重启策略等。这个工具真不错。

一旦你完成了配置,请确保 Docker 将其复制到了容器中。

ADD supervisord.conf /etc/supervisord.conf

让 Supervisor 作为容器的自启动命令。

CMD supervisord -c /etc/supervisord.conf

它将会在容器启动的时候,运行 Gunicorn 和 Nginx。如果已经配置过了,那将会按需重启它们。

学到的东西以及未来的目标

我们已经花了很长时间在 Docker 中部署代码,并且接下来会投入更多的时间。在使用 Docker 的过程中,我们学到的最重要经验就是如何最小化思考(think minimally)。在一个容器中运行你的整个系统真的很诱人,但是在应用各自的容器中运行应用进程却更容易维护。一般情况下,我们会在容器中运行 Nignx 和 Web 服务器,并且在一些场景中,使用单独的容器来运行 Nginx 却没有任何优势,它可能只会增加复杂度。我们发现对于大多数情况,它在容器中的开销是可接受的。

5 分钟,教你用 Docker 部署一个 Python 应用!

5 分钟,教你用 Docker 部署一个 Python 应用!

在使用传统物理机或云服务器上部署项目都会存在一些痛点

比如:项目部署速度慢、资源浪费、迁移难且扩展低

而使用 Docker 部署项目的优势包含:

  • 高效利用系统资源
  • 服务启动更快
  • 环境一致,迁移更加方便

本篇文章将介绍 Docker 部署一个 Python 项目的常规流程

1. Dockerfile 描述文件
Dockerfile 是一个放置在项目根目录下的描述文件,可以利用 Docker 命令基于该文件构建一个镜像

常用的指令包含:

  • FROM
    用于定义基础镜像
  • MAINTAINER
    指定维护者信息,可以省略不写
  • RUN
    和「 安装命令 」连接在一起,可用于安装工具依赖包
  • ADD
    将宿主机的文件,并进行解压
  • COPY
    和 ADD 指令功能一样,但是不会进行解压操作
  • WORKDIR
    用于切换工作目录
  • VOLUME
    配置宿主机与容器的目录映射
  • EXPOSE
    配置容器内项目对外暴露的端口号
  • CMD
    指定容器启动后,运行的命令

比如,可以运行某个命令启动项目

2. 实战一下
使用 Docker 部署应用的常规流程是:

  • 开发项目并本地测试通过
  • 编写 Dockerfile 放置到项目根目录
  • 打包镜像文件
  • 运行镜像容器
  • 测试

为了演示方便,这里以一个简单的 Flask 项目为例进行讲解

2-1 项目开发

from flask import Flask

# 安装依赖
# pip3 install -U flask

app = Flask(__name__)


@app.route(''/'')
def index():
    return "测试容器部署!"


if __name__ == ''__main__'':
    app.run(host=''0.0.0.0'', port=8888)

# 浏览器访问测试
# http://127.0.0.1:8888/

项目开发完成,并在本地测试通过后就可以编写 Dockerfile 文件了

2-2 编写 Dockerfile

在项目根目录下,创建一个 Dockerfile 文件,使用上面的指令编写描述脚本

需要注意的是,这里使用「 EXPOSE 」指令暴露的端口号与入口文件定义的端口号保持一致

# Dockerfile

FROM centos:7.9.2009
RUN yum makecache fast;
RUN yum install python3-devel python3-pip -y
RUN pip3 install -i https://pypi.douban.com/simple flask
COPY main.py /opt
WORKDIR /opt
EXPOSE 8888
CMD ["python3","main.py"]

2-3 构建镜像

# 在当前文件夹下,根据Dockerfile文件构建一个镜像
# 镜像名称:xag/my_flask_web
# --no-cache:不使用旧的缓存进行镜像构建
docker build --no-cache -t "xag/my_flask_web" .

2-4 运行镜像容器

使用 docker run 命令基于镜像运行一个容器

其中

* -d:代表容器在后台运行,不是基于前台运行
* --name:用于执行容器的别名
* -p:用于配置宿主机与容器的端口映射

# -d:后台运行
# 宿主机(9999)映射容器内的8888(上面Dockerfile已经暴露了8888端口)
docker run -d --name flask_web -p 9999:8888 xag/my_flask_web  

2-5 测试一下

最后在浏览器中,通过宿主机暴露的端口号 9999 访问项目了

访问地址:http://127.0.0.1:9999/

3. 总结
文章中以一个简单的 Web 项目阐述了利用 Docker 部署项目的常规流程

实际上,Dockerfile 非常的灵活,它还支持 ARG/ENV 设置环境变量,VOlUME 指令挂载目录,ENTRYPOINT 配置启动程序和参数等,这部分内容大家可以根据官网介绍自行进行扩展

最近整理了几百 G 的 Python 学习资料,包含新手入门电子书、教程、源码等等,免费分享给大家!想要的前往 “Python 编程学习圈”,发送 “J” 即可免费获得

5分钟教会你用Docker部署一个Python应用

5分钟教会你用Docker部署一个Python应用

前言

在使用传统物理机或云服务器上部署项目都会存在一些痛点

比如:项目部署速度慢、资源浪费、迁移难且扩展低

而使用 Docker 部署项目的优势包含:

  • 高效利用系统资源
  • 服务启动更快
  • 环境一致,迁移更加方便

本篇文章将介绍 Docker 部署一个 Python 项目的常规流程

1. Dockerfile 描述文件

Dockerfile 是一个放置在项目根目录下的描述文件,可以利用 Docker 命令基于该文件构建一个镜像

常用的指令包含:

FROM

用于定义基础镜像

MAINTAINER

指定维护者信息,可以省略不写

RUN

和「 安装命令 」连接在一起,可用于安装工具依赖包

ADD

将宿主机的文件,并进行解压

COPY

和 ADD 指令功能一样,但是不会进行解压操作

WORKDIR

用于切换工作目录

VOLUME

配置宿主机与容器的目录映射

EXPOSE

配置容器内项目对外暴露的端口号

CMD

指定容器启动后,运行的命令

比如,可以运行某个命令启动项目

2. 实战一下

使用 Docker 部署应用的常规流程是:

开发项目并本地测试通过

编写 Dockerfile 放置到项目根目录

打包镜像文件

运行镜像容器

测试

为了演示方便,这里以一个简单的 Flask 项目为例进行讲解

2-1 项目开发

from flask import Flask

# 安装依赖
# pip3 install -U flask

app = Flask(__name__)

@app.route(''/'')
def index():
    return "测试容器部署!"

if __name__ == ''__main__'':
    app.run(host=''0.0.0.0'', port=8888)

# 浏览器访问测试
# http://127.0.0.1:8888/

项目开发完成,并在本地测试通过后就可以编写 Dockerfile 文件了

2-2 编写 Dockerfile

在项目根目录下,创建一个 Dockerfile 文件,使用上面的指令编写描述脚本

需要注意的是,这里使用「 EXPOSE 」指令暴露的端口号与入口文件定义的端口号保持一致

# Dockerfile

FROM centos:7.9.2009
RUN yum makecache fast;
RUN yum install python3-devel python3-pip -y
RUN pip3 install -i https://pypi.douban.com/simple flask
COPY main.py /opt
WORKDIR /opt
EXPOSE 8888
CMD ["python3","main.py"]

2-3 构建镜像

# 在当前文件夹下,根据Dockerfile文件构建一个镜像
# 镜像名称:xag/my_flask_web
# --no-cache:不使用旧的缓存进行镜像构建
docker build --no-cache -t "xag/my_flask_web" .

2-4 运行镜像容器

使用 docker run 命令基于镜像运行一个容器

其中

-d:代表容器在后台运行,不是基于前台运行

–name:用于执行容器的别名

-p:用于配置宿主机与容器的端口映射

# -d:后台运行
# 宿主机(9999)映射容器内的8888(上面Dockerfile已经暴露了8888端口)
docker run -d --name flask_web -p 9999:8888 xag/my_flask_web  

2-5 测试一下

最后在浏览器中,通过宿主机暴露的端口号 9999 访问项目了

访问地址:http://127.0.0.1:9999/

3. 总结

文章中以一个简单的 Web 项目阐述了利用 Docker 部署项目的常规流程

实际上,Dockerfile 非常的灵活,它还支持 ARG/ENV 设置环境变量,VOlUME 指令挂载目录,ENTRYPOINT 配置启动程序和参数等,这部分内容大家可以根据官网介绍自行进行扩展

到此这篇关于用Docker部署一个Python应用的文章就介绍到这了,更多相关Docker部署Python应用内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

您可能感兴趣的文章:
  • 在Docker上开始部署Python应用的教程
  • 在Docker上部署Python的Flask框架的教程
  • Docker部署Python爬虫项目的方法步骤
  • Docker如何部署Python项目的实现详解
  • python开发之Docker入门安装部署教程

Altium Designer16绘制51单片机的一些经验总结

Altium Designer16绘制51单片机的一些经验总结

作者:<a href="https://www.cnblogs.com/structmooc/">struct_mooc</a> 博客地址:https://www.cnblogs.com/structmooc/p/10526143.html

制作这块51单片机的还是蛮艰辛的,应该是我水平太差,现在这块51板已经稳定了,也把这块板子制作过程中的一些问题及经验总结记录下来。这块板子制作出了很大问题很大原因是因为我对Altium Designer16这个软件的操作不熟悉以及芯片认识不到位,毕竟画这块板子的很大一部分原因就是为了熟悉这个软件。  

首先是从原理图的绘制开始,因为我的51入门单片机是普中科技的那种100+的单片机,比较亲切,所以我选择用这块单片机为原型画我的单片机。以下是步骤:  ##第一步 原理图的元器件的绘制,在绘制元器件的时候,我是几乎都是依照普中元器件的绘制模式绘制的,这是没有什么问题的,问题就出在原理图对应的

<center>![](https://img2018.cnblogs.com/blog/1622352/201903/1622352-20190313205834908-704900957.png) </center> <center>![](https://img2018.cnblogs.com/blog/1622352/201903/1622352-20190313205921260-705401363.png) </center> PCB中元器件引脚上。比如这个芯片,刚开始我对引脚的一一对应的理解是PCB对应的引脚排列顺序和原理图是一样的(实际是PCB中的引脚对应芯片资料的引脚),所以我就去更改封装引脚然后结果就是这样子了。真正对的引脚应该是逆时针开始12345678910,这个错误是非常严重的,后果很明显,板子直接崩溃。   ##第二步 原理图的绘制,毕竟是别人的原理图,对于我这种菜鸟来说还是存在一定的问题的,一定要注意网络编号的连接,漏掉一个都会出现问题,解决办法是自己在PCB板上拉一根飞线。还有最小系统模块一定要对,相对于其他模块来说,他们都是外设,这个才是核心。这里说一下因为原理图绘制出现的问题,这一步出现的最严重的问题就是下载模块无法下载,无法下载那其他模块正常与否就不重要了。解决下载的方法是自己用了一个CH340的下载模块来测试其他模块的好坏的。对于下载模块需要注意这几点,TX接RX,RX接TX,这个是常识;冷启动才是关键,51单片机必须冷启动才能下载,冷启动简单的说就是先给单片机供电,点击下载后断电,在重新供电,就能下载了。   ##第三步 PCB布线,原理图转PCB这里需要注意的是最好一次确定好元器件因为每次转都要重新制定下布线规则,或许可以更改设置不需要重复设置吧。这个阶段还要提一下的是51单片机的那个锁紧座是有一个开关的,就是用来锁住和打开那个芯片的,注意不要被其他元器件或者排针挡住,至于我为什么要提一下,这个就应该不用说了。   ##第四步 PCB板绘制成功的后期处理,也是对自己电路板的一个美化。这里就不得不提一下铺铜操作了。AD16我用了两种铺铜方式。 <center>![](https://img2018.cnblogs.com/blog/1622352/201903/1622352-20190313204420097-1355149298.png) </center> 最开始我是用第二种铺铜方式,因为我的板子是16cmx11cm的,用这种铺铜方式的话大约需要一分钟(我好几次以为是卡了,直接关闭重开),而且铺铜完毕之后如果需要改进一些布线的话,移动一下都要几秒。所以,如果板子比较大的话,建议用第一种方式。还有,如果板子条件允许的话,也可以加一个二维码上去,好玩吧,至于内容可以是原理图或者其他。   ##第五步 这块板子是废了,所以我重新推到开始,这里还是有一个建议的,这里明显可以看出锁紧座的那个孔比一般的孔大,因为我第一块板的时候发现那个锁紧座引脚不是很准,插进去很费力,所以我把孔变大了,插进去就容易了,后果是布线不允许从引脚中间通过了,孔小一点就能通过了,但是好不好插就不知道了,毕竟没试过。 <center>![](https://img2018.cnblogs.com/blog/1622352/201903/1622352-20190313204426316-602743117.png) </center> ##第六步 还有一个建议就是在焊接测试模块的好坏的时候最好一个一个模块焊接,测试。 

第一次写博客,自己都觉得条理不清,就留个纪念吧。

Docker 容器化部署 Python 应用

Docker 容器化部署 Python 应用

1. 简介

Docker 是目前主流 IT 公司广泛接受和使用的,用于构建、管理和保护它们应用程序的工具。

容器,例如 Docker 允许开发人员在单个操作系统上隔离和运行多个应用程序,而不是为服务器上的每个应用程序专用一个虚拟机。使用容器更轻量级,可以降低成本、更好地使用资源和发挥更高的性能。

本文将使用 Flask 开发一个简单的 Python web 应用程序,并为 “容器化” 做好准备。然后创建一个 Docker 映像,并将其部署到测试和生产环境中。

注意: 请确保机器上已安装 Docker,如果没有请参考 Docker 官方安装教程。

2. Docker 介绍

Docker 是一种工具,它使开发人员能够交付他们的应用程序 (以及库或其他依赖项),确保他们可以使用正确的配置运行,而不受部署环境影响。

这是通过将应用程序隔离在单独的容器中来实现的,这些应用程序虽然被容器分隔开,但是却可以共享操作系统和其他资源。

Docker 包含两部分:

  • Docker Engine — 应用打包工具,用于封装应用程序。

  • Docker Hub — 用于管理云上容器应用程序的工具。

3. 为何选择容器

了解容器的重要性和实用性非常重要,虽然它和直接将应用部署到服务器没有多大区别,但是当涉及到比较复杂的且相当吃资源的应用,尤其是多个应用部署在同一台服务器,或是同一应用要部署到多台服务器时。容器就变得非常有用。

在容器之前,这是通过 VMWare 和 Hypervisor 等虚拟机解决的,但是它们在效率、速度和可移植性方面已被证明并不是最佳选择。

Docker 容器是虚拟机的轻量级的替代品 - 与 VM 不同,我们不需要为它预先分配 RAM、CPU 或其他资源,也不需要为每个应用程序启动一个 VM,仅仅只需要一个操作系统即可。

使用容器开发人员就不需要为不同环境制定特殊版本,这样可以专注于应用程序的核心业务逻辑。

4. 创建 Python 应用

Flask 是 Python 的一个轻量级 Web 应用框架,简单易用,可以很快速地创建 web 应用。我们用它来创建此 demo 应用。

如果还没有安装 Flask 模块,可以使用下面命令安装:

$ pip install flask

安装成功后,新建一个应用目录,命名为 FlaskDemo。并在该目录下创建应用代码文件 app.py

app.py 中,首先引入 Flask 模块,然后创建一个 web 应用:

from flask import Flask

app = Flask(__name__)

然后定义路由 / 和其对应的请求处理程序:

@app.route("/")
def index():  
  return """
  <h1>Python Flask in Docker!</h1>
  <p>A sample web-app for running Flask inside Docker.</p>
  """

最后,添加运行主程序并启动该脚本:

if __name__ == "__main__":  
    app.run(debug=True, host=''0.0.0.0'')
$ python app.py

然后在浏览器中访问 http://localhost:5000/, 可以看到 Dockerzing Python app using Flask 这样的页面。

5.Dokcer 打包应用

要在 Docker 上运行应用程序,首先必须构建一个容器,而且必须包含使用的所有依赖项 —— 在我们的例子中只有 Flask。因此,新建一个包含所有依赖包的 requirements.txt 文件,然后创建一个 Dockerfile,该文件用来描述构建映像过程。

此外,当启动容器时还需要放开应用程序的 HTTP 端口。

准备工作

requirements.txt 文件非常简单,只需要填入项目的依赖包和其对应版本即可:

Flask==1.0.2 

接下来,需要将应用程序运行所需的所有 Python 文件都放在顶层文件夹中,例如,名为 app 的目录。

同时建议将主入口程序命名为 app.py ,将脚本中创建的 Flask 对象命名为 app 是一种通常的做法,这样也可以简化部署。

FlaskApp  
    ├── requirements.txt
    ├── Dockerfile
    └── app
        └── app.py
        └── <other .py files>

创建 Dockerfile

Dockerfile 本质上是一个文本文件,其中明确定义了如何为我们的项目构建 Docker 镜像。

接下来创建一个基于 Ubuntu 16.04 和 Python 3.X 的 Dokcer 镜像:

FROM ubuntu:16.04

MAINTAINER jhao104 "j_hao104@163.com"

RUN apt-get update -y && \  
    apt-get install -y python3-pip python3-dev

COPY ./requirements.txt /requirements.txt

WORKDIR /

RUN pip3 install -r requirements.txt

COPY . /

ENTRYPOINT [ "python3" ]

CMD [ "app/app.py" ] 

Dockerfile 的基本指令有十三个,上面用到了部分;

  • FROM - 所有 Dockerfile 的第一个指令都必须是 FROM ,用于指定一个构建镜像的基础源镜像,如果本地没有就会从公共库中拉取,没有指定镜像的标签会使用默认的 latest 标签,如果需要在一个 Dockerfile 中构建多个镜像,可以使用多次。

  • MAINTAINER - 描述镜像的创建者,名称和邮箱。

  • RUN - RUN 命令是一个常用的命令,执行完成之后会成为一个新的镜像,通常用于运行安装任务从而向映像中添加额外的内容。在这里,我们需更新包,安装 python3pip 。在第二个 RUN 命令中使用 pip 来安装 requirements.txt 文件中的所有包。

  • COPY - 复制本机文件或目录,添加到指定的容器目录,本例中将 requirements.txt 复制到镜像中。

  • WORKDIR - 为 RUN、CMD、ENTRYPOINT 指令配置工作目录。可以使用多个 WORKDIR 指令,后续参数如果是相对路径,则会基于之前命令指定的路径。

  • ENTRYPOINT - 在启动容器的时候提供一个默认的命令项。

  • RUN - 运行 app 目录中的 app.py

Docker 镜像构建原理

Docker 镜像是使用 Docker build 命令构建的。在构建镜像时,Docker 创建了所谓的 “层 (layers)”。每一层都记录了 Dockerfile 中的命令所导致的更改,以及运行命令后镜像的状态。

Docker 在内部缓存这些层,这样在重新构建镜像时只需要重新创建已更改的层。例如,这里使用了 ubuntu:16.04 的基础镜像,相同容器的所有后续构建都可以重用它,因为它不会改变。但是,因为项目修改,在下次重新构建过程中 app 目录的内容可能会有所不同,因此只会重新构建这一层。

需要注意的是,每当重新构建某一层时,Dockerfile 中紧随其后的所有层也都需要重新构建。例如,我们首先复制 requirements.txt 文件,然后再复制应用程序的其余部分。这样之前安装的依赖项只要没有新的依赖关系,即使应用程序中的其他文件发生了更改,也不需要重新构建这一层。这一点在创建 Dockerfiles 时一定要注意。

因此,通过将 pip 安装与应用程序其余部分的部署分离,可以优化容器的构建过程。

构建 Docker 镜像

现在 Dockerfile 已经准备好了,而且也了解了 Docker 的构建过程,接下来为我们的应用程序创建 Docker 映像:

docker build -t docker-flask:0.1 .

调试模式运行

根据前面讲到的容器化的优点,开发的应用程序通过容器部署,这从一开始就确保了应用程序构建的环境是干净的,从而消除了交付过程中的意外情况。

但是呢,在开发应用程序的过程中,更重要的是要快速重新构建和测试,以检查验证过程中的每个中间步骤。为此,web 应用程序的开发人员需要依赖于 Flask 等框架提供的自动重启功能(Debug 模式下,修改代码自动重启)。而这一功能也可以在容器中使用。

为了启用自动重启,在启动 Docker 容器时将主机中的开发目录映射到容器中的 app 目录。这样 Flask 就可以监听主机中的文件变化 (通过映射) 来发现代码更改,并在检测到更改时自动重启应用程序。

此外,还需要将应用程序的端口从容器转发到主机。这是为了能够让主机上的浏览器访问应用程序。

因此,启动 Dokcer 容器时需要使用 volume-mappingport-forwarding 选项:

docker run --name flask_app -v $PWD/app:/app -p 5000:5000 docker-flask:0.1

改命令将会执行以下操作:

  • 基于之前构建的 docker-flask 镜像启动一个容器;

  • 这个容器的名称被设置为 flask_app 。如果没有 ——name 选项,Docker 将为容器生成一个名称。显式指定名称可以帮助我们定位容器 (用来停止等操作);

  • -v 选项将主机的 app 目录挂载到容器;

  • -p 选项将容器的端口映射到主机。

现在可以通过 http://localhost:5000 或者 http://0.0.0.0:5000/ 访问到应用:

如果我们在容器运行的时候,修改应用程序代码,Flask 会检测到更改并重新启动应用程序。

要停止容器的话,可以使用 Ctrl + C, 并运行 docker rm flask_app 移除容器。

生产模式运行

虽然直接使用 Flask 裸跑运行应用程序对于开发来说已经足够好了,但是我们需要在生产中使用更健壮的部署方法。

目前主流的部署方案是 nginx + uwsgi,下面我们将介绍如何为生产环境部署 web 应用程序。Nginx 是一个开源 web 服务器,uWSGI 是一个快速、自我修复、开发人员和系统管理员友好的服务器。

首先,我们创建一个入口脚本,用来控制以开发模式还是生产模式启动我们的应用程序,这两者区别是选择直接运行 python 还是 nginx 模式。

然后再写一个简单 shell 启动脚本 entry-point.sh:

#!/bin/bash

if [ ! -f /debug0 ]; then  
  touch /debug0

  while getopts ''hd:'' flag; do
    case "${flag}" in
      h)
        echo "options:"
        echo "-h        show brief help"
        echo "-d        debug mode, no nginx or uwsgi, direct start with ''python3 app/app.py''"
        exit 0
        ;;
      d)
        touch /debug1
        ;;
      *)
        break
        ;;
    esac
  done
fi

if [ -e /debug1 ]; then  
  echo "Running app in debug mode!"
  python3 app/app.py
else  
  echo "Running app in production mode!"
  nginx && uwsgi --ini /app.ini
fi  

然后创建 uWSGI 配置文件 app.ini:

[uwsgi]
plugins = /usr/lib/uwsgi/plugins/python3  
chdir = /app  
module = app:app  
uid = nginx  
gid = nginx  
socket = /run/uwsgiApp.sock  
pidfile = /run/.pid  
processes = 4  
threads = 2 

和 nginx 配置文件 nginx.conf:

user nginx;
worker_processes  4;
pid /run/nginx.pid;

events {
    worker_connections  20000;
}

http {
    include    mime.types;
    sendfile on;
    keepalive_timeout  65;
    gzip off;

    server {
        listen 80;
        access_log off;
        error_log off;

        location / { try_files $uri @flaskApp; }
        location @flaskApp {
            include uwsgi_params;
            uwsgi_pass unix:/run/uwsgiApp.sock;
        }
    }
}

最后,修改 DockerfilenginxuWSGI 安装到镜像,将配置文件复制到镜像中,并设置运行 nginx 所需的用户权限:

FROM ubuntu:16.04

MAINTAINER jhao104 "j_hao104@163.com"

RUN apt-get update -y && \
    apt-get install -y python3-pip python3-dev && \
    apt-get install -y nginx uwsgi uwsgi-plugin-python3

COPY ./requirements.txt /requirements.txt
COPY ./nginx.conf /etc/nginx/nginx.conf

WORKDIR /

RUN pip3 install -r requirements.txt

COPY . /

RUN adduser --disabled-password --gecos '''' nginx\
  && chown -R nginx:nginx /app \
  && chmod 777 /run/ -R \
  && chmod 777 /root/ -R

ENTRYPOINT [ "/bin/bash", "/entry-point.sh"]

然后重新打包镜像:

docker build -t docker-flask:0.1 .

然后使用 nginx 启动应用程序:

docker run -d --name flaskapp --restart=always -p 8091:80 docker-flask:0.1

该镜像包含 python、ngix、uwsgi 完整环境,只需要在部署时指定端口映射便可以自动部署应用。要停止并删除此容器,请运行下面命令:

docker stop flaskapp && docker rm flaskapp

此外,如果我们仍然需要上面调试功能或修改部分代码,也可以像上面一样以调试模式运行容器:

docker run -it --name flaskapp -p 5000:5000 -v $PWD/app:/app docker-flask:0.1 -d debug

6. 管理外部依赖

如果将应用程序作为容器交付时,需要记住的一个关键事项是,开发人员管理依赖项的责任增加了。除了识别和指定正确的依赖项和版本之外,还需要负责在容器环境中安装和设置这些依赖项。

在 Python 项目中管理安装依赖比较容易,可以使用 requirements.txt 指定依赖项和对应版本,然后通过 pip 安装。

需要重申的是是,无论何时修改 requirements.txt 文件,都需要重新构建 Docker 镜像。

启动时安装依赖项

可能在某次版本更新时需要安装额外的依赖项。比如,在开发过程中使用了一个新的包。如果不希望每次都重新构建 Docker 镜像,或者希望在启动时使用最新的可用版本。可以通过修改启动程序在应用程序启动时运行安装程序来实现这一点。

同样,我们也可以安装额外的系统级包依赖项。修改 entry-point.sh:

#!/bin/bash

if [ ! -f debug0 ]; then
  touch debug0
  
  if [ -e requirements_os.txt ]; then
    apt-get install -y $(cat requirements_os.txt)
    
   fi
   if [-e requirements.txt ]; then
    pip3 install -r requirements.txt
   fi

  while getopts ''hd:'' flag; do
    case "${flag}" in
      h)
        echo "options:"
        echo "-h        show brief help"
        echo "-d        debug mode, no nginx or uwsgi, direct start with ''python3 app/app.py''"
        exit 0
        ;;
      d)
        touch debug1
        ;;
      *)
        break
        ;;
    esac
  done
fi

if [ -e debug1 ]; then
  echo "Running app in debug mode!"
  python3 app/app.py
else
  echo "Running app in production mode!"
  nginx && uwsgi --ini /app.ini
fi

这样我们可以在 requirements_os.txt 中指定将要安装的系统软件包名称,这些包名以空格分隔放在同一行。他们将和 requirements.txt 中的 Python 依赖库一样在应用程序启动之前安装。

尽管这样对应用的迭代开发期间提供了便利,但是出于几个原因,在启动时安装依赖项不是一个好的实践:

  • 它破坏了容器化的目标之一,即修复和测试由于部署环境的变化而不会改变的依赖关系;

  • 增加了应用程序启动的额外开销,这将增加容器的启动时间;

  • 每次启动应用程序时需要安装依赖项,这样对网络资源有要求。

今天关于使用 Docker 部署 Python 应用的一些经验总结docker部署python web应用的介绍到此结束,谢谢您的阅读,有关5 分钟,教你用 Docker 部署一个 Python 应用!、5分钟教会你用Docker部署一个Python应用、Altium Designer16绘制51单片机的一些经验总结、Docker 容器化部署 Python 应用等更多相关知识的信息可以在本站进行查询。

本文标签: