WordPress Geliştiricisinin Docker'a Girişi
Gereksinimler
Bu öğreticiyi takip etmek için, geliştirme bilgisayarınızda Docker'ın kurulu olduğundan ve çalıştığından emin olun (komut satırınızda $ docker -v çalıştırarak doğrulayın).
Her şeyi sıfırdan açıklamaya çalışacağım için önceden Docker deneyimine sahip olmanıza gerek yok. Herhangi bir sorunuz varsa, aşağıya yorum bırakmaktan çekinmeyin.
Son fakat en az değil, bir uyarı sözü; Docker Linux'ta yerel olarak desteklenirken, Windows ve Mac'te çalışmak için ek bir katman gerektirir (eğer yüklediyseniz zaten bilirsiniz). Bu sorun, Docker'ı şimdi kullanmanın avantajlarını biraz baltalıyor, ancak beta sürümüne erişebildiğim için (ve siz de yapabilirsiniz! Buraya başvurabilirsiniz) sizi temin ederim ki bu sorunlar yakında ortadan kalkacaktır. Sorun şu ki, hala çalışan bir sanal makineye ihtiyacınız var, ancak iyi yanı, bunun yalnızca boot2docker adlı küçük bir sarmalayıcı Linux dağıtımını çalıştırması.
Peki liman işçisi nedir?
Docker'ın ne olduğunu anlamak için, bizim (ve demek istediğim WordPress geliştiricilerinin) neredeyse her gün karşılaştığımız birkaç soruna bakalım.
Hepimiz kodumuzu başka bir geliştiriciyle (veya birçoğuyla) paylaşmamız gereken durumlarla karşılaşmışızdır. Kodumuzu GitHub'a adadığımızda (Git'i kullanıyorsunuz, değil mi?) ve onu çalıştırmayı denediler, işe yaramadı. Sorunun ne olduğu sorulduğunda hepimiz şu tanıdık ifadeyle yanıtladık: bilgisayarımda çalışıyor .
İki geliştirici aynı proje üzerinde çalışırken bu büyük bir sorun gibi görünmüyor – birlikte (veya sanal olarak) otururlar, sorunu çözerler ve umarım belgelendirirler. Peki aynı proje üzerinde çalışan 20 geliştirici olduğunda ne olur? Yoksa 50 mi? İşler hızla kontrolden çıkabilir.
Aynı şey üretim için de geçerli. Kaç kez kod yazdınız, yerel olarak test ettiniz, ancak üretime geçtiğinizde beyaz ölüm ekranıyla karşılaştınız? Şimdi aynı üretim ortamına dağıtım yapan 20 geliştiriciden oluşan bir ekip hayal edin. Geliştirme yerine devops için çılgınca miktarda zaman harcanıyor. Bu da çılgın paralar anlamına geliyor çünkü birileri bu konulara harcanan zamanın bedelini ödemek zorunda.
Bir adım geri gidelim ve bu sorunlara neden olan bazı olası suçlulara bakalım:
– farklı WordPress (ve/veya eklenti) sürümleri
– farklı PHP sürümleri
– farklı web sunucusu (Apache/Nginx) sürümleri
– farklı MySQL sürümleri
– tamamen farklı işletim sistemi
– yukarıdakilerin hepsinin farklı konfigürasyonları (bellek/CPU limitleri, kurulu modüller)
Peki Docker'ın masaya getirdiği şey nedir? Bir şey: tutarlılık . Nerede çalıştırırsanız çalıştırın ortamın aynı olacağını garanti eder; Yerel olarak, 50 farklı bilgisayarda, bir CI (sürekli entegrasyon) ortamında veya üretimde – aynı ortamı ve kodu kullanacağından tamamen aynı şekilde çalışacaktır .
Bu sorunlar elbette yeni değil ve tutarsızlık sorunlarını en azından bir dereceye kadar hafifletmeye çalışan bir alternatif var: Vagrant. Docker'a çok benzer şekilde, tutarlı ortamlar oluşturmak için bir reçete sunar ve bunun bir bedeli vardır: En az bir sanal makine çalıştırmanızı gerektirir – bu, Docker'dan farklı olarak tam teşekküllü bir Linux dağıtımıdır ve sorunları özetlemeye çalışacağım. Bu eğitim boyunca.
Bu sorunlardan ilkini göstermek için birçok Docker öğreticisi şu diyagramı gösterir:

İlk bakışta, çok büyük bir fark gibi görünmüyor, bu yüzden size sistem kaynaklarını hesaba katan daha doğru bir diyagram göstereyim:

O ekstra katman artık o kadar masum görünmüyor değil mi? Aslında öyle değil – sanal/misafir işletim sisteminin çalışması için çok sayıda kilitli kaynağa ihtiyacı var ve her konuk işletim sistemine uygun bir miktarı dikkatli bir şekilde atamazsanız, bunların hızla tükenmesi kaçınılmazdır. Kilitli derken, demek istediğim, konuk işletim sistemine CPU, RAM ve Sabit disk alanı miktarını ayarladığınızda, misafirin büyük bir bölümünü veya yalnızca küçük bir bölümünü kullanmasına bakılmaksızın ana bilgisayar bunları kullanamaz – bu kaynaklar değil paylaşıldı .
Şimdiye kadar Docker'ın bir tür kırpılmış sanal makine olduğunu düşünüyor olabilirsiniz ve yarı haklısınız; Sanaldır, ancak bir makine değil, bir ortamdır . Bir sanal makinenin fiziksel bir makine olduğunu düşündüğü yerde (VirtualBox veya VMWare Fusion gibi bir sanallaştırma yazılımı aracılığıyla), bir Docker Container (yakında terminoloji hakkında daha fazlası, onu kırpılmış bir Linux VM olarak düşünün) herhangi bir kaynak için ana bilgisayar işletim sistemine güvenir. bir Linux ortamını çalıştırmak için gereken minimum miktarı içerir – bazen 5 megabayt kadar az disk alanı ve geleneksel VM'lerden önemli ölçüde daha az bellek.
Docker'ın masaya getirdiği en büyük ikinci faydayı anlamak için biraz geliştirmeye bakalım (PHP veya WP değil, sadece genel olarak geliştirme). Uygulandığı takdirde geliştiricilerin hayatlarını önemli ölçüde kolaylaştıran birkaç geliştirme ilkesi vardır ve bunlardan SOLID adı verilen bir grup vardır.
İlk ilke ( tek sorumluluk ilkesi ) Docker'ın ikinci en büyük avantajıdır: Her Docker Görüntüsü yalnızca bir şeyi ve yalnızca bir şeyi yapmaktan sorumludur. Bir web sunucusuna ihtiyacınız var mı? Nginx görüntüsünü alın. Bir PHP yorumlayıcısına mı ihtiyacınız var? Bunun için bir görüntü var. MySQL? Kontrol.
Aslında, genellikle, birlikte düzgün çalışabilmeleri için Docker'ın kendisi, Docker Swarm veya Kubernetes gibi bazı daha yüksek seviyeli yazılımlar tarafından düzenlenen birkaç Docker konteyneri elde ederiz. Bu serinin üçüncü gönderisinde Kubernetes'i derinlemesine ele alacağız.
Tüm bu sorumlulukları içeren tek bir imaj oluşturmak kesinlikle mümkündür, ancak bundan neden kaçınmanız gerektiğini açıklamak için elimden geleni yapacağım.
İlk resmimiz
Artık Docker'ın ne olduğu hakkında temel bir anlayışa sahip olduğunuza göre, ileride WordPress web sitemiz için kullanacağımız temel bir LEMP yığını (Linux, Nginx, MySQL, PHP) oluşturmaya çalışalım.
Tüm docker kapsayıcıları Linux'a dayalı olduğundan, onu özel olarak oluşturmaya gerek yoktur, o yüzden bunun yerine ilk parçamız olarak Nginx'e odaklanalım. Yeni bir proje dizini oluşturun ve içinde index.html adlı bir dosya oluşturun ve aşağıdaki HTML parçacığını yerleştirin:
<h1>Hello world from Docker!</h1>
Ardından, Docker'ı başarıyla yüklediğinizi varsayarak bu komutu aynı dizinden çalıştırın:
$ docker run -v $(pwd):/usr/share/nginx/html -p 8080:80 nginx
(Bu hatayı alırsanız: docker: Cannot connect to the Docker daemon. bu, docker makine ayarlarını kabuğa yüklemediğiniz anlamına gelir, $ eval "$(docker-machine env default)" çalıştırın)
Büyük olasılıkla yerel olarak Nginx görüntüsüne sahip olmadığınız için Docker, resmi depodan indirecek ve girdiğiniz hacim ve bağlantı noktası parametreleriyle çalıştıracaktır. Çalışıp çalışmadığına dair herhangi bir gösterge vermeyecektir (ilk başta, askıda kalmış gibi görünüyor):

Bu yüzden tarayıcınızı açın ve http://localhost:8080 gidin (veya liman işçisi makinesi kullanıyorsanız, ki bu daha olasıdır, liman işçisi makinenizin IP'si için localhost değiştirin) ve bakın, Hello World! . İşlemi durdurmak için CTRL + C tuşlarına basın.

Az önce ne oldu?
İlk başta biraz sihir gibi görünse de aslında oldukça basit; Docker görüntüyü indirdi ( nginx – komuttaki son kelime) ardından bu görüntüyle iki özel parametre içeren bir kapsayıcı çalıştırdı: Proje dizinimizi ( $(pwd) geçerli veya mevcut çalışma dizini anlamına gelir) /usr/share/nginx/html içine yerleştirdi. /usr/share/nginx/html ve ayrıca konuk işletim sisteminin 80 numaralı bağlantı noktasını ana bilgisayarın 8080 numaralı bağlantı noktasına eşledi – iki nokta üst üste karakterinin yaptığı budur, ana bilgisayardan kapsayıcıya bağlantı noktalarını ve/veya birimleri eşler, bu nedenle 8080:80 , ana bilgisayarda 8080 bağlantı noktasını kullanın ve eşleyin konteynerin içindeki 80 numaralı bağlantı noktasına .
Not: Montaj terimine aşina değilseniz: Bir bilgisayarın kap içindeki belirli bir yol altında bir birimi (bir disk alanı bloğu) taktığı bir işlemdir. Bunu her gün bir USB anahtarı taktığınızda veya bir DVD taktığınızda yaşıyorsunuz – işletim sistemi tarafından otomatik olarak monte ediliyor. USB anahtarlarını güvenli bir şekilde çıkarmanızın nedeni de budur: İşletim sisteminin sürücünün bağlantısını kesmesi gerekir, böylece bozuk verilerle karşılaşmazsınız! Burada önemli bir not: Bir konağın dizinini, orada zaten var olan (ve dosyaları içeren) bir yolun altındaki kapsayıcıya bağlarsanız, bu dizin kaybolmaz, yalnızca dizin takılıyken erişilemez.
Ve bir Docker görüntüsü ile kapsayıcı arasındaki temel farkı anlamamıza yardımcı olabileceği için DVD benzetmesine biraz daha uzun süre bağlı kalırsak: Bir görüntü paketlenmiş, dağıtılabilir ve değişmez bir dosya sistemidir (bir DVD gibi) , kap bu görüntünün çalıştırılabileceği yalıtılmış, çıplak kemikli bir Linux ortamı (bir DVD-ROM gibi, bilgisayarın DVD'de ne varsa çalıştırmanıza izin veren fiziksel bileşeni).
Görüntülerin değişmez yönü onları özellikle ilginç kılar (değişmez, bir görüntü oluşturulduktan sonra içindeki dosyaların hiçbirini değiştiremeyeceğiniz veya kalıcı olarak değiştiremeyeceğiniz anlamına gelir) – bunun nedeni, bunların tamamen atılabilir hale gelmeleridir (karşılaşabileceğiniz başka bir terim de geçici – aynı şey). Görüntüler bir tariften ( Dockerfile olarak adlandırılır) tekrar tekrar oluşturulabilir, bu nedenle herhangi bir değişiklik yapmanız gerekirse, onları yeniden oluşturmanız yeterlidir.
Görüntüler ayrıca çok kullanışlı başka bir SOLID ilkesini izler: Açık-kapalı ilkesi. Bir kod parçasının değişikliğe kapalı, ancak genişletmeye açık olduğunu belirtir. Benzer şekilde, görüntüler değiştirilemez, ancak genişletilebilir.
Temel Nginx imajımız PHP hakkında (veya bu konuda başka bir şey) hiçbir şey bilmediğinden, onu genişletmenin zamanı geldi ve biz bunu şununla yapıyoruz…
Docker dosyası
Basitçe söylemek gerekirse, Dockerfile, Dockerfile bir görüntü oluşturabilmesi için bir dizi talimat içeren bir dosyadır. Bunu nihai görüntümüz için bir plan olarak düşünün. Dockerfile'a koymanız gereken tek zorunlu talimata FROM talimatı denir; Docker'ın, kendinize ait hangi görüntünün temel alınmasını istediğinizi bilmesini sağlar. Resmi depo, hayal edebileceğiniz her türlü Linux çeşidinin veya konfigürasyonunun resimlerini tutar ve Github'a çok benzer şekilde, herhangi bir kullanıcı adı gerektirmeyen resmi olanlar dışında (etiket her zaman isteğe bağlıdır) username/image-name:tag olarak adlandırılırlar. .
Bu nedenle, index.html yanında Dockerfile (uzantısız) adında boş bir dosya oluşturun ve aşağıdaki iki satırı ona yapıştırın (tabii ki MAINTAINER talimatını adınız ve e-postanızla eşleşecek şekilde değiştirin):
FROM nginx:1.10-alpine MAINTAINER Tomaz Zaman <[email protected]>
Özel görüntümüz, resmi Nginx'in Alpine görüntüsüne dayalı olacaktır. Alpine, yalnızca 5 MB ağırlığındaki küçük bir Linux dağıtımıdır ve kutudan çıktığı haliyle apk (Debian/Ubuntu'daki apt-get get'e benzer) adlı bir paket yükleyici sağladığı için Docker topluluğunda çok popüler hale geliyor ve küçük olduğu için , bu iyi bir şey çünkü sonunda görüntüleri (üretim için) aktaracaksınız ve küçük olanları kullanmak mantıklı – Debian, karşılaştırma için yaklaşık ~ 200 MB alıyor çünkü ihtiyacımız olmayan çok daha fazla şey içeriyor. Sadece Nginx'e ve bağımlılıklarına ihtiyacımız var.
İşte Docker kullanmanın bir diğer önemli yararı: Docker görüntüleri genişletilebilir. Ve ortaya çıkan görüntüler de istediğiniz kadar derine genişletilebilir, bu nedenle, tavşan deliğinin görüntü mirasıyla ne kadar derine gittiğini araştırırsanız, nginx:1.10-alpine alpine'in Dockerfile dosyasını kontrol edin, bu FROM alpine:3.3 . Öyleyse Alpine's Dockerfile'ı kontrol edelim. Temelde tamamen boş bir görüntü olan Scratch adlı bir görüntüden miras alır, hiçbir şey yapmaz, ancak esasen diğer tüm görüntülerin büyükannesidir, bu yüzden scratch kelimesi Docker'da ayrılmıştır. Bizim durumumuzda görüntü mirasının nasıl göründüğü:
Bu eğitimde ele almayacağımız ancak bahsetmeye değer bir Dockerfile talimatı CMD talimatıdır. Bu talimat, kapsayıcı herhangi bir parametre olmadan başlatıldığında çalışacak varsayılan bir komut ayarlar, ancak bunu tanımlamamıza gerek yoktu, çünkü Nginx'in Dockerfile'si zaten yapıyor. Bunu yapmasaydı, Nginx'i aşağıdaki gibi bir komutla çalıştırmamız gerekecekti (bir örnek, çalıştırmaya gerek yok):
$ docker run -v $(pwd):/usr/share/nginx/html -p 8080:80 nginx nginx -g "daemon off;"
( nginx kelimesinin neden iki kez göründüğünü merak ediyorsanız: ilk örnek görüntünün adıdır, ikincisi – ve sonraki her şey – kap içinde çalıştırdığımız asıl komuttur)
Bu yüzden imajımızı oluşturmak için şunu çalıştırın:
$ docker build -t my-wordpress .

Bu komut, geçerli dizindeki Docker dosyasını okur ve görüntüyü my-wordpress olarak etiketler, çünkü bunu yazmak, Docker'ın biz onu etiketlemezsek otomatik olarak oluşturduğu rastgele sayıda karakterden daha kolaydır. Test etmek için şunu çalıştırın:
$ docker run -v $(pwd):/usr/share/nginx/html -p 8080:80 my-wordpress
Pek bir şey değişmedi, ancak $ docker images çalıştırırsanız, hem varsayılan nginx imajını (ilk denememizde çalıştırdığımız) hem de my-wordpress imajımızı bulabileceksiniz. Boyutlarına bakın: varsayılan resim ~182MB, özel resmimiz ise sadece ~61MB. Alpine sürümünü kullanmak için ilk komutu (Dockerfile kullanmadan önce) çalıştırabileceğimizi düşünebilirsiniz ve gerçekten de yapabiliriz, bu örneği biraz araştırma yaparak Görüntü boyutlarınızı nasıl küçültebileceğinizi göstermek için kullanıyorum. seçeneklerin. Nginx'in durumunda, epeyce var.

Aynı komutu -v parametresi ( $ docker run -p 8080:80 my-wordpress ) olmadan çalıştırmayı denerseniz, index.html artık sunucu olmadığını fark edeceksiniz – varsayılan Nginx karşılama sayfası, ki bu değil çok faydalı, bu yüzden Dockerfile'ımıza (altta) başka bir talimat ekleyelim:
COPY index.html /usr/share/nginx/html
Tahmin edebileceğiniz gibi, bu talimat index.html dosyamızı Nginx'in varsayılan dizinine kopyalar (aynı ada sahip mevcut dosyaların üzerine yazar). Yine, önemli bir şey değil, ancak imajımızı kendimize yeterli hale getirdik. Dağıtılabilir hale geldi.
Birimleri kullanmak ve dosyaları kopyalamak arasındaki temel fark, genellikle geliştirme aşamasında birimleri monte etmeniz, ancak dağıtım (üretim) için görüntüye kopyalanan dosyalara ihtiyaç duymanızdır. Her değişiklik için görüntüyü yeniden oluşturmanız gerekmediğinden , geliştirme aşamasında birimlerin eklenmesi önemli miktarda zaman kazandırır – Docker, görüntüdeki kaynak dizini yerel olarak sahip olduğunuzla geçici olarak değiştirir.
Bu neden harika? Geliştirme makinemize herhangi bir şey yüklememiz gerekmediğinden, çalıştırmak istediğimiz her şeyi çalıştırmak için gereken her şey görüntüler tarafından sağlanır! Bu, geliştirme bilgisayarınıza artık Nginx, PHP veya MySQL yüklemeniz gerekmediği anlamına gelir, bu iyi bir şeydir, tüm bu işlemler, onları kapatmazsak değerli kaynakları işgal eder – ve çoğunlukla kapatmıyoruz, sadece çalışıyorlar arkaplan.
Yani eğer imajı tekrar derlerseniz ve imajı birimi monte etmeden çalıştırırsanız, Hello World! Tekrar.
Nginx'i Yapılandırma
Nginx imajımız şimdi çalışıyor ve çalışıyor, ancak henüz tam olarak orada değiliz – onu ihtiyaçlarımıza göre değiştirmemiz gerekiyor. En önemli kısım, elbette, sanal ana bilgisayardır . Bir tane oluşturmak için Nginx'in varsayılan yapılandırmasını bir şekilde geçersiz kılmamız gerekiyor. Bunun nerede olduğunu bulmak için konteynere bağlanalım:
$ docker run -it my-wordpress /bin/sh
Daha önce bir sunucuya bağlanmak için SSH kullandıysanız, bu komut oldukça benzer görünebilir, ancak gerçekte, burada SSH söz konusu değildir, yalnızca varsayılan konteynerin kabuğunu çalıştırıyoruz ve onu komut satırımıza (veya terminal, eğer varsa) ekliyoruz. OSX'tesiniz) – -it kısmı onu etkileşimli hale getirir.
Genellikle Debian/Ubuntu tabanlı sistemlerde, Nginx yapılandırması /etc/nginx içinde kurulur ve neyse ki bu görüntü tamamen aynı yapıyı kullanır, bu nedenle $ ls -al /etc/nginx/conf.d/ (kapsayıcının içinde) çalıştırırsanız , gerçekten de orada, birazdan üzerine yazacağımız default.conf adlı tek bir dosya göreceksiniz. Ama önce, aslında orada bir sanal konak olduğunu araştıralım:
$ cat /etc/nginx/conf.d/default.conf

Çıktıdaki server { ... } bloğuna dikkat edin? Bu kadar. Şimdi bu dosyanın kendi versiyonumuzu oluşturalım: Konteynırdan bağlantıyı kesmek için $ exit çalıştırın ve proje dizinimizin içinde nginx.conf adlı yeni bir dosya oluşturun. Aşağıdaki parçacığı içine koyun:
server { server_name _; listen 80 default_server; root /var/www/html; index index.php index.html; access_log /dev/stdout; error_log /dev/stdout info; location / { try_files $uri $uri/ /index.php?$args; } location ~ .php$ { include fastcgi_params; fastcgi_pass my-php:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } }
index.php henüz mevcut olmadığından, onu proje dizininde index.html yanına oluşturun ve <?php phpinfo(); ?> <?php phpinfo(); ?> içinde.
Ardından Dockerfile açın ve şöyle görünecek şekilde değiştirin:
FROM nginx:1.9-alpine MAINTAINER Tomaz Zaman RUN mkdir -p /var/www/html WORKDIR /var/www/html COPY nginx.conf /etc/nginx/conf.d/default.conf COPY . ./FROM nginx:1.9-alpine MAINTAINER Tomaz Zaman RUN mkdir -p /var/www/html WORKDIR /var/www/html COPY nginx.conf /etc/nginx/conf.d/default.conf COPY . ./
Buraya birkaç talimat ekledik: COPY (ki zaten biliyoruz), RUN ve WORKDIR . Son ikisini şimdilik görmezden gelebiliriz, ancak önemli bir resim oluşturma konsepti sunarlar: Her projenin bir kök dizine ihtiyacı vardır ve varsayılan olanlar mutlaka en iyisi değildir (veya mevcut değildir), bu yüzden ilk olarak, biz /var/www/html (WordPress kurulumumuzun kökü olacak) oluşturma ve ardından WORKDIR ayarlama, bu, sonraki tüm talimatların geçerli çalışma dizinini tanımlamak için ./ kullanabileceği anlamına gelir. Bunun bir örneği, bu Docker dosyasının en son satırındadır: . ./ içine, bu, ana makinenizin proje dizinindeki tüm dosyaların görüntünün içinde /var/www/html/ konumunda bulunmasına neden olur. WORKDIR temelde Linux'ta cd komutunu çalıştırmakla aynı şeyi yapar.
Görüntüyü oluşturmayı ve çalıştırmayı denerseniz, bir hata alırsınız çünkü varsayılan olarak Nginx görüntüsü yalnızca düz eski HTML'yi sunar. Yine de yapılandırmamızda, henüz mevcut olmayan başka bir resme ( my-php ) işaret eden bir fastcgi bloğu ( location ~ .php$ { ... } ) sunuyoruz, o yüzden şimdi oluşturalım.
PHP-FPM resmi
Aynı kap içinde hem Nginx hem de PHP-FPM'yi çalıştırmaya çalışan Docker görüntüleri gördüm, bu benim için büyük bir hayır . Yukarıda bahsettiğimiz tek sorumluluk ilkesini hatırlıyor musunuz? Sahip olmamız gereken iki resim: Biri Nginx için (burada hizmet vermek sorumluluktur) ve diğeri PHP-FPM için ( PHP'yi ayrıştırmanın sorumluluk olduğu yerde).
İki ayrı görüntüye sahip olmak neden önemlidir? Yakında göreceğiniz gibi, kapsayıcılardaki işlemler arka planda çalışmadığından (veya en azından çalışması beklenmediğinden), ana ve tek kapsayıcı işlemi olarak çalışıyor olmalılar, böylece başarısız olmaları durumunda Docker (veya yönetim yazılımı) bir şey olduğunu anlayacak ve en azından kabı yeniden başlatmaya çalışacaktır. İdeal olarak, bir görüntü => bir ön plan süreci. Kabul edelim ki, Nginx yerine Apache'yi çalıştırsaydık, bu sorun olmazdı (çünkü PHP bir Apache modülü olarak gelir, bu nedenle ayrı bir süreç yoktur), ancak bazen öğrenme amacıyla işleri aşırı karmaşık hale getirmek işe yarar. Bunun dışında, birçok ileri düzey geliştirici, Nginx'i çeşitli nedenlerle Apache'ye tercih ediyor – ve ben de öyle.
PHP imajımızı oluşturmak için önce resmi depodaki seçeneklerimizi inceleyelim. Birçoğu var, ancak hiçbiri MySQL ve diğer birçok WordPress bağımlılığı için yerleşik desteğe sahip değil, bu yüzden yine kendimizinkini oluşturmaya zorlanıyoruz. Ama Dockerfile'de sadece birkaç satır olduğu için sorun olmamalı, değil mi? Hadi bunu yapalım; Dockerfile.php-fpm adında yeni bir Dockerfile oluşturun ve içine aşağıdaki kodu koyun:
FROM php:7.0.6-fpm-alpine MAINTAINER Tomaz Zaman RUN docker-php-ext-install -j$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) iconv gd mbstring fileinfo curl xmlreader xmlwriter spl ftp mysqli VOLUME /var/www/htmlFROM php:7.0.6-fpm-alpine MAINTAINER Tomaz Zaman RUN docker-php-ext-install -j$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) iconv gd mbstring fileinfo curl xmlreader xmlwriter spl ftp mysqli VOLUME /var/www/html
Buradaki RUN talimatı, resmi resimde varsayılan olarak bulunmayan birkaç bağımlılık yüklememiz gerektiğinden ve WordPress'i çalıştırmak için bunlara ihtiyacımız olduğundan biraz farklıdır. Neyse ki, docker-php-ext-install komutuna sahibiz (nereden geldiğini anlamadıysanız Docker Hub'daki dokümanları okuyun) ve onu -j parametresiyle çağırıyoruz. Bu komut ilk başta oldukça korkutucu görünüyor, ancak aslında yalnızca uzantı yükleyicisinin kaç işlemci kullanabileceğini bilmesini sağlamak içindir. Bu önemlidir, çünkü bazı PHP uzantılarının anında derlenmesi gerekir – bu, hesaplama açısından pahalı bir işlemdir. Şimdi PHP-FPM imajını oluşturalım:
$ docker build -t my-php --file Dockerfile.php-fpm .
Ekranda çok şey göreceksiniz (derleme), ancak uzun sürmemelidir. Ve neyse ki bizim için Docker, talimatları katman adı verilen şeylerde önbelleğe alıyor – bu serinin sonraki bölümünde bununla ilgili daha fazla bilgi var, bu nedenle aynı komutu tekrar çalıştırmayı denerseniz, yalnızca bir saniye kadar sürer.
Dockerfile'ın son biti VOLUME komutudur. Bu sefer görüntüye dosya kopyalamıyoruz, bu ilk başta biraz kafa karıştırıcı gelebilir, o yüzden neler olduğunu anlatayım: Görüntünün kendi başına kaynak dosyası yok, üzerine harici bir birim takılmasını bekliyor. çalışma zamanı sırasında ve burada Docker'ın bir başka avantajı yatıyor: Hacimleri kapsayıcılar arasında paylaşabiliriz, bu da bazı rastgele ana bilgisayar dizinini aynı anda herhangi bir sayıda kapsayıcıya bağlayabileceğimiz ve hepsinin buna erişimi olacağı anlamına gelir. Bu önemlidir çünkü bunu yapmamak Nginx ve PHP-FPM'deki dosyalar arasında tutarsızlıklara yol açacaktır ve bundan kaçınmak istiyoruz. Öyleyse neden aynı verileri aralarında paylaşmıyorsunuz?
Her iki görüntümüz de hazır, aralarındaki bağlantıyı test etme zamanı. İlk olarak, PHP-FPM görüntüsünü getirin (çünkü bu bizim Nginx yapılandırmamız için bir bağımlılıktır ) ve onu arka planda çalıştırın ( -d anlamı budur):
$ docker run -v $(pwd):/var/www/html --name my-php -d my-php
Bu komut hiçbir şey döndürmediğinden, kapsayıcının çalıştığından emin olmak için $ docker ps komutunu çalıştırın. CONTAINER ID not edin, çünkü $ docker stop f0b621891979 girerek durdurmanız gerekecek (kimliğinizle son dizeyi değiştirin). Ve gerçekten, çalışıyor:

Ayrıca, şu şekilde ortaya çıkardığımız Nginx görüntüsüne bağlayabilmemiz için ona bir isim verdiğimizi unutmayın:
$ docker run -it --link my-php:my-php -p 8080:80 my-wordpress
Tarayıcıya geri dönün ve Nginx'in çalıştığını doğrulamak için kullandığınız adresi ziyaret edin ve bakın ve görün!

Buradan sonraki mantıklı adım MySQL imajımızı kurmak olacaktır, ancak bunu yapmadan önce hayatımızı biraz daha kolaylaştıracak başka bir aracı ziyaret edelim; Şimdiye kadar fark edebileceğiniz gibi, Docker komutları çok ayrıntılı hale gelebilir ve genellikle olduğu gibi bunun için ~~bir uygulama~~ bir araç vardır!
Komutları oluşturma
Devam etmeden önce, görüntülerimizi oluşturmak ve kapsayıcılarımızı çalıştırmak için çalıştırmamız gereken bazı komutlarımızı kontrol edelim. Daha da önemlisi, hangi bölümlerin defalarca tekrarlandığını araştıralım:
- Her iki görüntü de
/var/www/htmlaltına harici bir birimin takılmasını gerektirir - Her iki görüntü de belirli bağlantı noktalarını gösterir (Nginx için 80, PHP-FPM için 9000)
- Her iki görüntü de özel bir Docker dosyasından oluşturulur
- Nginx, PHP-FPM'nin mevcut olmasına güvenir (
my-phpana bilgisayar adı olarak)
Docker, hayatımızı kolaylaştırmak için, komutları kısaltmak (ve daha azını) yapmak için tüm bu yapılandırmayı bir dosyaya koymamıza izin veren bir araçla birlikte gelir. Aracın adı docker-compose (eski günlerde fig olarak bilinirdi) ve projenizin dizininde docker-compose.yml adlı bir dosyanın bulunmasını gerektirir, bu nedenle bir tane oluşturun ve şu kodu yerleştirin:
version: '2' services: my-nginx: build: . volumes: - .:/var/www/html ports: - "8080:80" links: - my-php my-php: build: context: . dockerfile: Dockerfile.php-fpm volumes: - .:/var/www/html ports: - "9000:9000"
Docker-compose, görüntüleri her zaman anında etiketlemek ve adlandırmak yerine, yapılandırma dosyasından gerekli tüm bilgileri çıkarır. İçinde, biri my-nginx (Nginx resmimiz) ve diğeri my-php olarak adlandırılan iki hizmet tanımlıyoruz.
my-nginx görüntüsü, derleme yolu için geçerli dizini kullanır (dolayısıyla . ) çünkü docker-compose varsayılan olarak orada bir Dockerfile bekler. Ayrıca, ana bilgisayardaki mevcut proje dizinini konteynerdeki /var/www/html ( volumes tuşu ile) ve ayrıca ports eşleştiririz, tıpkı -p komutumuzda olduğu gibi, bu artık gerekli olmayacaktır. Son olarak, onu my-php görüntüsüne bağlarız – Docker bunun için perde arkasında dahili bir ağ kurar.
my-php görüntüsüne gelince, build anahtarı biraz farklıdır, çünkü Dockerfile standart adı kullanmaz (daha fazla ayrıntı için buraya bakın). my-nginx görüntümüz gibi, birimi de monte ediyoruz ve bağlantı noktalarını eşliyoruz.
Şimdi eğlenceli kısım geliyor! Docker-compose kullanarak görüntüler oluşturmak için sadece çalıştırın (önbelleğe almayı görmek için iki kez yapın):
$ docker-compose build
Bir kez oluşturulduktan sonra, kapsayıcıları getirmek için yalnızca bir komut daha çalıştırmamız gerekir:
$ docker-compose up
Evet! İşte bu – artık uzun docker komutları yok, docker-compose sonuna kadar!
MySQL'e ne dersin?
Docker ile imaj oluşturmanın henüz bahsetmediğimiz çok önemli bir parçası ortam değişkenleridir . Bunları öğreticimizin sonraki bölümünde biraz daha derinlemesine tartışacağız, ancak hızlı bir giriş için MySQL imajımızı bunları kullanarak oluşturacağız.
PHP-FPM imajımızın aksine, özel bir MySQL imajı oluşturmaya gerek yoktur (ancak isterseniz kesinlikle yapabilirsiniz), resmi olan zaten ihtiyacımız olan her şeyle birlikte gelir!
Bu nedenle, uzun ve zahmetli docker komutunu atlayacağız ve yapılandırmayı doğrudan docker-compose.yml dosyasına ekleyeceğiz. En alta aşağıdaki satırları ekleyin (diğer hizmetler gibi girintili olmasına dikkat edin):
my-mysql: image: mariadb:5.5 volumes: - /var/lib/mysql environment: MYSQL_ROOT_PASSWORD: wp MYSQL_DATABASE: wp MYSQL_USER: wp MYSQL_PASSWORD: wp
Ayrıca, onu my-php görüntüsünden bağlamayı da unutmayın, bu yüzden sonuna şunu ekleyin:
my-php: (existing configuration) links: - my-mysql
$ docker-compose build çalıştırmayı denerseniz, MySQL görüntüsünün oluşturulmadığını fark edeceksiniz – bunun nedeni resmi depoda zaten oluşturulmuş ve saklanmış olmasıdır, yalnızca indirmemiz gerekir, çalıştırdığınızda otomatik olarak gerçekleşecektir. , o zaman devam et:
$ docker-compose up
Gerçekten çalıştığından emin olmak için kod düzenleyicinize geçin (ancak docker-compose durdurmayın ) ve projenizin kök dizininde db-test.php adlı yeni bir dosya oluşturun ve aşağıdaki içeriği buraya koyun:
<?php $dbuser = 'wp'; $dbpass = 'wp'; $dbhost = 'my-mysql'; $connect = mysqli_connect($dbhost, $dbuser, $dbpass) or die("Unable to Connect to '$dbhost'"); echo "Connected to DB!";
Tarayıcınıza geri dönün ve bu dosyayı adres çubuğuna manuel olarak girin, böylece şöyle görünür: http://localhost:8000/db-test.php . Connected to DB! , iyi yapılmış bir iş için arkana hafifçe vur!
Peki neden çalışıyor?
Çünkü resmi MariaDB görüntüsü, ortam değişkenlerini en yaygın yapılandırma seçenekleri olarak kabul edecek şekilde oluşturulmuştur. Bu nedenle docker-compose yapılandırmamıza environment anahtarını ekledik ve bu seçenekleri orada ayarladık. Yapılandırma seçenekleri olarak ortam değişkenlerine sahip olmak, yeni sunucuları yatay olarak tanıtarak (birçok sunucu aynı kodu sunar) uygulamalarımızı ölçeklendirmeye başladığımızda (ve WordPress farklı değildir) çok kullanışlı hale gelir – 12 faktörlü uygulamalara bağlıdır.
İşaret edilecek son bit, volumes anahtarıdır. Burada, onu herhangi bir ana bilgisayarın dizinleriyle eşlemiyoruz, bunun yerine sadece Docker'ın sahne arkasında oluşturacağı (ve hakkında bilgi sahibi olacağı) bir birim tanımlıyoruz. Bu yararlıdır çünkü daha önce öğrendiğimiz gibi görüntüler değişmezdir, bu yüzden bunu yapmasaydık, kapsayıcıyı durdurduğumuzda tüm MySQL verileri kaybolacaktı. Bu şekilde, bu birimi çalıştırmalar ve verilerimiz arasında kalıcı hale getiriyoruz.
Çözüm
Bu eğitimde öğrendiklerimizi tekrarlayalım:
- Dockerfile, özel Docker görüntüleri oluşturmak (veya daha doğrusu mevcut olanları genişletmek ) için bir plandır.
- Docker görüntüleri tek kullanımlık, dağıtılabilir ve değişmez dosya sistemleridir
- Docker Containers, görüntülerin çalıştırılabileceği temel Linux ortamı sağlar
- Her proje, gereksinimlere göre kendi Docker görüntülerini tanımlayabilir
- Docker ile yerel olarak herhangi bir şey yüklememize gerek yok (Docker'ın kendisi dışında)
- Birçok amaç için Docker Hub'daki mevcut görüntüleri kullanabiliriz.
- Docker, boru hattında Windows ve Mac desteği ile Linux üzerinde yerel olarak çalışır
- Her şey için görüntüler oluşturabiliriz, ancak her birinin genellikle ön planda çalışan bir süreç biçiminde tek bir sorumluluğu olmalıdır.
- docker-compose, bize biraz yazmaktan tasarruf etmenin uygun bir yolunu sunar
- Eşleme, ana bilgisayarın kaynaklarını kapsayıcıya bağlamak için uygun bir yol sağlar
- Montaj, ana bilgisayarın dizinlerini kapsayıcıya takmak için uygun bir yol sağlar
Tüm bunların başlangıçta oldukça ürkütücü olabileceğinin farkındayım, ancak yalnızca bu eğitimde ana hatları verilen birçok fayda nedeniyle değil, aynı zamanda bizi işleri belirli bir şekilde yapmaya zorlayacağı için Docker'ın geleceğe giden yol olduğuna kesinlikle inanıyorum. Bu yolun iyi mi yoksa kötü mü olduğuna siz karar verirsiniz, ancak yine de geliştiricilerin çoğunluğunun izlediği yol, gelecek için güçlü bir temel haline gelir. Ne de olsa WordPress bize bunu öğretti.
WordPress'ten bahsetmişken, bu bölümde bununla ilgilenmedik çünkü zaten yeterince uzun ve anlaşılması biraz zaman alacak, bu yüzden önümüzdeki haftalarda yapılması planlanan bir sonraki yazıda bunu ele alacağım. Abone olmayı unutmayın!
Bu makalenin teknik incelemesi için Mario Peshev'e teşekkür etmek istiyorum.
ev borcu WordPress sitesi
