问题描述
有一个第三方的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镜像时,你可以使用两个构建阶段或使用构建工具来实现两步构建的过程。这样可以避免在容器中存在不必要的内容,并确保构建是可复制的。
以上是两种常见的解决方案,你可以根据自己的需求选择适合的方法来构建镜像。