在 Docker 图像中压缩大文件夹然后在入口点提取它们有什么缺点吗?

Any downsides to compressing large folders in a Docker Image then extracting them in the entrypoint?

笼统的问题

压缩 Docker 图像中的大文件夹然后在图像入口点的容器级别提取它们是否有任何缺点?

缺点:

优点:

示例docker文件:

FROM some/image:latest
COPY ./venv.tar.gz .
COPY ./some_python_script.py .
SHELL ["/bin/bash", "-c"]
 
  # if directory venv does not exist: extract it to root then remove the tar file
ENTRYPOINT  [ ! -d "venv" ] && tar xzf venv.tar.gz && rm venv.tar.gz || \ 
  # else: it already exists so we don't have to waste time doing it again
  echo 'venv already extracted from tar' && \
  # these always run
  source venv/bin/activate && \
  cd /app && \
  python "some_python_scipt.py"

我为什么要问

我已经 docker 化了整个 PyTorch 地理空间训练应用程序,不包括数据。然而,地理空间训练包非常庞大,更不用说 PyTorch 和 Cuda 库的大小了。我的图像的虚拟环境单独为 10.9GB,导致图像总大小为 11.5GB。这也是在多阶段构建中使用 conda-pack 优化的 v-env。预先压缩它们将图像大小减小到 5.2GB。

运行 容器显然最终变成了原来的 11.5GB 而它是 运行。然而,缩小的图像尺寸使得管理起来更容易,尤其是在从 docker 集线器推拉时的速度方面。

举例说明压缩的 conda 虚拟环境的完整要点:https://gist.github.com/NoahTarr/cdc0af59ebc84fc9d936eece35ebfaf7

我建议此设置存在三个问题:

  1. 就本地磁盘 space 而言,这将需要 1.5 倍的存储空间 space 到 运行 容器的单个实例,然后每增加一个实例将需要额外的 space 等于整个虚拟环境的(大)大小。也就是说,您需要一份压缩的 venv 副本,以及每个容器的一份未压缩的 venv 副本。如果未压缩的 venv 在图像中,则所有容器只需要一份它的副本。

  2. 解压缩一个大的 tar 文件需要时间,这可能会使您的容器 startup 明显变慢。

  3. 我遇到了实际问题 docker pushdocker pull 大于 1 GB 的单个层。您可以使用一些技巧来使各个图层变小,例如 RUN pip install pytorchRUN pip install -r requirements.txt 之前。使用此设置,您别无选择,只能拥有一个 5 GB tar文件层。

综上所述,我相信这种方法会从根本上奏效;再次,假设您可以 docker pushdocker pull 成功。我要做的一个改变是将复杂的 ENTRYPOINT 行分解成一个单独的 shell 脚本:

#!/bin/sh
# entrypoint.sh

# Unpack the virtual environment if it doesn't already exist
if [ ! -d venv ]; then
  tar xzf venv.tar.gz
else
  echo 'venv already extracted from tar'
fi

# Add the virtual environment into $PATH
. venv/bin/activate

# Run the main container CMD
exec "$@"
# Dockerfile
...
WORKDIR /app
ENTRYPOINT ["./entrypoint.sh"]
CMD ["python", "some_python_script.py"]

这将使您可以执行 docker run --rm your-image ls venv/python3.10/site-packages 之类的操作来查看展开的树内部,而无需实际 运行 启动您的主应用程序。