如何使用在Docker镜像或新容器中不断变化的python库?
我组织我的代码在一个Python包(通常在一个虚拟的环境,如virtualenv
和/或conda
),然后通常调用:
python <path_to/my_project/setup.py> develop
以便我可以使用我的代码的最新版本。 由于我主要开发统计学或机器学习algorithm,所以我做了很多原型并每天更改我的代码。 然而,最近推荐的方式来运行在我有权访问的集群上的实验是通过docker。 我了解到docker工人,我想我对如何使它工作有一个粗略的想法,但是如果我的解决scheme是好的,或者如果有更好的解决scheme,我不太确定。
我认为第一个解决scheme是将数据复制到我的Docker镜像中的解决scheme:
COPY /path_to/my_project pip install /path_to/my_project
然后点安装它。 这个解决scheme的问题是,我必须每次都build立一个新的图像,看起来很傻,希望能有更好的东西。 要做到这一点,我想有一个bash文件,如:
#BASH FILE TO BUILD AND REBUILD MY STUFF # build the image with the newest version of # my project code and it pip installs it and its depedencies docker build -t image_name . docker run --rm image_name python run_ML_experiment_file.py docker kill current_container #not sure how to do get id of container docker rmi image_name
正如我所说,我的直觉告诉我这是愚蠢的,所以我希望有一个单一的命令的方式来做到这一点与Docker或一个单一的Dockerfile。 另外,请注意,命令应该使用-v ~/data/:/data
在完成训练时能够获取数据以及某些其他卷/装载(在主机中)写入。
我认为另一个解决scheme是拥有我的库在Dockerfile(因此在图像中)所需的所有python依赖关系或其他依赖关系,然后以某种方式在正在运行的容器中执行我的库的安装。 也许与docker exec [OPTIONS] CONTAINER COMMAND
为:
docker exec CONTAINER pip install /path_to/my_project
在正在运行的容器中。 之后,我可以运行我想用同一个exec命令运行的真实实验:
docker exec CONTAINER python run_ML_experiment_file.py
尽pipe如此,我仍然不知道如何系统地获取容器ID(因为我可能不想每次都查找容器ID)。
理想情况下,最好的概念解决scheme是简单地让Dockerfile从一开始就知道它应该挂载到哪个文件(即/path_to/my_project
),然后以某种方式在图像内部python [/path_to/my_project] develop
,这样它总会被链接到可能改变的python包/项目。 这样我就可以用一个docker命令运行我的实验,如下所示:
docker run --rm -v ~/data/:/data python run_ML_experiment_file.py
而不必每次都自己显式更新图像(包括不必重新安装应该是静态的图像部分),因为它总是与真实的库同步。 另外,有一些其他的脚本每次从头开始创build一个新的图像是不是我所期待的。 另外,如果可能的话,能够避免写任何bash是很好的。
我觉得我非常接近一个很好的解决scheme。 我会做什么,而不是每次我只是运行CMD
命令来做python开发,如下创build一个新的图像:
# install my library (only when the a container is spun) CMD python ~/my_tf_proj/setup.py develop
好处是只要我运行一个新的容器就可以安装我的库。 这解决了发展问题,因为重新创build一个新的形象需要很长的时间。 虽然我刚刚意识到,如果我使用CMD
命令,那么我不能运行给我的docker运行的其他命令,所以我其实是要运行ENTRYPOINT
。
现在唯一需要解决的问题就是我在使用卷时遇到问题,因为我无法成功链接到Dockerfile中的主机项目库 (由于某种原因,这似乎需要一个绝对path)。 我目前正在做(似乎不工作):
VOLUME /absolute_path_to/my_tf_proj /my_tf_proj
为什么我不能使用我的Dockerfile中的VOLUME命令进行链接? 我使用VOLUME的主要目的是在CMD命令尝试安装我的库时使我的库(以及此图像始终需要的其他文件)可访问。 容器启动时,是否可以随时使用我的库?
理想情况下,我只想在运行容器时自动安装库,并且如果可能的话,因为总是需要库的最新版本,所以在容器初始化时安装它。
作为一个参考现在我的非工作Dockerfile看起来如下:
# This means you derive your docker image from the tensorflow docker image # FROM gcr.io/tensorflow/tensorflow:latest-devel-gpu FROM gcr.io/tensorflow/tensorflow #FROM python FROM ubuntu RUN mkdir ~/my_tf_proj/ # mounts my tensorflow lib/proj from host to the container VOLUME /absolute_path_to/my_tf_proj # RUN apt-get update # apt-get install vim # RUN apt-get install -qy python3 RUN apt-get install -qy python3-pip RUN pip3 install --upgrade pip #RUN apt-get install -y python python-dev python-distribute python-pip # have the dependecies for my tensorflow library RUN pip3 install numpy RUN pip3 install keras RUN pip3 install namespaces RUN pip3 install pdb # install my library (only when the a container is spun) #CMD python ~/my_tf_proj/setup.py develop ENTRYPOINT python ~/my_tf_proj/setup.py develop
作为一个方面的评论:
另外,出于某种原因,它要求我RUN apt-get update
,以便能够在我的容器中安装pip或vim。 人们知道为什么吗? 我想这样做,因为万一我想用bash
terminal附加到容器,这将是非常有帮助的。
似乎Docker只是强迫你安装到容器中总是有最新版本的软件?
对于部署/分发,可以无缝地为你的软件包提供一个docker镜像。 如果不是图像,则需要将源代码转移到需要运行的环境中,将容器中的源代码configuration为容器内的源代码,以便它可以被构build等。出来了。
但为了方便起见,摆脱build立图像的手动步骤,可以考虑使用docker-compose。
docker-compose.yml可能看起来像这样:
ml_experiment: build: <path/to/Dockerfile> volumes: - ~/data/:/data command: ["python", "run_ML_experiment_file.py"]
现在要build立一个图像,并提出一个你只需要做的容器
docker-compose up --build
选项–build必须每次重build图像,否则docker-composeselect使用已经build好的图像
在开发过程中,IMO完全可以将hostdirectory映射/挂载到Docker容器中。 其余部分(python版本,其他依赖于你的库都可以正常的方式安装在docker容器中。
一旦稳定,我删除地图/安装,并将包添加到项目列表,以安装pip
。 我有一个单独的容器运行devpi
所以我可以devpi
安装软件包,无论我一直推到PyPI或只是推到我的本地devpi
容器。
即使您使用通用(但更有限)的python [path_to_project/setup.py] develop
也可以加快容器的创build速度。 在这种情况下,您的Dockerfile
应该如下所示:
# the following seldom changes, only when a package is added to setup.py COPY /some/older/version/of/project/plus/dependent/packages /older/setup RUN pip /older/setup/your_package.tar.gz # the following changes all the time, but that is only a small amount of work COPY /latest/version/of/project RUN python [path_to_project/setup.py] develop
如果第一个副本会导致更改/older/setup
下的文件,那么容器将从那里重build。
运行python ... develop
仍然有更多的时间,你需要重build/重新启动容器。 由于我的软件包全部也可以被复制到/链接到(除了被安装),这仍然是一个很大的开销。 我在容器中运行一个小程序,检查(挂载/映射)源是否改变,然后重新运行我正在开发/testing的任何东西。 所以我只需要保存一个新的版本并观察容器的输出。
- 当在Docker容器中打开搁置时,“ImportError:No module named _bsddb”
- dockerpythonAPI:我怎么知道什么时候实例准备好了?
- Docker中的Python日志logging类:日志不见了
- docker-py:是否可以将healthcheck命令添加到services.create?
- 在PyCharm 2016中configuration远程解释器Docker时,图像名称下拉列表为空
- Docker:通过共享PID命名空间从UID获取主机用户名
- 如何在一个docker容器中运行etcd之后启动一个python脚本?
- 运行ubuntu :: latest的DockerFile中的Python3
- 不能使用SIGKILL杀死Docker容器中的pid 1