在软件开发中,经常会遇到需要为不同的项目维护不同版本的Python环境和包。这不仅耗时,而且一旦出错,整个应用可能就会停止工作。传统的虚拟环境虽然可以解决部分问题,但在跨系统部署时仍然需要重复创建环境。为了解决这个问题,可以使用容器技术。容器可以为每个应用创建一个隔离的环境,互不干扰。本文将介绍如何在Docker中创建这些隔离的Python环境,并探讨如何通过Visual Studio Code访问和修改容器中的代码。
Docker是一个全球使用的开源平台,用于创建容器。这些容器与宿主环境隔离运行,即容器不会与它们运行的宿主系统交互。例如,如果正在处理两个需要不同版本的Python的应用,可以创建两个具有不同Python版本的Python容器,这些容器将运行应用。这些容器不仅与宿主隔离,而且彼此之间也是隔离的,即一个容器不会与另一个容器交互(除非希望它们这样做,但那是另一种情况)。
在本节中,将创建第一个隔离Python环境容器。为此演示,将使用Python开发一个Web应用。Python中有许多Web框架;选择了Flask。让创建一个简单的flask app.py文件。
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello, Docker'
if __name__ == "__main__":
app.run(debug=True)
运行此代码将启动服务器。输出将在本地主机服务器上显示,如下所示:
在本节中,将编写Dockerfile以创建容器。Dockerfile是一个文本文件,包含构建映像所需的命令。让看看这是如何完成的。
FROM python:3.10-slim
WORKDIR /flask_app
COPY . .
RUN pip install -r requirements.txt
ENV FLASK_DEBUG=1
EXPOSE 5000
CMD ["flask","run","--host=0.0.0.0"]
将在现有的python映像python:3.10-slim上创建容器,因此在Dockerfile中使用了FROM语句。接下来,在容器中创建了一个名为flask_app的文件夹,这将是工作目录,其中将包含flask_app。
接下来是COPY源路径目标路径。由于在包含flask应用程序(app.py)和requirements.txt的目录中创建Dockerfile,因此使用点(.)作为源路径,并且由于将这些文件复制到flask_app中,保留了点(.)作为目标路径。让再举一个例子,如果想将flask应用复制到flask_app内的文件夹中,那么将写入类似COPY源路径./new_folder的内容。
在容器中需要做的第一件事是使用pip安装requirements.txt中的依赖项,这是通过RUN命令完成的。还设置了flask调试为真,稍后会更多地讨论这个问题。然后暴露了容器内的端口:5000到外部,即宿主。无论何时运行容器,都需要运行flask应用。因此,向CMD传递了flask run命令。在这里,还将主机更改为0.0.0.0。默认情况下,无法从宿主访问在容器中运行的服务器。因此,将主机更改为0.0.0.0,以便可以访问它。
已经创建了Dockerfile。现在需要构建映像。为此,将使用docker build命令。在终端中,需要转到Dockerfile所在的目录;然后,需要输入以下内容:
docker build -t flask_env .
-t选项意味着用于命名映像的标签;在这里,将映像命名为flask_env。点(.)表示Dockerfile所在的文件路径。由于在Dockerfile所在的目录中,使用点(.)作为源路径。
运行此命令后,映像将被创建并命名为flask_env。可以使用docker image ls命令检查此映像。如果安装了Docker Hub,可以在Docker Hub中检查它。
让通过运行flask_env映像来测试它。在运行之前,需要将宿主系统中的app.py绑定到容器中的app.py。这样做的作用是,每当在宿主系统中对app.py进行更改时,容器中flask_app文件夹中的app.py也会更改。现在让运行容器:
docker run -p 5000:5000 -v C:/Users/Main//Desktop/python_docker_env:/flask_app flask_env
在这里,使用-p选项,将容器的端口:5000定向到宿主的端口:5000,这样就可以使用容器中运行的服务器。使用-v选项,将包含app.py的宿主系统文件夹挂载到容器中包含app.py的flask_app文件夹。
让尝试更改宿主操作系统中的app.py,以确保容器中的app.py也被更改,并且flask应用重新启动以反映服务器中的这些更改。为此,需要在Flask中启用调试模式。这就是为什么在Dockerfile中设置了ENV FLASK_DEBUG=1的原因。
现在让通过将宿主中的app.py中的Hello Docker更改为Hello Flask App来测试这一点。如果重新加载页面,然后可以看到更改。因此,很明显宿主flask文件夹被挂载到了容器flask文件夹。
最后,可以将宿主app.py连接到容器中的app.py,一切似乎都在正常工作。现在,如果宿主系统Python不包含Flask包呢?或者如果在另一个不包含flask包的系统中运行容器呢?这将在编写代码时引起问题。因为知道,在VS Code中,当在Python中导入库时,VS Code为提供了自动代码补全。这种自动代码补全只适用于安装在Python中的模块。因此,如果缺少Flask,就无法使用VS Code的自动补全功能。
但是有一个解决方案。Visual Studio Code为提供了直接访问容器中的app.py的权限;然后可以使用自动代码功能。为此,需要在VS Code中安装Docker和Dev Container扩展。这些扩展允许将Docker容器用作全功能的开发环境。
现在在左下角,可以找到打开远程窗口图标>打开新文件夹。将找到flask_app文件夹并点击它。现在终于能够访问位于容器中的app.py。
不能立即使用VS Code自动补全功能。为此,需要在新打开的VS Code工作区中安装Python扩展。安装后,将能够使用自动代码补全功能。
现在flask应用与宿主系统完全隔离。可以通过VS Code访问它,修改代码,并在服务器上看到更改的结果。通过这种方式,容器在创建隔离环境方面确实非常有用。当不使用它们时,可以移除它们。