Docker + Laravel + RoadRunner = ❤

gambar


Posting ini ditulis atas permintaan pekerja yang secara berkala bertanya tentang "Cara menjalankan aplikasi Illuminate / Symfony / MyOwn Psr7 di buruh pelabuhan." Saya tidak merasa ingin memberikan tautan ke pos yang ditulis sebelumnya , karena pandangan saya tentang cara mengatasi masalah telah sedikit berubah.


Segala sesuatu yang akan ditulis di bawah ini adalah pengalaman subjektif, yang (seperti biasa) tidak mengklaim sebagai satu-satunya keputusan yang tepat, tetapi beberapa pendekatan dan solusi mungkin tampak menarik dan bermanfaat bagi Anda.


Saya juga akan menggunakan Laravel sebagai aplikasi, karena ini paling akrab bagi saya dan cukup luas. Beradaptasi dengan kerangka kerja / komponen berbasis PSR-7 lainnya adalah mungkin, tetapi cerita ini bukan tentang itu.

Menangani kesalahan


Saya ingin memulai dengan apa yang ternyata "bukan praktik terbaik" dalam konteks artikel sebelumnya :


  • Kebutuhan untuk mengubah struktur file di repositori
  • Menggunakan FPM. Jika kita menginginkan kinerja dari aplikasi kita, maka mungkin salah satu solusi terbaik bahkan pada tahap pemilihan teknologi adalah meninggalkannya demi sesuatu yang lebih cepat dan "disesuaikan" dengan kenyataan bahwa memori mungkin bocor. RoadRunner oleh lachezis ada di sini yang belum pernah ada sebelumnya
  • Gambar terpisah dengan sumber dan aset. Terlepas dari kenyataan bahwa menggunakan pendekatan ini, kita dapat menggunakan kembali gambar yang sama untuk membangun perutean yang lebih kompleks dari permintaan masuk (nginx di depan untuk mengembalikan statis; permintaan untuk dinamika dilayani oleh wadah lain di mana volume dilemparkan dengan sumber yang sama - untuk scaling lebih baik) - skema ini telah terbukti agak rumit dalam operasi produk. Dan terlebih lagi, RR dengan sendirinya merender statika, dan jika ada banyak statika (atau sumber daya dapat memuat dan menampilkan konten yang dibuat pengguna) - kami membawanya ke CDN (bundel S3 + CloudFront + CloudFlare berfungsi dengan baik) dan lupakan masalah ini pada prinsipnya
  • CI kompleks. Ini menjadi masalah nyata ketika periode "daging bangunan" aktif dimulai pada tahap perakitan dan pengujian otomatis. Seorang pria yang tidak mendukung CI ini sebelumnya, menjadi sangat sulit untuk melakukan perubahan tanpa takut merusak apa pun.

Sekarang, mengetahui masalah apa yang perlu diperbaiki dan dengan pemahaman tentang bagaimana melakukan ini, saya mengusulkan melanjutkan penghapusannya. Himpunan "alat pengembang" tidak berubah - itu adalah docker-ce , docker-compose dan Makefile kuat.


Sebagai hasilnya, kita mendapatkan:


  • Wadah mandiri dengan aplikasi tanpa perlu memasang volume tambahan
  • Contoh menggunakan git-hooks - kami akan meletakkan dependensi yang diperlukan setelah git pull secara otomatis dan melarang mendorong kode jika tes gagal (hook akan disimpan di bawah git, secara alami)
  • RoadRunner akan menangani permintaan HTTP
  • Pengembang masih dapat menjalankan dd(..) dan dump(..) untuk debugging, sementara tidak ada yang macet di browser mereka
  • Tes dapat dijalankan langsung dari PHPStorm IDE, sementara itu akan dijalankan dalam wadah dengan aplikasi
  • CI akan mengumpulkan gambar untuk kami saat menerbitkan tag versi aplikasi baru
  • Mari kita ambil aturan ketat untuk memelihara file CHANGELOG.md dan ENVIRONMENT.md

Pengenalan visual dari pendekatan baru


Untuk demonstrasi visual, saya akan memecah seluruh proses menjadi beberapa tahap, perubahan di dalamnya akan dibuat sebagai MR terpisah (setelah merger, semua brunch akan tetap di tempatnya masing-masing; referensi ke MR di pos "langkah"). Titik awalnya adalah kerangka Laravel aplikasi yang dibuat menggunakan composer create-project laravel/laravel :


 $ docker run \ --rm -i \ -v "$(pwd):/src" \ -u "$(id -u):$(id -g)" \ composer composer create-project --prefer-dist laravel/laravel \ /src/laravel-in-docker-with-rr "5.8.*" 

Langkah 1 - Docking + RR


Langkah pertama adalah mengajarkan aplikasi untuk berjalan di wadah. Untuk melakukan ini, kita membutuhkan Dockerfile , docker-compose.yml untuk deskripsi "cara mengangkat dan menautkan kontainer", dan Makefile untuk mengurangi proses yang sudah disederhanakan menjadi satu atau dua perintah.


Dockerfile


Gambar dasar saya menggunakan php:XXX-alpine sebagai yang termudah dan berisi apa yang perlu Anda jalankan. Selain itu, semua pembaruan juru bahasa berikutnya dikurangi menjadi sekadar mengubah nilai pada baris ini (memperbarui PHP sekarang lebih mudah dari sebelumnya).


Komposer dan file biner RoadRunner dikirim ke wadah menggunakan multistage dan COPY --from=... - ini sangat nyaman, dan semua nilai yang terkait dengan versi tidak "tersebar", tetapi berada di awal file. Ini bekerja cepat, dan tanpa ketergantungan pada curl / git clone / make build . 512k / roadrunner didukung oleh saya, jika Anda mau - Anda dapat merakit sendiri file biner.


Sebuah cerita menarik terjadi dengan variabel lingkungan PS1 (bertanggung jawab atas prompt di shell) - ternyata Anda dapat menggunakan emoji di dalamnya, dan semuanya bekerja secara lokal, tetapi jika Anda mencoba memulai gambar dengan variabel yang mengandung emoji di, katakanlah, peternak, itu akan macet (di gerombolan semuanya bekerja tanpa masalah).

Di Dockerfile saya mulai membuat sertifikat SSL yang ditandatangani sendiri untuk menggunakannya untuk permintaan HTTPS yang masuk. Secara alami - tidak ada yang mencegah penggunaan sertifikat "normal".


Saya juga ingin mengatakan tentang:


 COPY ./composer.* /app/ RUN set -xe \ && composer install --no-interaction --no-ansi --no-suggest --prefer-dist \ --no-autoloader --no-scripts \ && composer install --no-dev --no-interaction --no-ansi --no-suggest \ --prefer-dist --no-autoloader --no-scripts 

Di sini artinya adalah sebagai berikut - file composer.lock dan composer.json dikirim dalam lapisan terpisah ke gambar, setelah semua dependensi yang dijelaskan di dalamnya diinstal. Hal ini dilakukan agar selama pembuatan selanjutnya gambar menggunakan --cache-from , jika komposisi dan versi dependensi yang diinstal tidak berubah, maka composer install tidak dieksekusi, mengambil lapisan ini dari cache, sehingga menghemat waktu dan lalu lintas pembangunan (terima kasih atas idenya jetexe ).


composer install dieksekusi dua kali (kedua kalinya dengan --no-dev ) untuk "menghangatkan" cache dependensi dev, sehingga ketika kita meletakkan semua dependensi pada CI untuk menjalankan tes, mereka dimasukkan dari cache komposer, yang sudah ada dalam gambar, dan tidak membentang dari galaksi yang jauh.


Dengan instruksi RUN terakhir, kami menampilkan versi perangkat lunak yang diinstal dan komposisi modul PHP baik untuk sejarah di build logs dan untuk memastikan bahwa "setidaknya ada dan entah bagaimana mulai."


Saya juga menggunakan Entrypoint saya, karena sebelum memulai aplikasi di suatu tempat di cluster saya benar-benar ingin memeriksa ketersediaan layanan dependen - DB, redis, kelinci dan lain-lain.


Roadrunner


Untuk mengintegrasikan RoadRunner dengan aplikasi Laravel, sebuah paket ditulis yang mengurangi semua integrasi menjadi beberapa perintah dalam shell (dengan docker-compose run app sh ):


 $ composer require avto-dev/roadrunner-laravel "^2.0" $ ./artisan vendor:publish --provider='AvtoDev\RoadRunnerLaravel\ServiceProvider' --tag=rr-config 

Tambahkan APP_FORCE_HTTPS=true ke file ./docker/docker-compose.env , dan tentukan jalur ke sertifikat SSL dalam wadah di .rr*.yaml .


Agar dapat menggunakan dump(..) dan dd(..) dan semuanya akan berfungsi, ada paket lain - avto-dev/stacked-dumper-laravel . Yang diperlukan hanyalah menambahkan pefix ke pembantu ini, yaitu \dev\dd(..) dan \dev\dump(..) masing-masing. Tanpa ini, Anda akan melihat kesalahan formulir:
 worker error: invalid data found in the buffer (possible echo) 

Setelah semua manipulasi, lakukan docker-compose up -d dan voila:


tangkapan layar


Basis data PostgeSQL, redis, dan pekerja RoadRunner berhasil dijalankan dalam wadah.


Langkah 2 - Makefile dan Tes


Seperti yang saya tulis sebelumnya, Makefile adalah item yang sangat diremehkan. Tergantung tujuan, gula sintaksis Anda sendiri, 99% kemungkinan dia sudah berdiri di Linux / mesin pengembangan mac, autocomplete "di luar kotak" - daftar kecil dari keuntungannya.


Menambahkannya ke proyek kami dan melakukan make tanpa parameter, kita dapat mengamati:


tangkapan layar


Untuk menjalankan tes unit, kita bisa melakukan make test , atau mendapatkan shell di dalam wadah dengan aplikasi ( make shell ), jalankan composer phpunit . Untuk mendapatkan laporan peliputan, cukup buat make test-cover , dan sebelum menjalankan tes, xdebug dengan dependensinya akan dikirimkan ke wadah dan tes akan diluncurkan (karena prosedur ini tidak sering dilakukan dan bukan oleh CI - solusi ini tampaknya lebih baik daripada menyimpan gambar terpisah dengan semua dev-lotion).


Git hooks


Pengait dalam kasus kami akan memenuhi 2 peran penting - tidak memungkinkan memasukkan kode ke tempat asal yang pengujiannya tidak berhasil; dan secara otomatis menempatkan semua dependensi yang diperlukan jika, menarik perubahan ke mesin Anda, ternyata composer.lock telah berubah. Di Makefile , ada target terpisah untuk ini:


 cwd = $(shell pwd) git-hooks: ## Install (reinstall) git hooks (required after repository cloning) -rm -f "$(cwd)/.git/hooks/pre-push" "$(cwd)/.git/hooks/pre-commit" "$(cwd)/.git/hooks/post-merge" ln -s "$(cwd)/.gitlab/git-hooks/pre-push.sh" "$(cwd)/.git/hooks/pre-push" ln -s "$(cwd)/.gitlab/git-hooks/pre-commit.sh" "$(cwd)/.git/hooks/pre-commit" ln -s "$(cwd)/.gitlab/git-hooks/post-merge.sh" "$(cwd)/.git/hooks/post-merge" 

Melakukan make git-hooks hanya menghilangkan hook yang ada dan meletakkannya di .gitlab/git-hooks di tempatnya. Sumber mereka dapat dilihat di tautan ini .


Menjalankan tes dari PhpStorm


Terlepas dari kenyataan bahwa itu cukup sederhana dan nyaman - saya menggunakannya untuk waktu yang lama ./vendor/bin/phpunit --group=foo daripada hanya menekan hotkey secara langsung saat menulis tes atau kode yang terkait dengannya.


Klik File > Settings > Languages & Frameworks > PHP > CLI interpreter > [...] > [+] > From Docker, Vargant, VM, Remote . Pilih komposisi Docker , dan nama layanan aplikasi .


tangkapan layar


Langkah kedua adalah memberi tahu phpunit untuk menggunakan juru bahasa dari wadah: File > Settings > Test frameworks > [+] > PHPUnit by remote interpreter dan pilih interpreter jarak jauh yang dibuat sebelumnya. Di bidang Path to script , tentukan /app/vendor/autoload.php , dan di Path mappings tentukan direktori root dari proyek yang terpasang di /app .


tangkapan layar


Dan sekarang kita dapat menjalankan tes langsung dari IDE menggunakan interpreter di dalam gambar dengan aplikasi, menekan (secara default, Linux) Ctrl + Shift + F10.


Langkah 3 - Otomasi


Yang tersisa untuk kita lakukan adalah mengotomatiskan proses menjalankan tes dan merakit gambar. Untuk melakukan ini, buat file .gitlab-ci.yml di direktori root aplikasi, isi dengan konten berikut . Gagasan utama dari konfigurasi ini adalah sesederhana mungkin, tetapi tidak kehilangan fungsionalitas pada saat bersamaan.


Gambar dirakit di setiap makan siang, di setiap komit. Menggunakan --cache-from merakit gambar setelah komit ulang sangat cepat. Kebutuhan untuk membangun kembali adalah karena pada setiap brunch kita memiliki gambar dengan perubahan yang dibuat sebagai bagian dari brunch ini, dan sebagai hasilnya, tidak ada yang mencegah kita untuk meluncurkannya ke swarm / k8s / etc untuk memastikan "live" bahwa semuanya bekerja, dan berfungsi sebagaimana mestinya bahkan sebelum bergabung dengan master light.


Setelah perakitan, kami menjalankan tes unit dan memeriksa peluncuran aplikasi dalam wadah, mengirimkan permintaan saat ini ke titik akhir pemeriksaan kesehatan (tindakan ini opsional, tetapi beberapa kali tes ini banyak membantu saya).


Untuk "rilis rilis" - cukup terbitkan tag bentuk vX.XX (jika Anda masih tetap menggunakan versi semantik - itu akan sangat keren) - CI akan mengumpulkan gambar, menjalankan tes, dan melakukan tindakan yang Anda tentukan dalam deploy to somewhere .


Jangan lupa dalam pengaturan proyek (jika mungkin) untuk membatasi kemampuan untuk mempublikasikan tag hanya untuk orang yang diizinkan untuk "melepaskan rilis".

CHANGELOG.md dan ENVIRONMENT.md


Sebelum menerima satu atau yang lain MR, inspektur harus, tanpa gagal, periksa file CHANGELOG.md dan ENVIRONMENT.md CHANGELOG.md ENVIRONMENT.md . Jika yang pertama lebih dan kurang jelas , maka relatif kedua saya akan memberikan penjelasan. File ini digunakan untuk menjelaskan semua variabel lingkungan yang ditampung oleh aplikasi. Yaitu jika pengembang menambahkan atau menghapus dukungan untuk satu atau variabel lingkungan lain, ini harus tercermin dalam file ini. Dan pada saat pertanyaan "Kami sangat perlu untuk mendefinisikan kembali ini dan itu" muncul - tidak ada yang panik mulai mempelajari dokumentasi atau kode sumber - tetapi melihat dalam satu file. Sangat nyaman


Kesimpulan


Pada artikel ini, kami memeriksa proses yang agak tidak menyakitkan untuk mentransfer pengembangan aplikasi dan meluncurkan ke lingkungan Docker, RoadRunner yang terintegrasi, dan menggunakan skrip CI sederhana yang mengotomatiskan perakitan dan pengujian gambar dengan aplikasi kami.


Setelah mengkloning repositori, para pengembang harus melakukan make git-hooks && make install && make up dan mulai menulis kode yang berguna. Kamerad * ops-am - mengambil gambar dengan tag yang diinginkan dan menggulungnya pada kelompok mereka.


Secara alami - skema ini juga disederhanakan, dan pada proyek "pertempuran" saya membuat lebih banyak, tetapi jika pendekatan yang dijelaskan dalam artikel membantu seseorang, saya akan tahu bahwa saya membuang-buang waktu.

Source: https://habr.com/ru/post/id461687/


All Articles