Docker解释:如何容器化PythonWeb应用程序
状态: 已弃用
本文已弃用,不再维护。
原因
本文中的技术已经过时,可能不再反映 Docker 的最佳实践。
请参阅
介绍
Web 应用程序被劫持并用于接管整个主机的威胁是巨大而可怕的。 长期以来,将事物彼此隔离以增强安全性一直是一项挑战,尤其是在应用程序属于不同客户端的情况下。 可以采取许多措施来防止这种不幸的情况发生,但是对于大多数开发人员或管理员的用例而言,它们通常成本太高(时间和资源)或太复杂。
在这篇 DigitalOcean 文章中,我们将讨论“容器化”Python Web 应用程序,以便将它们放在非常安全的沙箱中,绝对保存在它们自己的环境中(除非你明确地将它们“链接”到另一个环境)。 为了实现这一点,我们将逐步了解如何创建一个 docker 容器来托管 Python Web 应用程序,最后使用 Dockerfile 引导我们的构建过程以使其完全自动化。
词汇表
1. Docker 简介
2. 在 Ubuntu 上安装 Docker
3. 基本的 Docker 命令
- 运行 docker 守护进程和 CLI 用法
- 码头工人命令
4. 将 Docker 容器构建到沙箱 Python WSGI 应用程序
- 从 Ubuntu 创建基础 Docker 容器
- 为安装准备基本容器
- 安装用于部署的常用 Python 工具
- 安装 Web 应用程序及其依赖项
- 配置 Python WSGI 应用程序
5. 创建 Dockerfile 以自动构建镜像
- Dockerfile 基础
- Dockerfile 命令概述
- 创建 Dockerfile
- 定义基本面
- 更新安装的默认应用程序存储库
- 安装基本工具
- Python 和基本 Python 工具的基本安装说明
- 应用部署
- 引导一切
- 最终的 Dockerfile
- 使用 Dockerfile 自动构建容器
Docker 简介
docker 项目 提供了更高级别的工具,可以协同工作,这些工具构建在一些 Linux 内核特性之上。 目标是帮助开发人员和系统管理员移植应用程序——连同它们的所有依赖项——并让它们跨系统和机器运行——无头疼。
Docker 通过创建安全的 LXC(即 Linux Containers) 基于应用程序的环境,称为 docker 容器 。 这些容器是使用 docker 镜像创建的,可以通过手动执行命令或通过 Dockerfiles 自动执行命令来构建。
注意: 了解更多关于 docker 及其部分(例如 docker daemon、CLI、图像等),请查看我们对项目的介绍性文章:docker Explained: Getting Started。
在 Ubuntu 上安装 Docker(最新)
凭借其最新版本(0.7.1. 日期为 12 月 5 日),docker 可以部署在各种 Linux 操作系统上,包括 Ubuntu / Debian 和 CentOS / RHEL。
请记住,您可以使用 DigitalOcean 在 Ubuntu 13.04 上构建的即用型 docker 映像快速入门。
我们将快速介绍 Ubuntu(最新)的安装过程。
Ubuntu 安装说明
更新您的液滴:
sudo aptitude update sudo aptitude -y upgrade
确保 aufs 支持可用:
sudo aptitude install linux-image-extra-`uname -r`
将 docker 存储库密钥添加到 apt-key 以进行包验证:
sudo sh -c "wget -qO- https://get.docker.io/gpg | apt-key add -"
将 docker 存储库添加到 aptitude 源:
sudo sh -c "echo deb http://get.docker.io/ubuntu docker main\ > /etc/apt/sources.list.d/docker.list"
使用新增内容更新存储库:
sudo aptitude update
最后,下载并安装docker:
sudo aptitude install lxc-docker
Ubuntu 的默认防火墙(UFW: Uncomplicated Firewall)默认拒绝所有转发流量,这是 docker 需要的。
使用 UFW 启用转发:
使用 nano 文本编辑器编辑 UFW 配置。
sudo nano /etc/default/ufw
向下滚动并找到以 DEFAULT_FORWARD_POLICY
开头的行。
代替:
DEFAULT_FORWARD_POLICY="DROP"
和:
DEFAULT_FORWARD_POLICY="ACCEPT"
按 CTRL+X 并用 Y 确认保存并关闭。
最后,重新加载 UFW:
sudo ufw reload
基本的 Docker 命令
在我们开始使用 docker 之前,让我们快速回顾一下它的可用命令,以刷新我们的第一篇 Getting Started 文章中的记忆。
运行 docker 守护进程和 CLI 用法
安装后,docker daemon 应该在后台运行,准备好接受 docker CLI 发送的命令。 对于可能需要手动运行 docker 的某些情况,请使用以下命令。
运行 docker 守护进程:
sudo docker -d &
码头工人 CLI 用法:
sudo docker [option] [command] [arguments]
注意: docker 需要 sudo 权限才能工作。
码头工人命令
以下是当前可用(版本 0.7.1)docker 命令的摘要:
附
附加到正在运行的容器
建造
从 Dockerfile 构建容器
犯罪
从容器的更改创建新图像
cp
将文件/文件夹从容器文件系统复制到主机路径
差异
检查容器文件系统上的更改
事件
从服务器获取实时事件
出口
将容器的内容作为 tar 存档流式传输
历史
显示图像的历史
图片
列出图像
进口
从 tarball 的内容创建新的文件系统映像
信息
显示系统范围的信息
插入
在图像中插入文件
检查
返回容器的底层信息
杀
杀死一个正在运行的容器
加载
从 tar 存档加载图像
登录
注册或登录到 docker 注册服务器
日志
获取容器的日志
港口
查找经过 NAT 转换为 PRIVATE_PORT 的面向公众的端口
ps
列出容器
拉
从 docker 注册表服务器中拉取图像或存储库
推
将图像或存储库推送到 docker 注册表服务器
重新开始
重新启动正在运行的容器
R M
移除一个或多个容器
rmi
移除一张或多张图片
跑
在新容器中运行命令
节省
将图像保存到 tar 存档
搜索
在 docker 索引中搜索图像
开始
启动一个停止的容器
停止
停止正在运行的容器
标签
将图像标记到存储库中
最佳
查找容器的运行进程
版本
显示 docker 版本信息
将 Docker 容器构建到沙箱 Python WSGI 应用程序
在我们的 VPS 上安装了 docker 并快速查看了它的命令后,我们准备开始实际工作,创建运行 Python WSGI 应用程序的 docker 容器。
注意: 以下部分将使您能够拥有一个 dockerized(容器化)Python WSGI Web 应用程序。 但是,由于其复杂性和不实用性,绝对不是推荐的方法。 它在这里为您提供了一个学习如何使用实时容器并熟悉我们需要在下一节稍后定义的命令以自动化该过程的机会。
让我们开始!
从 Ubuntu 创建基础 Docker 容器
使用 docker 的 RUN 命令,我们将首先基于 Ubuntu 映像创建一个新容器。 我们将使用 -t 标志将终端附加到它,并将 bash 作为正在运行的进程。
我们将公开 端口 80 以便我们的应用程序可以从外部访问。 将来,您可能希望对多个实例进行负载平衡并将容器“链接”到彼此以使用反向代理运行容器访问它们。
sudo docker run -i -t -p 80:80 ubuntu /bin/bash
注意: 执行此命令后,docker 可能需要 pull Ubuntu 映像,然后才能为您创建新容器。
记住:您将被附加到您创建的容器中。 为了分离自己并返回主终端接入点,请运行转义序列:CTRL+P,然后是 CTRL+Q。 连接到 docker 容器就像连接到另一个内部的新液滴。
要将自己重新连接到此容器:
- 使用“sudo docker ps”列出所有正在运行的容器
- 找到它的 ID
- 使用“sudo docker attach [id]”附加回其终端
重要:请不要忘记,由于我们是在一个容器,所以下面的所有命令都会在那里执行,不会影响它所在的主机。
为安装准备基本容器
为了在容器内部署 Python WSGI Web 应用程序 - 以及我们在该过程中需要的工具 - 相关的应用程序存储库必须可供下载。 不幸的是(并且故意保持简单)这是 而不是 与 docker 附带的默认 Ubuntu 映像的情况。
让我们将 Ubuntu 的 Universe 存储库附加到基础映像的默认应用程序源列表。
echo "deb http://archive.ubuntu.com/ubuntu/ $(lsb_release -sc) main universe" >> /etc/apt/sources.list
使用新添加的源更新列表。
apt-get update
在我们继续设置 Python WSGI 应用程序之前,我们应该拥有一些工具,例如 nano、tar、curl 等。 - 以防万一。
让我们在我们的容器中下载一些有用的工具。
apt-get install -y tar \ git \ curl \ nano \ wget \ dialog \ net-tools build-essential
安装用于部署的常用 Python 工具
对于我们的教程(作为示例),我们将创建一个非常基本的 Flask 应用程序。 阅读本文后,您可以使用和部署您喜欢的框架,就像在虚拟服务器上部署它一样。
记住: 下面的所有命令和指令仍然发生在一个容器内,它几乎就像一个全新的水滴一样。
让我们从安装 Python 和 Python 包管理器 pip 开始我们的部署过程:
# Install pip's dependency: setuptools: apt-get install -y python python-dev python-distribute python-pip
安装 Web 应用程序及其依赖项
在我们开始创建示例应用程序之前,我们最好确保所有内容 - 即 所有依赖项- 都在那里。 首先,您很可能将 Web 应用程序框架 (WAF) 作为应用程序的依赖项(即 烧瓶)。
由于我们已经安装了 pip 并准备好工作,我们可以使用它来提取所有依赖项并将它们设置在我们的容器中:
# Download and install Flask framework: pip install flask
安装 pip 后,让我们在“my_application”文件夹中创建一个基本的示例 Flask 应用程序,该文件夹将包含所有内容。
# Make a my_application folder mkdir my_application # Enter the folder cd my_application
注意:如果您有兴趣部署您的应用程序而不是这个简单的示例示例,请参阅下面的“快速提示”中间部分。
让我们创建一个单页烧瓶“Hello World!” 使用纳米的应用程序。
# Create a sample (app.py) with nano: nano app.py
并为我们刚刚提到的这个小应用程序复制并粘贴以下内容:
from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello World!" if __name__ == "__main__": app.run()
按 CTRL+X 并用 Y 批准以保存并关闭。
或者,您可以使用“requirements.txt”来包含应用程序的依赖项,例如 Flask。
使用 nano 文本编辑器创建 requirements.txt:
nano requirements.txt
并在里面输入以下内容,以及所有依赖项:
flask cherrypy
按 CTRL+X 并用 Y 批准以保存并关闭。
注意: 您可以使用 pip 创建实际应用程序依赖项的列表。 要了解如何操作,请查看我们的教程 常用 Python 工具:使用 virtualenv、使用 Pip 安装和管理包。
我们最终的应用程序文件夹结构:
/my_application | |- requirements.txt # File containing list of dependencies |- /app # Application module (which should have your app) |- app.py # WSGI file containing the "app" callable |- server.py # Optional: To run the app servers (CherryPy)
注意:请参阅以下有关“server.py”的部分 - 配置您的Python WSGI应用程序。
记住:这个应用程序文件夹将在容器内创建。 当您自动构建映像时(请参阅以下有关 Dockerfile 的部分),您需要确保在主机上具有此结构以及 Dockerfile。
__ * 实际部署的快速提示 * __
如何在容器中获取应用程序存储库及其要求
在上面的示例中,我们在容器内创建了应用程序目录。 但是,您不会这样做来部署您的应用程序。 您很可能从存储库中提取其源代码。
有几种方法可以将您的存储库复制到容器中。
下面解释其中的两个:
# Example [1] # Download the application using git: # Usage: git clone [application repository URL] # Example: git clone https://github.com/mitsuhiko/flask/tree/master/examples/flaskr # Example [2] # Download the application tarball: # Usage: wget [application repository tarball URL] # Example: (make sure to use an actual, working URL) wget http://www.github.com/example_usr/application/tarball/v.v.x # Expand the tarball and extract its contents: # Usage: tar vxzf [tarball filename .tar (.gz)] # Example: (make sure to use an actual, working URL) tar vxzf application.tar.gz # Download and install your application dependencies with pip. # Download the requirements.txt (pip freeze output) and use pip to install them all: # Usage: curl [URL for requirements.txt] | pip install -r - # Example: (make sure to use an actual, working URL) curl http://www.github.com/example_usr/application/requirements.txt | pip install -r -
配置 Python WSGI 应用程序
要为该应用程序提供服务,您将需要一个 Web 服务器。 为 WSGI 应用程序提供支持的 Web 服务器需要安装在与应用程序的其他资源相同的容器中。 实际上,它将是 docker 运行的进程。
注意: 在本例中,由于其简单性,我们将使用 CherryPy 内置的生产就绪 HTTP Web 服务器。 按照我们关于该主题的教程,您可以使用 Gunicorn、CherryPy 甚至 uWSGI(并在 Nginx 后面设置它们)。
使用 pip 下载并安装 CherryPy:
pip install cherrypy
创建一个“server.py”来为来自“app.py”的Web应用程序提供服务:
nano server.py
复制并粘贴下面的内容,以便服务器导入您的应用程序并开始提供服务:
# Import your application as: # from app import application # Example: from app import app # Import CherryPy import cherrypy if __name__ == '__main__': # Mount the application cherrypy.tree.graft(app, "/") # Unsubscribe the default server cherrypy.server.unsubscribe() # Instantiate a new server object server = cherrypy._cpserver.Server() # Configure the server object server.socket_host = "0.0.0.0" server.socket_port = 80 server.thread_pool = 30 # For SSL Support # server.ssl_module = 'pyopenssl' # server.ssl_certificate = 'ssl/certificate.crt' # server.ssl_private_key = 'ssl/private.key' # server.ssl_certificate_chain = 'ssl/bundle.crt' # Subscribe this server server.subscribe() # Start the server engine (Option 1 *and* 2) cherrypy.engine.start() cherrypy.engine.block()
就是这样! 现在,您可以将“dockerized” Python Web 应用程序安全地保存在其沙箱中,只需运行以下命令即可为成千上万的客户端请求提供服务:
python server.py
这将在前台运行服务器。 如果要停止它,请按 CTRL+C。
要在后台运行服务器,请运行以下命令:
python server.py &
当您在后台运行应用程序时,您将需要使用进程管理器(例如 htop) 杀死(或停止)它。
注意: 要了解更多关于配置 Python WSGI 应用程序以使用 CherryPy 进行部署,请查看我们的教程:如何使用 CherryPy Web 服务器部署 Python WSGI 应用程序
为了测试一切运行顺利,他们应该考虑到所有端口分配都已经处理好了,您可以使用浏览器访问 http://[your droplet's IP] 以查看“[X206X ]Hello World!”消息。
创建 Dockerfile 以自动构建镜像
正如我们在上一步中提到的,对于可扩展的生产部署,当然不推荐以这种方式创建容器。 正确的做法可以认为是使用 Dockerfiles 以结构化的方式自动化构建过程。
在完成了在容器中下载和安装的必要命令之后,我们可以使用相同的知识来编写一个 Dockerfile,docker 可以使用它来构建一个镜像,然后可以使用它来轻松地运行 Python WSGI 应用程序容器。
在我们开始处理 Dockerfile 之前,让我们快速回顾一下基础知识。
Dockerfile 基础
Dockerfiles 是包含连续声明的命令的脚本,这些命令将由 docker 按该顺序执行以自动创建新的 docker 映像。 它们对部署有很大帮助。
这些文件总是以使用 FROM 命令定义基本映像开始。 从那里开始, 构建过程 开始,随后采取的每个操作都形成了将提交到主机上的最终映像。
用法:
# Build an image using the Dockerfile at current location # Tag the final image with [name] (e.g. *nginx*) # Example: sudo docker build -t [name] . sudo docker build -t nginx_img .
注意: 要了解有关 Dockerfile 的更多信息,请查看我们的文章:Docker 解释:使用 Dockerfiles 自动构建映像。
Dockerfile 命令概述
添加
将文件从主机复制到容器中
命令
设置要执行的默认命令,或传递给 ENTRYPOINT
入口点
设置容器内的默认入口点应用程序
环境噪声
设置环境变量(例如 “键=值”)
暴露
将端口暴露在外面
从
设置要使用的基础镜像
维护者
设置 Dockerfile 的作者/所有者数据
跑
运行命令并提交最终结果(容器)图像
用户
设置用户从镜像运行容器
体积
从宿主机挂载目录到容器
工作目录
设置要执行的CMD指令的目录
创建 Dockerfile
要使用 nano 文本编辑器在当前位置创建 Dockerfile,请执行以下命令:
sudo nano Dockerfile
注意: 将以下所有行一个接一个地附加以形成 Dockerfile。
定义基本面
让我们通过定义诸如 FROM 映像(即 Ubuntu)和维护者。
附加以下内容:
############################################################ # Dockerfile to build Python WSGI Application Containers # Based on Ubuntu ############################################################ # Set the base image to Ubuntu FROM ubuntu # File Author / Maintainer MAINTAINER Maintaner Name
更新安装的默认应用程序存储库
运行以下命令以使用其他应用程序更新 apt-get
存储库,就像我们在上一节中所做的那样。
附加以下内容:
# Add the application resources URL RUN echo "deb http://archive.ubuntu.com/ubuntu/ $(lsb_release -sc) main universe" >> /etc/apt/sources.list # Update the sources list RUN apt-get update
安装基本工具
更新默认应用程序存储库源列表后,我们可以通过获取我们需要的基本应用程序来开始我们的部署过程。
附加以下内容:
# Install basic applications RUN apt-get install -y tar git curl nano wget dialog net-tools build-essential
注意: 虽然您不太可能需要上述某些工具,但我们仍然会得到它们 - 以防万一。
Python 和基本 Python 工具的基本安装说明
为了部署 Python WSGI 应用程序,您极有可能需要一些我们之前使用过的工具(例如 点)。 在继续设置框架之前让我们现在安装它们(即 您的 WAF) 和您选择的 Web 应用程序服务器 (WAS)。
附加以下内容:
# Install Python and Basic Python Tools RUN apt-get install -y python python-dev python-distribute python-pip
应用部署
鉴于我们正在构建 docker 镜像来部署 Python Web 应用程序,我们都可以充分利用 docker 的 ADD 命令来复制应用程序存储库,最好使用 REQUIREMENTS 文件以一步快速运行。
注意: 要将所有内容打包在一个文件中而不是重复我们自己,一个类似于以下结构的应用程序文件夹可能是一个不错的方法。
示例应用程序文件夹结构:
/my_application | |- requirements.txt # File containing list of dependencies |- /app # Application module |- app.py # WSGI file containing the "app" callable |- server.py # Optional: To run the app servers (CherryPy)
注意:要了解如何创建这个结构,请回滚并参考安装Web应用程序及其依赖项部分。
附加以下内容:
# Copy the application folder inside the container ADD /my_application /my_application
注意:如果要从在线主机git仓库部署,可以使用如下命令克隆:
RUN git clone [application repository URL]
请不要忘记将 URL 占位符替换为您的实际占位符。
引导一切
添加复制应用程序的说明后,让我们完成最终配置,例如从 requirements.txt 中提取依赖项。
# Get pip to download and install requirements: RUN pip install -r /my_application/requirements.txt # Expose ports EXPOSE 80 # Set the default directory where CMD will execute WORKDIR /my_application # Set the default command to execute # when creating a new container # i.e. using CherryPy to serve the application CMD python server.py
最终的 Dockerfile
最后,Dockerfile 应该是这样的:
############################################################ # Dockerfile to build Python WSGI Application Containers # Based on Ubuntu ############################################################ # Set the base image to Ubuntu FROM ubuntu # File Author / Maintainer MAINTAINER Maintaner Name # Add the application resources URL RUN echo "deb http://archive.ubuntu.com/ubuntu/ $(lsb_release -sc) main universe" >> /etc/apt/sources.list # Update the sources list RUN apt-get update # Install basic applications RUN apt-get install -y tar git curl nano wget dialog net-tools build-essential # Install Python and Basic Python Tools RUN apt-get install -y python python-dev python-distribute python-pip # Copy the application folder inside the container ADD /my_application /my_application # Get pip to download and install requirements: RUN pip install -r /my_application/requirements.txt # Expose ports EXPOSE 80 # Set the default directory where CMD will execute WORKDIR /my_application # Set the default command to execute # when creating a new container # i.e. using CherryPy to serve the application CMD python server.py
再次按 CTRL+X 并用 Y 确认保存并退出文件。
使用 Dockerfile 自动构建容器
正如我们第一次在“基础”部分讨论的那样,Dockerfiles 的使用包括使用 docker build 命令调用它们。
由于我们正在指示 docker 复制一个应用程序文件夹(即 /my_application),我们需要确保在开始构建过程之前将它与这个 Dockerfile 放在一起。
这个 docker 镜像将允许我们使用单个命令快速创建运行 Python WSGI 应用程序的容器。
要开始使用它,请使用以下内容构建一个新的容器映像:
sudo docker build -t my_application_img .
并使用该图像 - 我们标记为 my_application_img - 我们可以运行一个运行应用程序的新容器:
sudo docker run -name my_application_instance -p 80:80 -i -t my_application_img
现在您可以访问您的 Droplet 的 IP 地址,您的应用程序将通过 docker 容器运行。
例子:
# Usage: Visit http://[my droplet's ip] http://95.85.10.236/
示例响应:
Hello World!
有关安装 docker(包括其他操作系统)的完整说明,请查看 docker.io 上的 docker 安装文档。