Creating Laravel Image with Docker Multi-Stage Builds
Docker: 18.09
Laravel: 6.9
在製作 Container Images
時,基本上 Images
的大小是越小越好,而瘦身的面向很多,在 Dockerfile
中使用 Multi-Stage Builds
也是方法之一。
Docker 在 17.05
以後提供了一個 Multi-Stage Builds
(多階段構建)功能,這個功能可以將整個產線的 Images
整合進同一個 Dockerfile
,讓其變為 Intermediate Image
(中繼映象檔),而後續的映象檔也可以取得中繼映象檔產生的 artifacts
(檔案),這樣一來便可以有效地控管流程及降低不必要的安裝。
Usage
以 Laravel
為例,要完整的部署 Laravel
,必須先經過 composer
及 npm
or yarn
安裝一些套件,但這些套件只負責安裝或編譯,在網站部署以後是不需要的。
最原始的作法,就是將從安裝到部署需要用到的東西都裝進去 Image
。
範例
# Base image
FROM php:7.4.1-apache
# Install npm
RUN apt-get update && apt-get install -y npm
# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Copy Laravel app to Container
COPY . .
# Composer Install
RUN composer install \
--ignore-platform-reqs \
--no-interaction \
--no-plugins \
--no-scripts \
--prefer-dist
# Npm install and Compile
RUN npm install \
&& npm run production
其實我們真正需要的只是特定的產物,因此可以使用 Multi-Stage Builds
,讓套件先在 Intermediate Image
安裝完成,最後再使用其產生的檔案就好了。
範例
# 使用 composer image 建立 vendor stage
FROM composer:1.9 as vendor
COPY database/ database/
COPY composer.json composer.json
COPY composer.lock composer.lock
RUN composer install \
--ignore-platform-reqs \
--no-interaction \
--no-plugins \
--no-scripts \
--prefer-dist
# 使用 node image 建立 nodejs stage
FROM node:10.18 as nodejs
RUN mkdir -p /app/public
COPY package.json webpack.mix.js /app/
COPY resources/sass/ /app/resources/sass/
COPY resources/js/ /app/resources/js/
WORKDIR ./app
RUN npm install && npm run production
# Base image
FROM php:7.4.1-apache
COPY . /var/www/html
# 拿出 vendor stage 安裝的檔案
COPY --from=vendor /app/vendor/ /var/www/html/vendor/
# 拿出 nodejs stage 安裝及編譯完成的檔案
COPY --from=nodejs /app/public/js/ /var/www/html/public/js/
COPY --from=nodejs /app/public/css/ /var/www/html/public/css/
COPY --from=nodejs /app/mix-manifest.json /var/www/html/mix-manifest.json