用Docker打包Python运行环境
虽然Docker作为部署环境打包镜像的工具,和我的科研并没有直接的关系。但我觉得在项目中运用Docker来打包环境依赖也可以大大提高工作效率,于是准备专门学习一下Docker。
1. Docker基础
1.1 Docker架构
Docker使用客户端服务器架构。Docker客户端与Docker守护进程会话,后者复杂构建、运行和分发Docker容器的繁重工作。Docker客户端和守护程序可以在同一系统运行,也可以将Docker客户端连接到远程Docker守护进程。Docker客户端和守护程序通过REST API(采用一种简洁的URL风格规范)通信,其底层基于UNIX套接字或网络接口。其架构示意图如下:

其中,Docker 守护程序 (dockerd) 监听Docker API 请求并管理Docker对象,例如镜像、容器、网络和磁盘分卷。守护进程还可以与其他守护进程通信以管理Docker服务。而Docker 客户端 ( docker) 是用户与 Docker 交互的主要方式。当我们使用诸如docker run之类的命令时,客户端会将这些命令发送到dockerd执行它们。docker命令使用 Docker API。Docker 客户端可以与多个守护进程通信。
Docker注册表存储Docker镜像(你可以类比为Maven的repo)。Docker Hub 是一个任何人都可以使用的公共注册表,并且 Docker 默认配置为在Docker Hub上查找镜像。我们也可以运行自己的私有注册表。我们可以调用docker pull从注册表中拉取镜像。当我们docker run命令时,系统会从先从本地寻找镜像,如果本地找不到,则会从Docker Hub拉取。当我们使用docker push命令时,镜像会被推送到我们配置的注册表中。可以看出,Docker镜像版本控制和Git类似。
1.2 Docker对象
当我们在使用Docker时,我们就正在创建和使用镜像、容器、网络、磁盘分卷、插件和其他对象了。下面简要介绍一下其中的镜像和容器对象。
镜像 镜像可视为一个只读模板,其中包含创建 Docker 容器的指令。通常,一个镜像基于另一个镜像,并带有一些额外的自定义。例如可以基于现有的ubuntu镜像,来构建安装有其它应用程序的镜像。要构建我们自己的镜像,需要使用简单的语法创建一个Dockerfile ,用于定义创建和运行镜像所需的步骤。
容器
容器是镜像的可运行实例(类似于进程和程序的关系)。我们可以使用 Docker API 或 CLI 创建、启动、停止、移动或删除容器。我们可以将容器连接到一个或多个网络。
2. 启动Docker进程并运行镜像
2.1 启动Docker守护进程
Linux
Linux上的docker同时包括客户端和守护进程两部分,故安装好docker后,只需要用以下命令即可运行docker守护进程:
$ sudo service docker start # Ubuntu/Debian
如果您是RedHat/Centos,则需要运行:
$ sudo systemctl start docker
MacOS
然而,在Mac上docker二进制仅仅是client部分(因为docker守护进程使用了一些Linux内核的特点),我们不能使用它来运行docker守护进程。所以,我们还需要安装docker-machine来创建一个虚拟机并将守护进程运行在上面。如果你的Mac上已经有brew,可以直接运行以下命令安装:
brew install docker-machine
然后启动docker-machine:
(base) orion-orion@MacBook-Pro ~ % brew services start docker-machine
==> Successfully started `docker-machine` (label: homebrew.mxcl.docker-machine)
2.2 运行镜像
之后我们就可以尝试运行Docker镜像了。比如我们下面用docker run命令运行docker/getting-started镜像:
(base) orion-orion@MacBook-Pro ~ % docker run -d -p 80:80 docker/getting-started
Unable to find image 'docker/getting-started:latest' locally
latest: Pulling from docker/getting-started
9981e73032c8: Pull complete
e5f90f35b4bc: Pull complete
ab1af07f990a: Pull complete
bd5777bb8f79: Pull complete
a47abff02990: Pull complete
d4b8ebd00804: Pull complete
6bec3724f233: Pull complete
b95ca5a62dfb: Pull complete
Digest: sha256:b558be874169471bd4e65bd6eac8c303b271a7ee8553ba47481b73b2bf597aae
Status: Downloaded newer image for docker/getting-started:latest
cc167092ff76941a25fe51da25fbbfe6a0a70cc07171fa5f56707f3bf7383e6a
可以看到由于没有在本地找到docker/getting-started:latest镜像,Docker从远处Docker Hub注册表上pull下来。
我们用docker ps查看目前在运行的镜像实例(即容器):
(base) orion-orion@MacBook-Pro ~ % docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cc167092ff76 docker/getting-started "/docker-entrypoint.…" 29 minutes ago Up 29 minutes 0.0.0.0:80->80/tcp epic_lehmann
可以用docker stop终止镜像运行:
(base) orion-orion@MacBook-Pro ~ % docker stop cc167092ff76
cc167092ff76
(base) orion-orion@MacBook-Pro ~ % docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
用docker images查看有哪些本地镜像:
(base) orion-orion@MacBook-Pro ~ % docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker/getting-started latest 157095baba98 4 weeks ago 27.4MB
3. 用Docker打包Python环境
接下来我们看如何用Docker打包一个Python环境。
首先,我们编写一个Python小Demo:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(-10, 10, 0.01)
y = x**2
plt.plot(x, y)
plt.savefig("/out/quad.png")
# 此处的/out为容器内的绝对路径,无需手动创建,
# 后面我们会设置挂载参数自动生成该目录
然后我们编辑好requirements.txt:
numpy==1.21.3
matplotlib==3.4.3
再编辑好Dockerfile:
# syntax=docker/dockerfile:1
FROM python:3.9-slim-buster
WORKDIR /draw_quad
COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt
COPY . .
CMD [ "python3", "draw_quad.py"]
我们来细细看Dockerfile每一部分。
首先,# syntax是指解析器指令。这里使用docker/dockerfile:1,即始终指向版本1语法的最新版本。
之后,我们需要告诉Docker我们在应用中使用什么基础镜像。由于Docker镜像可以从其它镜像继承,因此我们并不构建自己的基础镜像,而是使用官方的Python镜像,即FROM python:3.9-slim-buster。
然后我们建立一个工作目录/draw_quad,即后续命令的默认执行路径。这样我们后面就不必输入完整的文件路径,而是可以使用基于工作目录的相对路径。如COPY requirements.txt requirements.txt其实是将requirements(第一个参数)复制到到工作目录中(第二个参数)。
接着,我们将requirements.txt 放入镜像后,就可以使用RUN命令来执行pip3 install了,这和我们在本地安装的经验完全相同,不过这次是将模块安装到镜像中。
此时,我们有了一个基于Python 3.9的镜像,并且已经按照了我们的依赖项。下一步我们继续用COPY
命令将源代码添加到镜像中,即DockerFile中的COPY . .。
之后,我们还需要Docker当我们的镜像在容器中运行时我们想要执行什么命令,即CMD [ "python3", "draw_quad.py"]。
最终的项目目录如下:
draw
|____ draw_quad.py
|____ requirements.txt
|____ Dockerfile
然后我们就可以构建docker镜像了(用--tag参数指定镜像名称):
(base) orion-orion@MacBook-Pro draw % docker build --tag draw .
[+] Building 9.1s (14/14) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 37B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> resolve image config for docker.io/docker/dockerfile:1 4.9s
=> CACHED docker-image://docker.io/docker/dockerfile:1@sha256:443aab4ca21183e069e7d8b2dc68006594f40bddf1b15bbd83f5137bd 0.0s
=> [internal] load build definition from Dockerfile 0.0s
=> [internal] load .dockerignore 0.0s
=> [internal] load metadata for docker.io/library/python:3.9-slim-buster 3.9s
=> [1/5] FROM docker.io/library/python:3.9-slim-buster@sha256:830e161433edfe047a23ebc99c12ee0eb1dc0a50e6b5f1c98e869ac27 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 594B 0.0s
=> CACHED [2/5] WORKDIR /draw_quad 0.0s
=> CACHED [3/5] COPY requirements.txt requirements.txt 0.0s
=> CACHED [4/5] RUN pip3 install -r requirements.txt 0.0s
=> [5/5] COPY . . 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:18f3a254f4ce46faa17142ece6bfd442e9157e79510ca60a789ab4d4b1a12498 0.0s
=> => naming to docker.io/library/draw 0.0s
我们输入docker images命令可以看到名称为draw的镜像已经构建成功。
(base) orion-orion@MacBook-Pro Draw % docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
draw latest f1fc30becc34 46 seconds ago 251MB
然后就可以运行镜像了(包含文件系统挂载操作):
(base) orion-orion@MacBook-Pro draw % docker run -d -v ${PWD}/out:/out draw
0e04d81d254fcd963924ee2492b82a6c895789525f09943b43ce0b46ac0d63a9
注意,${PWD}/out为宿主机的目录,意思为当前目录下的out文件夹,如果不存在则会自动为我们创建。/out为该容器中的绝对路径,在容器启动会自动创建/out目录。
我们可以看到,quad.png成功在宿主机当前目录下的out文件中生成:
(base) orion-orion@MacBook-Pro draw % ls out
quad.png
参考
- [1] https://docs.docker.com/get-started/overview/
- [2] https://docs.docker.com/language/python/build-images/
- [3] https://stackoverflow.com/questions/31448821/how-to-write-data-to-host-file-system-from-docker-container
- [4] https://stackoverflow.com/questions/58205178/python-docker-filenotfounderror-errno-2-no-such-file-or-directory
- [5] https://www.cnblogs.com/ivictor/p/4834864.html
用Docker打包Python运行环境的更多相关文章
- Docker构建Python Web环境
出于寻找Docker对Python相关项目部署的学习,找到腾讯课堂NEXT公开课中[Docker构建Python Web环境]的课程,本文对其进行内容梳理及知识点汇总. 该课程总计6小时左右,是个适合 ...
- 自动化测试 Appium之Python运行环境搭建 Part2
Appium之Python运行环境搭建 Part2 by:授客 QQ:1033553122 实践环境 参见 Appium之Python运行环境搭建 Part1 环境部署 1.安装Android SDK ...
- 自动化测试 Appium之Python运行环境搭建 Part1
Appium之Python运行环境搭建 Part1 by:授客 QQ:1033553122 实践环境 Win7 Python 3.4.0 JAVA JDK 1.8.0_121 node.js8.11. ...
- 用 virtualenv 创建隔离的 Python 运行环境
以 Ubuntu 14.04 系统为例,安装的 Python 和 Python3 分别是 2.7.6 和 3.4.3, 但有些项目,有些模块要求特定的 Python 版本.而当前系统默认的 Pytho ...
- 使用Docker搭建Tomcat运行环境
1 准备宿主系统 准备一个 CentOS 7操作系统,具体要求如下: 必须是 64 位操作系统 建议内核在 3.8 以上 通过以下命令查看您的 CentOS 内核: # uname -r 2 安装Do ...
- 隔离python 运行环境和Pycharm 设置代码同步
隔离python 运行环境 查看当前有哪些虚拟环境:workon 进入虚拟环境:workon django 退出虚拟环境:deactivate 创建虚拟环境: mkvirtualenv -p /usr ...
- Python学习笔记(四十三)virtualenv (创建一套“隔离”的Python运行环境)
摘抄自:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001432712108 ...
- Win10下使用VSCode配置python运行环境
VSCode配置python运行环境 安装python 到官网下载python,直接安装即可,在安装过程中可以选择将python加入环境变量 安装VSCode 官网下载,直接安装 配置 安装pytho ...
- 使用virtualenv为应用提供了隔离的Python运行环境
在开发Python应用程序的时候,系统安装的Python3只有一个版本:3.4.所有第三方的包都会被pip安装到Python3的site-packages目录下. 如果我们要同时开发多个应用程序,那这 ...
随机推荐
- remote debug 的详细配置
一.remote debug 的简单介绍 何为远程debug,项目写完后就需要进入到测试环节,将代码打包发布到测试环境(服务器)上.这时候测试人员测试出一个缺陷(bug).由于代码已经发布到测试环境, ...
- WEB架构深度优化之PHP
一.PHP引擎缓存加速优化(4种) 1.eAccelerator 2.XCache 3.APC 4.Zend 二.使用tmpfs作为缓存加速缓存的目录(可用rc.local或fstab来自动挂载) m ...
- 学习RabbitMQ(三)
1 用户注册后(会立即提示注册成功),过一会发送短信和邮件通知 发布/订阅模型 以上模式一般是用户注册成功后,写入一条数据到mysql,在发送一条消息到MQ! 如果不用消息中间件(或者简单的做成异步发 ...
- Eclipse 从SVN检出项目之《文件夹 “” 已不存在 》
1.eclipse 从svn检出项目 报文件夹不存在, 参考博客 https://blog.csdn.net/wenbsu/article/details/80965680 2.You need to ...
- WordPress 网站开发“微信小程序“实战(二)
原文链接:https://devework.com/wordpres...,转载请用明链注明来源,谢谢! 本文是"WordPress 开发微信小程序"系列的第二篇,本文记录的是开发 ...
- 微信小程序调研
小程序入口 微信发现,小程序 公众号主体查看小程序 好友分享,群分享 公众号自定义菜单跳转 APP页面跳转 第三方服务 附近的小程序 扫普通链接二维码打开小程序 需要后台开启功能,开启后,用户在微信& ...
- IDEA中Tomcat找不到war包导出按钮解决办法
解决办法 (1) 打开Idea,点击File,然后点击Project Structure-,进入项目结构 (2) 具体步骤看下图: (3) 具体步骤如下图: (4) 具体步骤如下图: (5) 问题解决 ...
- MySQL外键约束On Delete和On Update的使用
On Delete和On Update都有Restrict,No Action, Cascade,Set Null属性.现在分别对他们的属性含义做个解释. ON DELETE restrict(约束) ...
- 实战-DRF快速写接口(认证权限频率)
实战-DRF快速写接口 开发环境 Python3.6 Pycharm专业版2021.2.3 Sqlite3 Django 2.2 djangorestframework3.13 测试工具 Postma ...
- 自己写一个简单的LinkedList
单链表 推荐阅读:https://www.cnblogs.com/zwtblog/tag/源码/ 哨兵节点: 哨兵节点在树和链表中被广泛用作伪头.伪尾等,通常不保存任何数据. 我们将使用伪头来简化我们 ...