Cara Menggunakan NGINX untuk Menghosting Situs Lokal Menggunakan Docker

· 5 min read
Cara Menggunakan NGINX untuk Menghosting Situs Lokal Menggunakan Docker
Photo by Christopher Gower / Unsplash

Terkadang, Anda tidak bisa begitu saja membukanya index.htmldi Chrome untuk menguji situs web Anda. Anda memerlukan fitur server web nyata seperti NGINX.

Kasus umum ketika pemuatan langsung index.htmlgagal adalah mencoba menyajikan file lokal menggunakan Fetch API. Anda mengalami kesalahan Berbagi Sumber Daya Lintas Asal (CORS). Saya mengalami masalah kecil ini ketika membuat contoh untuk posting blog ini tentang ClipBoard API . Selain mencegah kesalahan CORS, lebih realistis menggunakan server web produksi di lingkungan pengembangan Anda.

An Introduction to NGINX for Developers

Untuk memulai, Anda hanya perlu menginstal Docker dan menjalankan satu perintah.

$ docker run -d --name nginx-development -v $(pwd):/usr/share/nginx/html -p 80:80 nginx

Perintah di atas melakukan beberapa hal. Bendera -dmemastikan Anda tidak terjebak di wadah. Menggunakan --name nginx-developmentargumen kata kunci memberi nama pada instance container ini, sehingga kita dapat mereferensikannya nanti. Ini -p 80:80memetakan port mesin lokal kami 80ke port container yang digunakan NGINX untuk melayani HTTP. Pemetaan port ini memungkinkan kami mengunjungi http://localhostsitus pengembangan kami.

Argumen -v $(pwd):/usr/share/nginx/htmlkata kunci perlu penjelasan lebih lanjut. Ini menghubungkan direktori kerja kita saat ini ke direktori dalam instance container yang sedang berjalan. Direktori dalam container ini adalah lokasi default tempat NGINX mencari file untuk disajikan. Jika Anda ingin menyajikan direktori yang berbeda, maka Anda perlu mengubah argumennya --volume. Misalnya, saya ingin meletakkan index.htmldi  ./src/index.html di direktori proyek saya. Untuk menyesuaikannya, -vargumen saya akan terlihat seperti ini -v "$(pwd)/src:/usr/share/nginx/html".

Jika Anda menggunakan browser untuk bernavigasi ke http://localhost, Anda seharusnya dapat melihat situs Anda. Namun jika Anda membuat perubahan pada file Anda index.htmlatau file lain di situs Anda, menyegarkan browser Anda tidak akan menampilkannya. Untuk memuat ulang situs setelah Anda melakukan perubahan, gunakan perintah berikut.

$ docker restart nginx-development

Ada baiknya kita dapat memuat ulang perubahan kita, tetapi ini memerlukan langkah ekstra: menjalankan docker restartperintah di atas. Dengan alur kerja sebelumnya – membuka index.htmlsecara langsung – kita hanya memerlukan satu langkah: menyegarkan browser kita. Mari kita perbaiki

Untuk membuat skrip ini, kita perlu melakukannya

  1. Jajak pendapat direktori sesering mungkin dan catat sendiri perubahannya
  2. Miliki cara untuk diberitahu ketika ada perubahan

Untuk menghindari pengelolaan negara kita sendiri dan menjaga skrip bash tetap sederhana, mari kita pilih opsi 2. Bagaimana kita bisa mendapatkan notifikasi ini? Di Linux, ada alat baris perintah inotifywaityang mengandalkan inotify C API yang mendasarinya . Kita bisa menggunakan ini, tapi kemudian kita akan terkunci di Linux. Saya mengembangkannya di Mac OS dan Linux, jadi saya ingin mendukung keduanya – bahkan lebih baik lagi jika kami juga dapat mendukung Windows.

Ada alat lain fswatchyang berfungsi di Mac OS, Linux, dan Windows. Ini mungkin tidak diinstal secara default di sistem operasi Anda. Di Mac OS, saya perlu menginstal fswatchmenggunakan perintah berikut.

$ brew install fswatch

Sekarang mari kita lihat cara kerja alat ini. Mari kita coba jalankan alat ini dan arahkan ke direktori sumber kita.

$ fswatch src

Konsol saya hang dengan kursor berkedip. Mari kita lihat apa yang terjadi jika kita mengubah salah satu file di srcdirektori. Saya akan mencoba mengedit salah satu file css saya...

$ fswatch src
/Users/curtis/git/licorice-works/src/styles/4913
/Users/curtis/git/licorice-works/src/styles/projects.css
/Users/curtis/git/licorice-works/src/styles/projects.css
/Users/curtis/git/licorice-works/src/styles/projects.css~

Sekarang, fswatchberikan kita keluaran di atas dengan nama file yang saya modifikasi.

Ini adalah pemberitahuan perubahan yang banyak untuk memodifikasi satu file. Sepertinya kami tidak ingin pemberitahuan untuk 4913file atau .css~file tersebut. Ini tampaknya merupakan keanehan dalam cara kerja penyimpanan file di Mac OS. Untungnya, fswatchalat ini memiliki beberapa argumen yang dapat kita gunakan untuk memfilter notifikasi perubahan. Secara default, ini mencakup semuanya. Perilaku ini membuat penyertaan jenis file yang kita inginkan menjadi sedikit aneh. Pertama, kita perlu menggunakan -e '.*'untuk mengecualikan semuanya. Kemudian kita dapat menggunakan -i 'css$'untuk memasukkan kembali hanya file yang berakhiran css. Dengan perintah baru kami, kami hanya mendapat notifikasi untuk file CSS yang kami ubah – bukan file aneh lainnya.

$ fswatch -e '.*' -i 'css$' src                     
/Users/curtis/git/licorice-works/src/styles/projects.css
/Users/curtis/git/licorice-works/src/styles/projects.css

Ini masih berupa dua notifikasi. Kami hanya ingin memuat ulang NGINX satu kali per perubahan. Untungnya, fswatchada --one-per-batchtanda yang dapat kita gunakan untuk mengelompokkan perubahan bersama-sama.

$ fswatch -o -e '.*' -i 'css$' src
2

Setelah menambahkan -o, kita hanya mendapatkan satu baris keluaran saat kita memodifikasi file. Mari kita gunakan output ini untuk memicu restart container Docker kita.

$ fswatch -o -e '.*' -i 'css$' -i 'html$' -i 'js$' src | \
while read -r line; do docker restart nginx-development; done

Perintah itu terlihat lebih rumit dibandingkan perintah yang kita gunakan selama ini. Mari kita gali lebih dalam. Pertama, saya menambahkan dua -ifilter penyertaan lagi. Satu untuk menyertakan pembaruan apa pun yang kami buat pada .htmlfile dan satu lagi untuk menyertakan .jsfile. Kemudian kita menyalurkan |output dari perintah ini ke dalam loop while. Jika Anda tidak terbiasa dengan pipa, ia hanya mengirimkan keluaran dari perintah pertama sebagai masukan ke perintah kedua. Perintah kedua yang kita masukkan adalah while loop. Sintaks umum dari perulangan while terlihat seperti berikut.

while <condition>;
do
  <command to execute>
done

Akan lebih mudah dibaca jika tidak dipadatkan menjadi satu baris. Untuk <condition>bagian ini, kami menggunakan perintah read -r line. Setiap kali ada baris input untuk dibaca, perintah ini membacanya, menyimpannya dalam variabel line, dan mengembalikan nilai true. Dalam skrip kami, ini berarti setiap kali fswatchmencetak sekumpulan perubahan, loop kami akan dijalankan satu kali. Jadi setiap kali ada perubahan, kami akan menjalankan perintah restart yang sama seperti di atas docker restart nginx-development.

Anda bisa memulai dengan menjalankan dua perintah.

$ docker run -d --name nginx-development -v $(pwd):/usr/share/nginx/html -p 80:80 nginx
$ fswatch -o -e '.*' -i 'css$' -i 'html$' -i 'js$' $(pwd) | while read -r line; do docker restart nginx-development; done

Tapi ini banyak yang perlu diingat atau disalin-tempel setiap saat, jadi saya menulis skrip yang hanya membutuhkan satu argumen: direktori sumber Anda. Anda dapat menyalin skrip ini dan menggunakannya kembali dengan mudah untuk setiap proyek Anda.

nginx-autoreload.sh

#!/bin/bash

CONTAINER_NAME="nginx-development"

# Use the first argument as our source dir.
# Default to current working directory if no argument is supplied.
SOURCE_DIRECTORY=$1
if [ ! $1 ]; then
    SOURCE_DIRECTORY="$(pwd)";
    echo "No source directory provided. Defaulting to current working directory: ${SOURCE_DIRECTORY}";
else
    # Get the full path
    SOURCE_DIRECTORY=$(realpath "${SOURCE_DIRECTORY}")
fi

docker rm --force "${CONTAINER_NAME}" &> /dev/null;

docker run -d --name "${CONTAINER_NAME}" -v "${SOURCE_DIRECTORY}":/usr/share/nginx/html -p 80:80 nginx > /dev/null;
if [ $? -ne 0 ]; then
    echo "Failed to initialize container";
    exit 1;
else
    echo "Successfully started container: ${CONTAINER_NAME}";
fi

echo "Waiting for changes..."
fswatch -o -e '.*' -i 'css$' -i 'html$' -i 'js$' "${SOURCE_DIRECTORY}" |
while read -r line; do
    docker restart "${CONTAINER_NAME}" > /dev/null;
    if [ $? -eq 0 ]; then
        echo "Successfully reloaded ${CONTAINER_NAME}";
    else
        echo "Failed realoading ${CONTAINER_NAME}";
    fi
done

Anda dapat menggunakan skrip seperti $ ./nginx-autoreload.sh <your-source-directory, dan skrip ini akan mengatur penyiapan penampung dan mengamati perubahan. Catatan: ingatlah untuk menginstal Docker dan fswatch terlebih dahulu!