當我們在開發專案時,往往會發現現成的 image 無法完全符合我們的需求。這時就可以透過自訂的 Dockerfile 來擴充、修改這些 image,進而產出屬於我們的專案容器環境。
就是把專案所需的環境寫成一份可以被版控、可重現、可移植的檔案,這也是 Docker 為什麼能達成「環境一致」的核心原因。
其實說穿了,Dockerfile 就是照著 Docker 能理解的格式語法,一行行地指定「這個 image 應該具備什麼樣的環境與工具」。
FROM php:8.3-fpm-alpine3.20 AS app
這行代表我們的自訂 image 是以官方 PHP 8.3 的 Alpine Linux 版本為基礎。使用 Alpine 可以減少 image 的大小,適合部署環境。
AS app 是給這個階段起個名字,方便之後引用。
FROM app AS build
這是 Docker 的多階段建構(multi-stage build)技巧。這裡表示我們要「以剛剛命名為 app 的 image」為基礎,建立一個名為 build 的階段。
接下來會在這個階段中安裝 PHP 擴充套件與 composer 套件。
WORKDIR /www
設定 container 內的預設工作目錄為 /www,後續的命令會以此為根目錄執行。
RUN set -eux; \
apk add --no-cache \
autoconf \
ca-certificates \
curl \
gcc \
g++ \
make \
libpng-dev \
zlib-dev \
libzip-dev \
linux-headers \
gmp-dev;
這段透過 Alpine 的套件管理工具 apk 安裝了建構 PHP 擴充套件所需的工具與開發函式庫(例如:libzip-dev 是為了安裝 PHP 的 zip 擴充)。
RUN set -eux; \
docker-php-ext-install -j$(nproc) \
gd \
zip \
pdo_mysql \
bcmath \
gmp ;
這段是使用 PHP 官方 image 內建的指令 docker-php-ext-install,用來安裝常見的 PHP 擴充套件,這些模組是 Laravel 等框架常用的。
WORKDIR /tmp/composer
COPY --from=composer:2.2 /usr/bin/composer /usr/local/bin/composer
COPY composer.* /tmp/composer/
這裡先切換到 /tmp/composer 目錄(在 container 中),接著:
並把本機的 composer.json 與 composer.lock 複製進 container,準備進行依賴安裝
RUN set -eux; \
composer install --no-autoloader --no-ansi --no-progress --no-dev;
這是執行 composer install 來安裝生產環境所需的套件(不含 dev 套件),而且為了加速建構過程,略過 autoloader 的生成與格式化輸出。
FROM app
這是新的 build 階段,會使用之前定義過的 app 作為基礎(也就是乾淨、尚未做過任何安裝的 PHP + Alpine 環境)。
接著將上一個 build 階段建好的檔案與設定複製進來:
COPY --from=build /usr/local/lib/php/extensions /usr/local/lib/php/extensions
COPY --from=build /usr/local/etc/php /usr/local/etc/php
COPY --from=build /usr/lib /usr/lib
COPY --from=composer:2.2 /usr/bin/composer /usr/local/bin/composer
這樣就不需要在這個 image 再次安裝任何東西,節省空間與建構時間。
WORKDIR /www
COPY --from=build /tmp/composer/vendor /www/vendor
COPY . .
COPY . . 是將本地所有專案檔案複製進 container
COPY --from=build
則是將剛剛安裝好的 composer 套件複製進來,避免在 production image 中重複執行 install
RUN set -eux; \
composer dump --optimize --no-ansi;
這會重新生成 optimized autoloader,讓 Laravel 在執行時效能更佳。
使用多階段建構(multi-stage build)的好處包括: