Docker镜像的两步构建

41次阅读
没有评论

问题描述

有一个第三方的PHP应用程序需要安装到一个容器中。该应用程序没有包含其依赖项。提供了一个脚本来自动安装依赖项,但它依赖于一些在我的基础镜像中不可用的工具(包括通用工具如unzip以及一些PHP特定的工具如composer)。这些工具只在依赖项安装期间需要,安装完成后就不再需要了。
一个简单的解决方案是在Dockerfile的RUN部分安装所需的工具并运行安装脚本。但我不想在镜像中添加只在构建镜像时有用的软件。

RUN apt-get update && apt-get install --yqq unzip
RUN wget https://getcomposer.org/download/1.8.3/composer.phar
RUN php installer.php

这样做会使容器中存在未使用的工具,并可能导致某些文件(如php.ini)发生不可预料的更改。
另一种解决方案是在主机上执行安装,并将应用程序及其依赖项与容器一起COPY进去。但我希望构建是可复制的。

COPY app/ ./

解决方案

请注意以下操作注意版本差异及修改前做好备份。

方案1

你可以使用Dockerfile中的两个构建阶段(multistage build)来避免在容器中存在不必要的内容。第一阶段的任何内容在移动到第二阶段之前都会被删除。具体操作如下:

FROM whatever as build-stage
WORKDIR /app
RUN apt-get update && apt-get install -y unzip
RUN wget https://getcomposer.org/download/1.8.3/composer.phar
RUN php installer.php

FROM whatever as production-stage
COPY --from=build-stage /app ./

在上面的示例中,我们使用了两个构建阶段。第一阶段使用build-stage作为标识符,并在其中进行依赖项的安装。第二阶段使用production-stage作为标识符,并从第一阶段复制应用程序及其依赖项到/app目录下。
这样做可以确保在第二阶段中只有必要的内容,并且不会在容器中留下不必要的工具和文件。

方案2

另一种方法是使用构建工具或脚本来控制构建过程。你可以在主机上执行安装和构建,并将构建好的应用程序及其依赖项复制到容器中。这样可以确保构建是可复制的。
以下是一个简单的bash脚本示例,可以在主机上执行安装和构建:

#!/bin/bash
# 安装所需的工具
apt-get update && apt-get install -y unzip
wget https://getcomposer.org/download/1.8.3/composer.phar
php installer.php
# 复制应用程序及其依赖项到容器中
docker cp app/ container_name:/app

在这个示例中,我们首先在主机上安装所需的工具,并执行安装脚本。然后,使用docker cp命令将应用程序及其依赖项复制到容器中的/app目录下。
请注意,这种方法需要确保主机和容器之间的文件路径和目录结构保持一致,以便正确复制文件。

总结

在构建Docker镜像时,你可以使用两个构建阶段或使用构建工具来实现两步构建的过程。这样可以避免在容器中存在不必要的内容,并确保构建是可复制的。
以上是两种常见的解决方案,你可以根据自己的需求选择适合的方法来构建镜像。

正文完