在数据科学领域,开发人员经常遇到应用程序在一台机器上运行正常,而在另一台机器上却无法运行的问题。Docker容器化技术通过确保应用程序在任何机器上都能运行,解决了这一问题。简而言之,如果工作涉及到开发应用程序,Docker可以为提供隔离的环境,封装所有必要的依赖项,从而简化创建、部署和运行应用程序的过程。可以将Docker视为没有操作系统的虚拟机,它允许应用程序使用与它们运行的系统(宿主机)相同的内核。这有助于使Docker容器轻量化,并提高性能。
使用Docker容器化技术,可以确保应用程序的可复制性,这意味着不必处理“在机器上无法工作”的问题。此外,开发的容器具有高度的可移植性,允许轻松地从本地开发环境迁移到超级计算集群。
本文是一个实践指南,用于构建和运行一个通用Flask应用的Docker镜像。为了进一步简化这个过程并避免手动编写Docker命令,使用VS Code中提供的Docker扩展,它创建了一个包含这些命令的自动模板。
已经创建了一个包含简单Flask应用的GitHub仓库。这个仓库可以克隆到本地,用于构建Docker镜像。让首先了解这个仓库中的文件。
server.py
:这个Python脚本用于创建一个Flask应用,运行时会渲染包含在‘index.html’中的模板。
index.html
:在模板文件夹中,文件‘index.html’包含一个简单的模板,包含一个作为标题的单行文本。
requirements.txt
:这个文件包含了运行此应用所需的所有Python包。
gunicorn.sh
:尽管Flask内置了一个Web服务器,但它不适合生产环境,需要安装在可以通过WSGI协议与Flask连接的真实Web服务器后面。常见的选择是Gunicorn。这个shell脚本文件帮助启动Gunicorn服务器。脚本包含以下内容:
gunicorn server:app -b 0.0.0.0:5005 -- timeout 900
上述命令是启动服务器的Gunicorn命令,其中‘server’指的是构建的模块(server.py),而‘app’指的是Flask对象的变量名。命令中的‘-b’用于指定绑定服务器的套接字。由于某些应用程序需要比其他应用程序更长的时间来响应,可以显式设置‘timeout’为更高的数字(以秒为单位),以确保为应用程序加载提供更长的时间。
Dockerfile是一个创建文件,它有助于构建Docker镜像。这个文件包含指示Docker如何构建Docker镜像的指令。要构建Docker文件,在VS Code中打开‘server.py’文件,并使用Ctrl+Shift+P(Windows)或Cmd+Shift+P(Mac)打开命令面板。可以输入以下内容以获得Docker文件的标准模板:
>docker: add
然后选择‘Docker: Add Docker Files to Workspace’并选择‘Python’作为语言。将被提示选择应用程序的入口点;然后可以选择下拉菜单中的server.py文件的路径。将进一步被提示为应用程序提供一个端口(如5005)来运行。这创建了Dockerfile,如下所示:
# 有关更多信息,请参考 https://aka.ms/vscode-docker-python
FROM python:3.8-slim
EXPOSE 5005
# 防止Python在容器中生成.pyc文件
ENV PYTHONDONTWRITEBYTECODE=1
# 关闭缓冲,便于容器日志记录
ENV PYTHONUNBUFFERED=1
# 安装pip依赖
COPY requirements.txt .
RUN python -m pip install -r requirements.txt
WORKDIR /app
COPY . /app
# 创建一个非root用户,并添加访问/app文件夹的权限
# 有关更多信息,请参考 https://aka.ms/vscode-docker-python-configure-containers
RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app
USER appuser
# 在调试期间,此入口点将被覆盖。有关更多信息,请参考 https://aka.ms/vscode-docker-python-debug
ENTRYPOINT ["./gunicorn.sh"]
更改默认的CMD行为以下内容,以确保在运行Docker容器时加载gunicorn服务器:
ENTRYPOINT ["./gunicorn.sh"]
让回顾一下这个Dockerfile中包含的一些重要命令:
1) FROM python:3.8-slim
:它允许继承现有的镜像,安装一个Python镜像并将其安装在Docker镜像中。
2) EXPOSE 5005
:EXPOSE指令通知Docker容器在运行时监听指定的网络端口(5005)。
3) ENV PYTHONDONTWRITEBYTECODE=1
:这个环境变量阻止Python在容器中生成.pyc文件。
4) COPY requirements.txt.
:COPY是Docker文件命令,它将文件从本地源位置复制到Docker容器中的目标位置。在这种情况下,COPY命令将requirements.txt文件从本地目录复制到Docker容器中。
5) RUN python -m pip install -r requirements.txt
:此命令用于运行复制的requirements.txt文件,安装应用程序的所有必要依赖项,并将它们保留在容器中。
6) WORKDIR /app
:WORKDIR指令为任何RUN、CMD、ENTRYPOINT、COPY和ADD指令设置工作目录,这些指令在Dockerfile中跟在它后面。
7) ENTRYPOINT [“./gunicorn.sh”]
:Docker中的ENTRYPOINT指令用于设置容器启动时始终运行的可执行文件。因此,当Docker容器启动时,将运行gunicorn.sh文件。
Docker镜像是通过运行Docker命令(使用创建的Dockerfile)构建的。然后可以右键单击VS Code的资源管理器选项卡中的Docker文件,并选择‘构建镜像’选项。这有助于根据创建的Docker文件创建Docker镜像。
容器是Docker镜像的运行实例。可以通过转到VS Code的Docker选项卡来运行创建的Docker镜像。可以选择想要运行的镜像(在镜像下),然后开始运行它。现在可以使用以下URL在浏览器中打开应用程序:
http://localhost:port/
上述链接中的‘port’需要更改为在gunicorn.sh脚本中提供的端口号(5005)。这将给以下内容(即放在index.html文件中的文本):
数据科学家经常参与他们构建的模型的生产,因此学习如何使用Docker容器化应用程序变得至关重要。它确保了应用程序在任何机器上都能运行,如果它在机器上可以工作的话。它的容器具有高度的可移植性,允许轻松地从本地开发环境迁移到超级计算集群。它允许应用程序使用与它们运行的系统(宿主机)相同的内核。这有助于使容器轻量化,并提高性能。本文旨在提供Docker化简单Flask应用的实践指南。类似的流程可以扩展到Docker化任何开发人员构建的Flask应用程序。
博客马拉松
数据工程
Docker
Nibedita Dutta
Nibedita于2014年在IIT Kharagpur完成了化学工程硕士学位,目前担任高级数据科学家。在她目前的职位上,她致力于构建基于机器学习的智能解决方案,以改善业务流程。