Halo Talenta Digital! Selamat datang kembali di blog Ruang Developer, kali ini kita akan belajar bagaimana cara menggunakan multi stage build saat membuat docker image untuk project laravel kita. Untuk mengikuti materi ini, saya harap kamu sudah mengetahui apa itu docker ya. Oke, langsung kita mulai.

Dockerfile

Ketika kita ingin membuat docker image, kita menuliskan perintah-perintah yang digunakan untuk membangun image yang ingin kita buat dalam sebuah file bernama Dockerfile. Di dalam file Dockerfile, kita menggunakan sebuah base image sesuai dengan stack teknologi project kita. Misalnya, ketika kita membuat image untuk project laravel, maka kita bisa menggunakan base image dari apache. Ketika project kita menggunakan Node JS, maka kita menggunakan base image dari Node. Berikut ini contoh Dockefile untuk project Node JS.

# Menggunakan base image node:alpine
FROM node:alpine
# Membuat directory app, setting working directory
WORKDIR /usr/src/app
# Copy file package.json dan package-lock.json (jika ada)
COPY package*.json ./
# Menginstal dependency
RUN npm install
# Bundle source
COPY . .
# Expose port (for documentation)
EXPOSE 3000
# Run the app
CMD [ "node", "src/app.js"]

Apa Itu Multi Stage Build?

Multi stage build adalah menggunakan lebih dari satu statement FROM dalam Dockerfile. Tiap statement FROM menggunakan base image yang berbeda sesuai dengan stack yang digunakan. Pada contoh Dockerfile di atas, hanya terdapat satu buah statement FROM untuk menggunakan image node:alpine. Hal ini disebabkan karena contoh projectnya hanya menggunakan stack Node JS saja. Lalu bagaimana jika project kita menggunakan laravel?

Seperti yang kita ketahui, laravel merupakan full stack web framework. Di dalam project laravel, biasanya kita menggunakan composer untuk depenedency management Node JS untuk compile asset. Ini berarti kita menggunakan dua buah stack yang berbeda pada project laravel. Sehingga, ketika kita ingin membuat docker image untuk project laravel, kita bisa menggunakan multi stage build.

Apa Keuntungan Menggunakan Multi Stage Build?

Sebenarnya, kita bisa membuat docker image untuk larave tanpa multi stage build, yaitu dengan menginstall semua stack teknologi dalam satu buah base image. Namun, hal ini akan membuat ukuran docker image kita akan menjadi lebih besar. Hal ini akan menjadi sebuah pemborosan ketika kita mendeploy aplikasi kita di server production. Ukuran image yang besar tentunya memerlukan resource server yang besar pula, sehingga berakibat pada biaya server yang membengkak.

Membuat Multi Stage Build Untuk Project Laravel

Oke, setelah penjelasan singkat tentang multi stage build, kita akan mencoba membuat multi stage build untuk project laravel. Sebagai informasi, di sini saya akan menggunakan laravel versi 8.0.

Dalam root folder project, buat sebuah file bernama .dockerignore yang berisi kode berikut:

vendor/
node_modules/

File tersebut berfungsi untuk mengabaikan file saat melakukan perintah copy dalam Dockerfile.

Berikutnya, masih dalam root folder project, buatlah sebuah file baru bernama Dockerfile (tanpa ekstensi). Berikut ini beberapa perintah yang harus kita tulis dalam file Dockerfile.

Stage 0: Vendor

Pada stage ini kita akan menggunakan Composer sebagai base image dan menginstall dependency untuk project laravel kita.

FROM composer:latest AS vendor

WORKDIR /app

COPY composer.json composer.json
COPY composer.lock composer.lock

RUN composer install \
    --no-interaction \
    --no-plugins \
    --no-scripts \
    --no-dev \
    --prefer-dist

COPY . .

RUN composer dump-autoload

Stage 1: Frontend

Pada stage ini kita akan menggunakan Node JS sebagai base image dan menginstall node modules.

FROM node:alpine AS frontend

WORKDIR /app

COPY resources/css ./resources/css
COPY resources/js ./resources/js
COPY package*.json webpack.mix.js ./

RUN mkdir -p /app/public
RUN npm install
RUN npm run production

Stage 2: App

Pada stage ini kita mengumpulkan kembali file-file yang telah kita install sebelumnya ke dalam satu buah base image yang digunakan untuk menjalankan aplikasi laravel yaitu php apache.

FROM php:8.0-apache

COPY . /var/www/html
COPY --from=vendor /app/vendor/ /var/www/html/vendor/
COPY --from=frontend /app/public/js/ /var/www/html/public/js/
COPY --from=frontend /app/public/css/ /var/www/html/public/css/
COPY --from=frontend /app/mix-manifest.json /var/www/html/mix-manifest.json

RUN chown -R www-data:www-data /var/www/html

Berikut ini hasil keseluruhan file Dockerfile untuk project kita.

FROM composer:latest AS vendor

WORKDIR /app

COPY composer.json composer.json
COPY composer.lock composer.lock

RUN composer install \
    --no-interaction \
    --no-plugins \
    --no-scripts \
    --no-dev \
    --prefer-dist

COPY . .

RUN composer dump-autoload

FROM node:alpine AS frontend

WORKDIR /app

COPY resources/css ./resources/css
COPY resources/js ./resources/js
COPY package*.json webpack.mix.js ./

RUN mkdir -p /app/public
RUN npm install
RUN npm run production

FROM php:8.0-apache

COPY . /var/www/html
COPY --from=vendor /app/vendor/ /var/www/html/vendor/
COPY --from=frontend /app/public/js/ /var/www/html/public/js/
COPY --from=frontend /app/public/css/ /var/www/html/public/css/
COPY --from=frontend /app/mix-manifest.json /var/www/html/mix-manifest.json

RUN chown -R www-data:www-data /var/www/html

Sekarang kita bisa coba membuild imagenya menggunakan perintah berikut:

docker build -t <name>:<tag> .

Sebagai perbandingan, saya juga membuild project yang sama, namun dengan menggunakan cara tradisional yaitu satu stage saja dengan Dockerfile berikut:

FROM php:8.0-apache

# NPM
RUN apt-get update && apt-get install -y npm zip unzip
# Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Copy project
COPY . .

# Composer Install
RUN composer install \
       --ignore-platform-reqs \
       --no-interaction \
       --no-plugins \
       --no-scripts \
       --prefer-dist

# NPM Install dan compile production
RUN npm install \
       && npm run production

Berikut ini hasil perbandingan ukuran image yang dibuild menggunakan multi stage (tag: 1.0) dan single stage (tag: traditional)

image name tag image id size
laravel-docker traditional b7c3f1233f02 1.08GB
laravel-docker 1.0 4e12df5bace0 498MB

Wow, dapat kita lihat perbedaan yang cukup besar ya untuk ukuran image.

Kesimpulan

Oke, setelah kita mencoba multi stage build. Kita mendapatkan ukuran image yang cukup lebih kecil dibandingkan dengan menggunakan cara tradisional. Maka dari itu, mulai sekarang kita biasakan untuk menggunakan multi stage build jika ingin membuild docker image untuk project laravel. Hal ini selain hemat resource di production, juga hemat resource di komputer local kita.

Bagikan:

Ingin Berdiskusi?

Yuk bergabung di Grup Telegram Ruang Developer atau mulai diskusi melalui GitHub. See You!

comments powered by Disqus

Berlangganan Gratis

Kamu akan menerima email update dari Ruang Developer

Beri Dukungan

Beri dukungan, dapatkan full source code project web untuk bahan referensi, tiru, dan modifikasi.

Lightbox