在选择基础镜像时,考虑到镜像大小和安全性,Alpine Linux似乎是一个显而易见的选择。然而,对于Python应用程序来说,情况并非如此简单。Alpine使用musl——一个与大多数标准Linux发行版使用的glib不同的C库。这使得大多数编译的Pip wheels不兼容,因此在安装期间需要进行编译。实际上,在Alpine上设置任何非平凡的Python环境(具有多层依赖关系)所需的时间要比在更流行的发行版(如Debian或Ubuntu)上多得多。不仅如此,最终的镜像可能会更大,代码运行速度也可能更慢!
为了避开上述问题,选择基于Debian 10(Buster)构建的官方Python镜像的最小版本作为基础:python:3.8.8-slim-buster。
需要一个带有基本机器学习库和Jupyter Notebooks的镜像来处理实验。将把所有所需的库存储在app/requirements.txt文件中:
numpy==1.19.5
pandas==1.2.2
scikit-learn==0.24.1
matplotlib==3.3.4
jupyter==1.0.0
opencv-python==4.5.1.48
tensorflow-cpu==2.4.0
现在,让开始创建Dockerfile:
FROM python:3.8.8-slim-buster
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get -y install --no-install-recommends ffmpeg libsm6 libxext6 \
&& apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/*
首先,在切换到非交互模式后,安装了Python库所需的所有系统依赖项,并在之后进行了清理,以限制镜像大小。请注意,如果更改了requirements.txt,这些依赖项可能会有所不同。
ARG USERNAME=mluser
ARG USERID=1000
RUN useradd --system --create-home --shell /bin/bash --uid $USERID $USERNAME
使用USERNAME和USERID值的参数将允许在构建和执行期间替换它们。
COPY app/requirements.txt /tmp/requirements.txt
RUN pip3 install --no-cache-dir -r /tmp/requirements.txt \
&& rm /tmp/requirements.txt
然后,让配置Python环境。
USER $USERNAME
WORKDIR /home/$USERNAME/app
EXPOSE 9000
CMD ["jupyter", "notebook", "--ip", "0.0.0.0", "--port", "9000"]
最后,切换到新用户,并默认启动Jupyter Notebook(如果没有指定其他命令)。
在Linux上,应该始终使用一个预定的用户来运行容器。这确保了容器的内部进程以及保存到映射的主机驱动器的文件将有一个预期的所有者。在以下示例中,确保当前用户对构建镜像mld02_cpu_experiment时创建的所有文件具有适当的权限:
$ docker build --build-arg USERID=$(id -u) -t mld02_cpu_experiment .
提供的--build-arg USERID参数将用提供的值替换Dockerfile中预定义的USERID参数。
实际上,只需要在Linux上本地运行容器时才需要这样做。镜像中的默认值(1000)可能会在主机上引起麻烦,容器需要对包含在镜像中的用户文件夹或文件具有写入权限。在任何其他情况下,可以跳过此步骤。
构建完容器后,可以尝试运行它。假设已经下载并解压了示例代码,运行Jupyter Notebook实例:
$ docker run -p 9000:9000 -v $(pwd)/app:/home/mluser/app -v $(pwd)/data:/home/mluser/data --rm --user $(id -u):$(id -g) mld02_cpu_experiment
在Windows上:
$ docker run -p 9000:9000 -v %cd%/app:/home/mluser/app -v %cd%/data:/home/mluser/data --rm mld02_cpu_experiment
这里的参数有:
如果一切顺利,应该能够看到Jupyter Notebook启动的日志:
由于端口映射,应该能够在Web浏览器中使用http://localhost:9000(或上述日志中的URL)打开笔记本。