问题描述
想要将他的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更改时,您不希望重新构建应用程序。)