将文件复制到Docker镜像中还是使用挂载卷

167次阅读
没有评论

问题描述

想要将他的PHP应用程序Docker化并部署到生产环境中。他的应用程序结构如下:

api|
+-- src
+-- config
+-- vendor
+-- tests
+-- public

他需要将api/*嵌入到容器中,但对于最佳方法感到困惑。他提出了两种方法:
1. 使用一个轻量级的多阶段Docker镜像(大约85MB,但可以进一步优化)。
2. 使用挂载卷(docker-compose.yml)。

他看到很多Docker镜像在Dockerfile中使用COPY ..指令而不是挂载卷。他认为COPY适用于复制小的配置文件(或编译语言的小型构建),但不适用于保持镜像小的优化(Docker的基本规则)。

他想知道是否有什么遗漏?例如,从开发环境外部处理挂载卷是否是一种不好的做法?

解决方案

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

方案1

根据非开发环境的标准做法,将应用程序代码复制到镜像中,并在那里设置标准的CMD
以下是这样做的几个重要优点:
– 您可以直接在目标系统上运行Docker镜像,无需单独复制Docker镜像和应用程序代码。
RUN composer install仅在构建过程中运行一次。command: composer install ...在每次重新启动时运行,这会更慢,使用网络带宽,并且可能失败。
– 如果为每个镜像提供唯一的标签,您可以通过将标签改回来轻松回滚到较早的镜像。使用卷挂载很难做到这一点。
– 在所有环境中,您将以相同的镜像运行docker run;您不需要担心应用程序的主机目录副本在某个系统上略有不同。

对于您提出的COPY与挂载卷的选择,我建议相反的选择:将应用程序代码复制进去,并使用挂载卷来处理配置文件和其他不是”您的代码”但需要直接从主机访问的内容。(当应用程序更改时,您确实希望重新构建应用程序;但当数据库URL更改时,您不希望重新构建应用程序。)

以下是一个示例Dockerfile

FROM php:7.4-fpm-alpine AS base
WORKDIR /var/www/html
ENV COMPOSER_ALLOW_SUPERUSER 1
RUN apk update && \
  docker-php-ext-install mysqli tokenizer pdo_mysql && \
  curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

FROM base AS dev
COPY xdebug.ini /usr/local/etc/php/conf.d/xdebug-dev.ini
RUN apk add --no-cache --virtual .phpize-deps $PHPIZE_DEPS && \
  pecl install xdebug-2.9.1 && \
  docker-php-ext-enable xdebug && \
  touch /tmp/xdebug.log && \
  chmod -R 666 /tmp/xdebug.log && \
  apk del -f .phpize-deps

方案2

如果文件很少更改,则将其复制到镜像中,并理解如果需要修改它们,则需要重新构建镜像。
如果需要频繁更改文件,或者存储有关文件的某种状态(并将其与将来的容器实例重用),则将其作为挂载卷。

请注意,没有特定的规则要求Docker镜像非常小;我遇到的唯一实际问题是多GB的镜像在网络传输时不好。实际上,我建议您在COPY与挂载卷的选择上做出相反的选择:将应用程序代码复制进去,并使用挂载卷来处理配置文件和其他不是”您的代码”但需要直接从主机访问的内容。(当应用程序更改时,您确实希望重新构建应用程序;但当数据库URL更改时,您不希望重新构建应用程序。)

正文完