Bu makalede, bir Laravel uygulamasını konteynerleştirme sürecini ele alacağım. Bu süreçte Docker ile ilgili duyacağınız bazı terimleri, bazı komut satırı komutlarını ve Dockerfile sözdizimini inceleyeceğiz.
Öncelikle, yeni bir Laravel projesi oluşturacağız:
$ docker run --rm \
-v "$PWD":/app \
composer/composer:latest create-project laravel/laravel yorkshire
Bu projede Laravel Octane ve FrankenPHP kullanacağım. Bu tercihimin bir sebebi, FrankenPHP’yi henüz deneyimlememiş olmam, diğer sebebi ise en iyi uygulamalar arasında yer alan Docker ile ilgili bir uygulamadır: Her konteynerde tek bir süreç.
Apache kullanmak istemiyorum. Diğer bir tipik kurulum ise PHP-FPM’dir ancak bu genellikle ayrı bir web sunucusu (genelde nginx) gerektirir; bu durum ya ayrı konteynerler oluşturmaya (tamam) ya da ikisini tek bir konteynerde birleştirmeye (daha az iyi) yol açar.
Birden fazla hizmetin tek bir konteynerde birleştirilmesi genellikle bir süreç yöneticisi (örneğin supervisord) işlemini PID 1 olarak çalıştırmayı gerektirir. Bu işlevsel bir şekilde çalışabilir ancak önemli bir kısıtlaması vardır. Docker (ve Docker Compose, ECS/Fargate, Kubernetes gibi orkestrasyon katmanları), bir konteynerin canlılığını ana işlemi ile takip eder. Eğer supervisord çalışmaya devam ederse, konteyner “çalışıyor” olarak kabul edilir.
Gerçekte PHP-FPM veya Nginx tamamen başlatılmamış olmasına rağmen, görünüşte konteyner “sağlıklı” görünür. Bununla bir kez karşılaştım ve bir daha aynı duruma düşmek istemiyorum.
RoadRunner, FrankenPHP ve Swoole gibi çalışma süreleri bu durumu tamamen önler. PHP çalışma zamanı ve web sunucusu, tek bir süreçte yaşar. Herhangi bir şey ters giderse, konteyner çıkar, bu da konteyner orkestratörlerinin beklediği bir davranıştır.
$ docker run --rm \
-v "$PWD":/app \
composer/composer:latest require laravel/octane
Octane belgelerindeki bir sonraki adım, bir artisan komutu çalıştırmaktır. Yerel olarak PHP yüklü değil ama PHP 8.5 kullanmayı planlıyorum.
$ docker run --rm \
-v "$PWD":/app \
-w /app \
php:8.5-cli-alpine php artisan octane:install --server=frankenphp
Octane başarıyla yüklendi.
Dockerfile
Dockerfile
Şu ana kadar, önceden oluşturulmuş imajlar kullanarak composer ve artisan çalıştırdık. Bir Laravel uygulamasını çalıştırmak için daha özel bir şey gerekiyor — bir Dockerfile. Dockerfile’ı, Docker’a bir imajın nasıl oluşturulacağını anlatan bir dizi yapılandırma talimatı olarak düşünebilirsiniz.
Bir Dockerfile her zaman FROM ile başlar – bir şeyden başlamanız gerekir.
Diğer sık kullanacağınız komutlar:
COPY:cpgibi çalışır. Yerel makinenizden konteynere dosyaları kopyalamak için kullanılır.WORKDIR: Konteyner içindecdgibi çalışır. İzleyen her komut için varsayılan dizini ayarlar.RUN: Düşünün ki bu, konteyner içinde bir bash kabuğu çalıştırıyor.apt update,mkdir storage,composer install,rm -rf *ENTRYPOINT: Bu, Docker’a şu talimatı verir: “Bu konteyner başladığında, ana işlem budur.” Bunu tek bir çalıştırılabilir hale getirir.npm run dev,php artisan octane:start
FROM dunglas/frankenphp:php8.5.1
# Gerekli PHP uzantılarını yükleyin
RUN install-php-extensions \
opcache \
pcntl \
zip
# Composer yürütmesini, Composer docker imajından kopyalayın
COPY --from=composer/composer:latest /usr/bin/composer /usr/bin/composer
# Kaynak kodu yerel makinemizden konteynerin /app dizinine kopyalayın
COPY . /app
# Depolama dizinlerini oluşturun ve izinleri ayarlayın
RUN mkdir -p \
storage/framework/sessions \
storage/framework/views \
storage/framework/cache \
storage/logs \
bootstrap/cache \
&& chmod -R 777 storage bootstrap/cache
# Composer'ı çalıştırın
RUN /usr/bin/composer install --no-dev --optimize-autoloader
# Bu konteyner başladığında, çalıştırdığı tek komut budur.
# Uygulama sunmak için 'octane' başlatıyoruz.
ENTRYPOINT ["php", "artisan", "octane:frankenphp"]
Ayrıca bir .dockerignore dosyası oluşturmamız gerekecek. Bu, .gitignore ile benzer işlev görür.
Şu anda Dockerfile, yerel makinemizden konteynerin içine her şeyi kopyalıyor. vendor veya storage dizinlerini konteynerin içine kopyalamak istemiyoruz.
# .dockerignore
vendor/
storage/
Bu dosya tamamlandığında – bir imaj inşa etmek gerekiyor (Dockerfile’dan).
Bir Docker imajı, uygulamayı çalıştırmak için gereken her şeyi içeren değişmez bir anlık görüntüdür. Bir imaj oluşturulduğunda, asla değişmez. Değişiklik yapmak istediğinizde, yeni bir imaj oluşturmalısınız.
$ docker build -t yorkshire .
Bu komutun içeriğini ayıracak olursak:
docker build: Docker’a, bir imaj inşa etmesini söyleme-t yorkshire: İmajıyorkshireolarak etiketleme.: Geçerli dizindeDockerfile‘ı arama
Yanlışlık olmadan tamamlandığında – konteynerleştirilmiş bir Laravel uygulaması oluşturmuş olacaksınız.
Etiketler
Etiketler
Daha önce zaten etiketler kullanıyorduk: php:8.5-cli, dunglas/frankenphp:php8.5.1, composer/composer:latest.
Bir etiket, bir imaj için yalnızca bir versiyon etiketidir. Formatı her zaman image_name:tag şeklindedir. Docker bir imaja ihtiyacı olduğunda, şu basit kuralı takip eder:
- Yerel makinenizi kontrol edin.
- Orada yoksa, Docker Hub’dan çekmeyi deneyin.
İnşa etmiş olduğumuz imajı bu yüzden çalıştırabiliriz.
:latest için bir uyarı
:latest için bir uyarıSıklıkla öğrenirken php:latest veya mysql:latest gördüğünüzde, bu pratik görünebilir ama tavsiye etmem.
Yazının yazıldığı anda, php:latest sürümü 8.5.1 olarak belirlemekte. Bu her zaman doğru olmayabilir. Üretim ortamında, her zaman açık ve net olun. Sürümlerinizi kilitleyin (php:8.5.1). Aksi takdirde, bir gün bir konteyneri yeniden başlattığınızda bir Windows tarzı güncellemeyle karşılaşabilirsiniz – birisi istemediğiniz bir şekilde.
Bir konteynerle çalışmak başlangıçta çarpıcı görünmeyebilir. Daha önce de belirttiğim gibi, dosya sisteminizde herhangi bir dosya ortaya çıkmadı. Derlenmiş çıkışlar içeren bir klasör yok, büyük bir imaj dosyası yok. İmaj, Docker’ın iç depolama alanında var ve siz ona Docker komutları ile etkileşimde bulunursunuz.
Peki, şimdi bunu çalıştıralım.
docker run komutu, bir imajdan çalışan bir konteyner oluşturur. Bir imaj bir anlık görünümse, bir konteyner bu anlık görünümün hayata geçirilmesi demektir – çalışan bir işlem, dosya sistemi, ağ ve işlem alanı ile.
Önceki örneklerde composer veya PHP çalıştırdığımızda konteynerler, barındırma makinesi ağından izoleydi. Hiçbir şey içeri veya dışarı girmiyor, aksi halde açıkça izin vermediniz.
Burada port yayınlama devreye giriyor. -p bayrağı, makineniz ile konteyner arasında bir tünel oluşturur. FrankenPHP, konteyner içinde HTTP’yi 8000 numaralı porta ve HTTPS’yi 443 numaralı porta bağlar, bu nedenle bunları yerel makinemizdeki portlarla eşleştirmek gerekiyor.
$ docker run -p 80:8000 -p 443:443 -p 443:443/udp yorkshire
Bu komutun içeriğini ayıracak olursak:
docker run: Bir konteyner oluştur ve başlat-p 80:8000: Port yayınlama,host:containerformatında. Makinemdeki 80 numaralı porta gelen isteklerin, konteyner içindeki 8000 numaralı porta yönlendirilmesini sağlar. Neden sadece 8000:8000 kullanmıyorum? Kullanabilirim, fakat 80 numaralı port varsayılan HTTP portudur – böylecehttp://localhost‘u ziyaret edebilirim,http://localhost:8000yerine.-p 443:443: HTTPS trafiği için de aynı fikir.-p 443:443/udp: HTTP/3, QUIC üzerinde yürür ve UDP kullanır. Bunu etkinleştirmeden yalnızca HTTP/1.1 ve HTTP/2 ile sınırlısınız. FrankenPHP, HTTP/3’ü kutudan çıkmış olarak destekler, bu nedenle bunu etkinleştirebiliriz.yorkshire: Çalıştırılacak imaj. Docker önce yerel makinede kontrol eder, bulamazsa Docker Hub’dan çeker.
Tarayıcımda http://localhost‘u açarak, İngiltere’nin en iyi şehri hakkında bir web sitesi ile karşılaşıyorum:
Docker Hub’a imajı gönderdim; böylece hiçbir şey oluşturmadan kendiniz çalıştırabilirsiniz.
$ docker build --platform=linux/amd64 -t clegginabox/yorkshire .
$ docker push clegginabox/yorkshire
--platform=linux/amd64 bayrağına dikkat etmek gerekir. Varsayılan olarak Docker, imajları ev sahibi makinenizin mimarisi için inşa eder. Ben Apple Silicon Mac’teyim; bu nedenle o bayrak olmadan ARM64 imajı alırım. Bu yerel olarak iyi ama çoğu cloud sunucusu x86_64 üzerinde çalışır.
Artık herkes imajı çekip çalıştırabiliyor:
$ docker run -p 80:8000 -p 443:443 -p 443:443/udp clegginabox/yorkshire
Bu Yerel Geliştirme için İyi Değil
Bu Yerel Geliştirme için İyi Değil
Yaptığımız yapı, dağıtım için harika. Bir imaj oluştur, it, her yerde çalıştır. Ama yerel geliştirme için? Hayır teşekkürler.
Homepage’e başka bir çeviri eklemeye çalışıyorsam – “Sort thi sen art”. Dosyayı kaydediyorum, tarayıcıyı yeniliyorum, hiçbir şey değişmiyor.
Az önce söylediğim gibi, Docker imajları değişmezdir. Değişiklik yapmak istiyorsanız, başka bir imaj inşa etmeniz gerekir. Bu, docker build çalıştırmayı gerektirir; bu da composer install‘u çalıştırır. Ardından tekrar docker run çalıştırırım. Bununla uğraşacak zamanım yok.
Neyse ki bu soruna güzel bir çözüm var – Docker Compose.
Sonuç
Sonuç
Boş bir dizinden FrankenPHP üzerinde çalışan bir konteynerleştirilmiş Laravel uygulamasına geçtik. Bu süreçte şunları ele aldık:
- Tek süreçli konteynerlerin orkestrasyon için neden önemli olduğu
- Temel Dockerfile talimatları:
FROM,COPY,WORKDIR,RUN, veENTRYPOINT - İmajlar ve konteynerler arasındaki fark
- Konteynerleri inşa etme, etiketleme ve çalıştırma
Mac’imde oluşturduğum aynı imaj, şimdi AWS üzerinde çalışıyor. Bu, konteynerlerin vaadi – henüz iyi kısmına bile ulaşmadık.
3. Bölümde, Docker Compose ile bir tam geliştirme yığını kurmayı ele alacağım. 4. Bölümde, güvenlik sertleştirmesi, çok aşamalı derlemeler, sağlık kontrolleri ve diğer üretim adımlarını ele alacağım.
Özellikle görmek istediğiniz bir şey varsa lütfen aşağıdaki yorumlarda belirtin. React? Vue? Meilisearch? Aynı anda birden fazla compose projesi çalıştırmak?
Kaynak: Orijinal Makale


