Giriş
WordPress piyasadaki en popüler İçerik Yönetim Sistemlerinden (CMS) biridir. İstatistiksel olarak, dünya genelinde gördüğünüz tüm web sitelerinin %39'undan fazlasına güç vermektedir. Eklentiler aracılığıyla genişletilebilirliği ve esnek şablon sistemi nedeniyle popüler bir seçimdir. Görünümünü saniyeler içinde değiştirmenize olanak tanır. Dahası, yönetimi çok fazla teknik bilgi gerektirmeden web arayüzü üzerinden yapılabilir.
Ayrıca WordPress ücretsiz ve açık kaynaklıdır ve PHP işleme özelliğine sahip bir MySQL veritabanı üzerine kurulmuştur. WordPress'i WordPress'i bir LAMP yığını (Linux, Apache, MySQL ve PHP) üzerinde dağıtabilir veya bir LEMP yığını (Linux, Nginx, MySQL ve PHP) üzerinde dağıtabilirsiniz. Ancak, her dağıtım yapmak istediğinizde yığını kurmak zaman alıcı olabilir.
Neyse ki, bulut bilişim, Docker ve Docker Compose gibi modern yazılım teslim yöntemleri genel geliştirici deneyimini kolaylaştırmıştır. Bu araçlar, bir uygulamayı her dağıtmak istediğinizde tek tek bileşenleri kurma ve yapılandırma yükünden kaçınarak herhangi bir yığını kurma sürecini basitleştirir. Bunun yerine, imajları çekmek, oluşturmak ve bunları Docker konteynerlerinde çalıştırmak için kullanılacak yapılandırma dosyaları yazarsınız ve bu da uygulamanızı tek bir komutla dağıtmanıza olanak tanır.
Konteynerler, yazılımın fiziksel ana makinede çalışan diğer yazılımlardan yalıtılmış olarak çalışmasını sağlayan hafif, sanallaştırılmış, taşınabilir, yazılımla tanımlanmış standartlaştırılmış ortamlardır. Docker Compose, birden fazla konteyneri yönetmenize ve bunların iletişim kurmasını sağlamanıza olanak tanır. Örneğin, bir uygulama kaynak kodu ile bir veritabanı iletişim kurmalıdır.
Bu eğitimde, çoklu konteynerli bir WordPress uygulaması oluşturacağız. Eksiksiz bir WordPress uygulaması üç konteyner gerektirir: MySQL veritabanı, Nginx sunucusu ve WordPress kaynak kodu. Modern web sitelerinde güvenlik bir öncelik olduğundan, kurulumunuzu güvence altına almak için Let’s Encrypt üzerinden bir SSL sertifikası alacağız. Ardından, web sitenizin güvenliğinin sürekli olarak korunmasını sağlamak amacıyla sertifikaları periyodik olarak kontrol etmek ve yenilemek için bir cron görevi ayarlayacağız.
Önkoşullar
- Bu uygulamalı bir eğitim olduğundan, başlangıç işletim ortamınız olarak bir Ubuntu 20.04 kurulumuna sahip olmalısınız. Ayrıca sudo yetkilerine sahip root olmayan bir kullanıcıya sahip olmalısınız. İşte Ubuntu sunucunuzu kurmanıza yardımcı olacak adım adım bir eğitim.
- . Ayrıca Docker'ı da kurmanız gerekir. Ubuntu 18.04 üzerinde Docker'ın nasıl kurulacağı ve çalıştırılacağı hakkındaki bu eğitime.
- başvurabilirsiniz. Docker Compose kurulumu için eğitimin Ubuntu 20.04 üzerinde Docker Compose Nasıl Kurulur ve Yapılandırılır başlıklı olanının 1. Adımını takip edebilirsiniz.
- Bir Let’s Encrypt TLS/SSL sertifikası almak için kayıtlı bir alan adı gereklidir. Bu eğitim için
example.com. - adresini kullanacağız. Trafiği VPS'nize yönlendirmek için DNS kayıtlarını ayarlayın. İki DNS kaydına ihtiyacınız vardır:
- Sunucunuzun genel IP adresini gösteren,
example.comdeğerine sahip bir A kaydı. - Sunucunuzun genel IP adresini gösteren,
www.example.comdeğerine sahip bir A kaydı.
- Sunucunuzun genel IP adresini gösteren,
Adım 1: Web Sunucusu için Yapılandırmaları Tanımlama
Web sunucusu, web sitenizin dosyalarını barındırır ve kullanıcıların web uygulamanıza erişmesini sağlar. Bu nedenle, ilk adımda web sunucusunun yapılandırmasını tanımlamamız son derece uygundur. WordPress'e özgü konum bloklarını içerecek bir Nginx sunucu yapılandırma dosyası tanımlayacağız. Ayrıca, sertifikanın otomatik olarak yenilenmesi amacıyla Let’s Encrypt doğrulama isteklerini Certbot istemcisine yönlendirmek için konum blokları da ekleyeceğiz.
Proje için bir dizin oluşturarak başlayalım. Tercih ettiğiniz bir dizin adını seçebilirsiniz. Bu eğitim için wordpress_docker kullanacağız. Dizini oluşturmak ve içine girmek için aşağıdaki komutu girin:
|
1 |
mkdir wordpress_docker && cd wordpress_docker |
Ardından, aşağıdaki komutla Nginx yapılandırma dosyalarını tutacak bir dizin oluşturun:
|
1 |
mkdir nginx-conf |
Dosyayı aşağıdaki komutla açmak için nano kullanın:
|
1 |
nano nginx-conf/nginx.conf |
Bu dosyada, bir Nginx sunucu bloğu yapılandırması için temel yönergeleri tanımlayacağız. Bunlar arasında sunucu adı, belge kökü (document root) ve sertifikalar, statik dosyalar ile PHP işleme için Certbot eklentisi isteklerini yönlendirecek konum (location) blokları yönergeleri yer almaktadır. Daha fazla bilgi edinmek için Let’s Encrypt ile Nginx Nasıl Güvenli Hale Getirilir hakkındaki eğitimimizi okuyabilirsiniz. Dosyaya aşağıdaki kodu ekleyin ve example.com kısmını kayıtlı alan adınızla değiştirin:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
server { listen 80; listen [::]:80; server_name example.com www.example.com; index index.php index.html index.htm; root /var/www/html; location ~ /.well-known/acme-challenge { allow all; root /var/www/html; } location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass app:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~ /\.ht { deny all; } location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { log_not_found off; access_log off; allow all; } location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ { expires max; log_not_found off; } } |
Eklediğiniz bölümleri tanımlayalım:
-
Yönergeler:
listen: Nginx'e şu portu dinlemesini söyler:80. Bu, sertifika istekleri yapmak için Certbot'un webroot eklentisinin kullanılmasını sağlar. Bir SSL sertifikası aldıktan sonra, bu yapılandırmayı şu portu kullanacak şekilde güncelleyeceğiz:443.server_name: bu, bu yapılandırmanın işlemesi gereken alan adını tanımlar. Burada tanımlanan alan adına gelen trafik bu özel sunucu bloğuna ve dolayısıyla belgekök dizinine (root).root: yukarıdaki alan adına yapılan istekler için kök dizini tanımlar. Genellikle gerçek web sitesi dosyalarımızı barındıran dizindir. Dizini şu şekilde ayarladık:/var/www/html. Bu dizin bir Docker bağlama noktası (mount point) konteyner oluşturma süresi boyunca. Bu işlem için talimatları şunun içinde tanımlayacağız: WordPress Dockerfile.index: bu, istekleri işlerken web sunucunuz için dizin veya giriş noktası olarak kullanılacak dosyaları tanımlar. Nginx'in öncelik vermesi için index.php'yi index.html'den önceye taşıdık:index.php.
-
Location Blokları:
location ~ /.well-known/acme-challenge: Certbot'un, belirtilen alan adı için DNS yönlendirmesinin SSL sertifikaları talep ettiğimiz belirli sunucuya yapıldığını doğrulamak üzere geçici bir dosya eklediği well-known dizinine yapılan istekleri işler. Bu nedenle, bu adımın çalışması için bu eğitimde kullandığımızexample.comyerine geçerli bir alan adı eklemelisiniz.location /: URI isteklerini alır ve işleme argümanları talep etmek üzere kontrolü WordPressindex.phpdosyasına verir.location ~ \.php$: PHP işlemeyi yönetir ve isteği WordPress konteynerine iletir (bunun için sonraki bir adımda bir yapılandırma dosyası tanımlayacağız). Burada şuna özel yapılandırmalar tanımladık: FastCGI protokolü, çünkü WordPress Docker imajı şu imaja dayanacaktır: php:fpm imajı. Nginx, PHP'ye özel istekler için bağımsız bir PHP işlemcisi kullanır. Şununla birlikte gelenphp-fpmişlemcisini kullanacağız:php:fpmDocker imajı.location ~ /\.ht: Nginx'in kullanmadığı.htaccessdosyalarını işler.deny allyönergesi, bu dosyaların web sitesi ziyaretçilerine asla sunulmamasını sağlar.location = /favicon.ico, location = /robots.txt: tanımda görüldüğü gibi, bu durum şu dosyalara yapılan isteklerin günlüğe kaydedilmesini önler:/favicon.icove/robots.txtdosyaları.location ~* \.(css|gif|ico|jpeg|jpg|js|png)$: statik dosyalara yapılan isteklerin günlüğe kaydedilmesini kapatır ve sunucu üzerindeki yükü azaltmak için bunların önbelleğe alınmasını sağlar.
Şimdi şu tuşlara basarak dosyayı kaydedip kapatabilirsiniz: CTRL+X, Y, ardından ENTER. Bu, ilk adımı tamamlar.
Adım 2: Ortam Değişkenlerini Tanımlama
Ortam değişkenleri, WordPress uygulaması ile Veritabanı arasındaki iletişimi kolaylaştırmak için gereklidir. Ayrıca uygulama verilerinin kalıcı olmasını sağlarlar. Ortam değişkenleri, veritabanı kimlik bilgileri gibi hassas bilgileri ve veritabanı adı ile ana bilgisayarı gibi hassas olmayan bilgileri içerir.
Güvenlik amacıyla, hassas bilgileri proje depolarına eklememek her zaman iyi bir fikirdir. Bu nedenle, hassas değerleri Docker Compose dosyasında ayarlamak yerine, MySQL kimlik bilgilerini proje deposuna taahhüt edilmeyecek ve kamuya açık hale gelme riski taşımayacak olan .env dosyalarının içinde tanımlayacağız. Proje kök dizini olan root ~/wordpress_docker içinde .env dosyasını açın:
|
1 |
nano .env |
|
1 2 3 |
MYSQL_ROOT_PASSWORD=your_strong_root_password MYSQL_USER=your_wordpress_database_user MYSQL_PASSWORD=strong_wordpress_database_password |
Yapmanız gereken bir sonraki şey, sırasıyla depolarınıza veya Docker imajlarınıza eklenmediğinden emin olmak için .env dosyasını .gitignore ve .dockerignore dosyalarına eklemektir.
Bu eğitim için bu gerekli değildir, ancak sürüm kontrolü için Git ile çalışmak istiyorsanız, mevcut dizini bir git deposu olarak başlatmak için aşağıdaki komutu girin:
|
1 |
git init |
Open the .gitignore dosyasını nano ile açın:
|
1 |
nano .gitignore |
Aşağıdaki satırı ekleyin:
|
1 |
.env |
Dosyayı kaydedip kapatın. Ardından, .dockerignore dosyasını nano ile açın:
|
1 |
nano .dockerignore |
Aşağıdaki satırı ekleyin:
|
1 |
.env |
Hazır başlamışken, isteğe bağlı olarak uygulamanızın geliştirilmesiyle ilişkili diğer dosya ve dizinleri de ekleyebilirsiniz:
|
1 2 3 |
.env .git docker-compose.yml |
İşiniz bittiğinde dosyayı kaydedip kapatın. Bu adım için bu kadar. Docker Compose tanımına geçelim.
Adım 3: Docker Compose ile Servisleri Yapılandırma
Docker Compose, imajlar oluşturmak için bir docker-compose.yml dosyası kullanır. Bu dosya, bir uygulamanın eksiksiz kurulumu için servis tanımlarını içerir. Servis tanımları, temel olarak bir konteynerin nasıl çalışacağına dair talimatlardır. Bir servis, fiilen çalışan bir konteynerdir.
Docker Compose, çeşitli servisleri paylaşılan ağlar ve birimler (volumes) ile birbirine bağlayarak çoklu konteyner uygulamaları için farklı servisler tanımlamayı mümkün kılar. Uygulamamız için üç konteyner tanımlayacağımızdan bunu iş başında göreceksiniz: web sunucusu, WordPress kurulumu ve veritabanı. Sertifika yenilemeleri için Certbot istemcisini çalıştıracak dördüncü bir konteyner ekleyeceğiz.
Aşağıdaki komutu girerek docker-compose.yml dosyasını oluşturun:
|
1 |
nano docker-compose.yml |
Bir docker-compose.yml dosyasındaki ilk satır, sürüm tanımı satırıdır. Biz kendimizinki için 3 olarak ayarladık. Ardından, servislerinizi tanımlamaya başlayabilirsiniz. db servisini tanımlamak için dosyaya aşağıdaki kod parçacığını ekleyin:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
version: '3' services: #MySQL Servisi db: image: mysql:8.0 container_name: db restart: unless-stopped env_file: .env environment: - MYSQL_DATABASE=wordpress volumes: - dbdata:/var/lib/mysql command: '--default-authentication-plugin=mysql_native_password' networks: - app-network |
Aşağıdaki db servis tanımlarında neler olduğuna göz atalım:
image: konteynerin temel alacağı imajı belirler. Belirli bir sürüm belirtmek (mysql:8.0) belirtmek, en son etiketi (mysql:latest) kullanmaktan her zaman daha iyidir; çünkü gelecekteki MySQL imajları sürümleri, bu imajı yeniden oluşturmamız durumunda uygulamamızla çelişebilir. Resmi Dockerfile Belgelerindeki Dockerfile En İyi Pratikleri hakkında daha fazla bilgi bulabilirsiniz.container_name: burada konteyner adını belirtiyoruz.restart: bu yönerge konteynerin yeniden başlatma davranışını belirler. Varsayılan değernoşeklindedir ancak biz bunu her zamanyeniden başlatılacakşekilde (manuel olarak durdurulmadığı sürece) ayarladık.env_file: bu yönerge, uygulamamız tarafından kullanılan ortam değişkenlerini içeren dosyanın (.env) konumunu belirtmek için kullanılır.environment: ek ortam değişkenlerini belirtmek için kullanılır. Bu öğreticide, uygulamamızın veritabanı adını tutması içinMYSQL_DATABASEdeğişkenini belirttik. Veritabanı adıdocker-compose.yml.volumes: bağlama (mount) konumlarını belirtmek için kullanılır. Örneğimizde, birim (volume) adında bir birimi, konteyner üzerindeki/var/lib/mysqldizinine bağladık; bu dizin genellikle MySQL için standart veri dizinidir.command: bu yönerge, imaj için varsayılan CMD talimatını geçersiz kılacak bir komut belirtir. Docker imajının, konteyner içinde MySQL sunucusunu başlatan standartmysqldkomutuna bir seçenek ekledik. Eklediğimiz seçenek--default-authentication-plugin=mysql_native_passwordolup, MySQL için varsayılan kimlik doğrulama eklentisini şifre kimlik doğrulaması (mysql_native_password) kullanacak şekilde günceller. Bu, PHP (WordPress uygulamanızın çalışması) için gereklidir çünkü veritabanına erişmek için bir kullanıcı adı ve şifre kullanırlar. Daha yeni MySQL sürümlerinde, varsayılan kimlik doğrulama eklentisi değişmiştir. Ancak çoğu uygulama şifre kimlik doğrulaması kullanır. Bu nedenle, uygulamanın çalışması için bu ayarı değiştirmeniz gerekir.networks: bu yönerge,dbservisinin, öğretici boyunca tanımlayacağımızapp-networkağına katılması gerektiğini belirtmek için kullanılır.
Ardından, WordPress uygulamamız için servis yapılandırmasını tanımlayalım. Servisi ve container_name'i app olarak adlandıracağız. Aşağıdaki kod parçacığını db servis tanımının altına, uygun girintilemeye dikkat ederek ekleyin:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#WordPress uygulama kodu Servisi app: depends_on: - db image: wordpress:5.1.1-fpm-alpine container_name: app restart: unless-stopped env_file: .env environment: - WORDPRESS_DB_HOST=db:3306 - WORDPRESS_DB_USER=$MYSQL_USER - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD - WORDPRESS_DB_NAME=wordpress volumes: - app:/var/www/html networks: - app-network |
Tıpkı db servisinde yaptığımız gibi, konteynerimizi adlandırdık ve yeniden başlatma politikasını tanımladık. Eklediğimiz diğer bazı seçenekler aşağıda tanımlanmıştır:
depends_on: bu yönerge, konteynerlerin bağımlılık sırasına göre başlatılmasını sağlar. Bizim durumumuzda,appkonteyneridbkonteynerine bağımlıdır. Bu nedenle,dbkonteyneri başlatıldıktan sonra başlayacaktır. WordPress uygulamasının çalışabilmesi için bir MySQL veritabanının kullanılabilir olmasına bağımlı olduğundan, bunun bu sırayla gerçekleşmesi gerekir.image: kod parçacığında görüldüğü gibi, WordPress sürüm 5.1.1 fpm alpine imajını kullanacağız. Nginx'in PHP işleme için ihtiyaç duyduğuphp-fpmişlemcisini açıklamıştık. Bu imaj bu işlemi halleder. Alpine Linux projesini temel alan alpine imajı, imaj boyutunun daha küçük tutulmasına yardımcı olur. İmaj varyasyonları hakkında daha fazla bilgiye ihtiyacınız varsa, Docker Hub Wordpress imajları için bu bağlantıyı takip edebilirsiniz.env_file: veritabanı kimlik bilgilerini içeren.envdosyasının konumunu belirtir.environment: bu yönerge ek ortam değişkenlerini tanımlar. Bizim durumumuzda, WordPress'in beklediği değişkenleri tanımlıyor ve bunlara.envdosyamızdaki değişkenlerin değerlerini atıyoruz. Bunlar;WORDPRESS_DB_USER,WORDPRESS_DB_PASSWORD, veWORDPRESS_DB_HOSTolup,dbkonteynerinde çalışan ve MySQL'in varsayılan bağlantı noktasından erişilebilen MySQL sunucusunu ifade eder3306. Son olarak, WordPress olarak ayarladığımızWORDPRESS_DB_NAMEdeğişkenini görüyorsunuz. Aynı değer, db konteynerindeki MySQL servis tanımında da belirtilmiştir:MYSQL_DATABASE=wordpress.volumes: bu yönerge,/var/www/htmlbağlama noktasına, WordPress imajı tarafından oluşturulan app adlı bir birimi bağlar. Birimlerin adlandırılması, uygulama kodunun diğer konteynerlerle paylaşılmasına olanak tanır.networks: son olarak, app konteyneriniapp-networkağına ekleyerek ağdaki diğer konteynerlerle iletişim kurmasını sağlıyoruz.
WordPress imajına ait app servis konteyneri için bu kadar. Şimdi Nginx imajı için webserver servisini tanımlayalım. İlk olarak, docker-compose.yml dosyanızdaki app servis tanımının altına aşağıdaki kod parçacığını ekleyin:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#Webserver Nginx servisi webserver: depends_on: - app image: nginx:1.15.12-alpine container_name: webserver restart: unless-stopped ports: - "80:80" volumes: - app:/var/www/html - ./nginx-conf:/etc/nginx/conf.d - certbot-etc:/etc/letsencrypt networks: - app-network |
Daha önce depends_on seçeneğini açıklamıştık. Bu webserver servisi durumunda, konteyner app konteyneri başlatıldıktan sonra başlayacaktır. Web sunucusu konteyneri, alpine Nginx imajını temel alır. Önceki servis tanımlarıyla benzer bir yeniden başlatma politikasına sahiptir. Web sunucusu servis tanımındaki diğer seçenekler şunlardır:
ports: ana makine ile konteyner arasındaki portları bağlar. Adım 1'de,80portununginx.confdosyasında tanımlamıştık. Bu port, konteyner üzerindeki80portuna eşlenir.volumes: bu seçeneğin altında bind mounts ve adlandırılmış birimlerin bir kombinasyonu bulunur:app:/var/www/html: bu birim tanımı, WordPress uygulamasını, daha önce Nginx sunucu bloğunda kök dizin olarak ayarladığımız/var/www/htmldizinine bağlar../nginx-conf:/etc/nginx/conf.d: bu tanım, ana makinedeki Nginx yapılandırma dizinini konteyner için tanımladığımız Nginx yapılandırma dizinine bağlar (bind mount). Bu nedenle, ana makinedeki herhangi bir değişiklik otomatik olarak konteynere yansıtılır.certbot-etc:/etc/letsencrypt: bu tanım, alan adı için Let’s Encrypt sertifikalarını ve anahtarlarını konteyner üzerindeki uygun dizine bağlar.
networks: önceki servis tanımlarında olduğu gibi,networksyönergesi, webserver servisini şu ağa ekler:app-networks.
Web sunucusu tanımını tamamladığımıza göre, Certbot servisi için talimatları ekleyelim. Bu servis, TLS/SSL sertifikalarınızı Let’s Encrypt'ten almayı üstlenecektir. Bir Nginx sunucusunu güvenli hale getirmek hakkında daha fazla bilgi edinmek isterseniz, Let’s Encrypt ile Nginx nasıl güvenli hale getirilir konulu bu kılavuz iyi bir kaynaktır.
Ardından, web sunucusu servisinin altına aşağıdaki kod parçacığını ekleyin. Doğru alan adınızı ve e-posta adresinizi ayarlamayı unutmayın:
|
1 2 3 4 5 6 7 8 9 10 |
#certbot servisi certbot: depends_on: - webserver image: certbot/certbot container_name: certbot volumes: - certbot-etc:/etc/letsencrypt - app:/var/www/html command: certonly --webroot --webroot-path=/var/www/html --email hackins@cloudsigma.com --agree-tos --no-eff-email --staging -d example.com -d www.example.com |
The certbot imajı, webserver başladıktan sonra başlayacaktır, çünkü depends_on yönergesi kullanılmıştır. Docker Compose, tanımlandığı gibi Docker Hub'dan Certbot imajını çekecektir.
Birimler (volumes) tanımı altında, Certbot konteyneri certbot-etc içindeki alan adı sertifikalarını ve anahtarını Nginx webserver konteyneri ile ve uygulama kodunu app konteyneri ile paylaşacaktır.
Under the command tanımı altında, konteynerin varsayılan Certbot certonly komutunu aşağıda listelenen ek seçeneklerle çalıştırmak için bir alt komut belirttik:
-
--webroot: kimlik doğrulama için dosyaları webroot klasörüne yerleştiren webroot eklentisinin kullanılacağını belirtir.--webroot-path: webroot dizininin yolunu belirtir.--agree-tos: ACME'nin Hizmet Şartlarını.--no-eff-emailkabul ettiğinizi belirtir. --no-eff-email: e-postanızı EFF ile paylaşmak istemediğinizi belirtir. Paylaşmak istiyorsanız bunu atlayabilirsiniz.--staging: Certbot'a, gerçek sertifikayı almadan önce yapılandırmanızı test etmek için ilk olarak Let's Encrypt hazırlık (staging) ortamından test sertifikaları almak istediğinizi söyler. Let's Encrypt'in alan adı istek oranı sınırlaması (rate limiting) vardır. Bu nedenle, önce yapılandırmanızı test etmek, alan adınızın sınırlandırılmasını önlemenize yardımcı olacaktır.-d: bu seçenek, sertifika talebi için alan adlarını alır. Bu kılavuzda,example.comvewww.example.comalan adlarını dahil ettik. Lütfen kendi kayıtlı gerçek alan adınızı belirtin.
Our docker-compose.yml dosyamız neredeyse tamamlandı. Ancak, Certbot servisinin altına ağ ve birim (volume) tanımlarını da eklemelisiniz:
|
1 2 3 4 5 6 7 8 9 10 |
#Birimler volumes: certbot-etc: app: dbdata: #Ağlar networks: app-network: driver: bridge |
The volumes anahtarı, bu compose dosyasında tanımlanan tüm servislerle (konteynerlerle) paylaşılacak birimleri tanımlar: certbot-etc, app, ve dbdata. Docker'ın oluşturduğu birimlerin içerikleri, ana makine dosya sisteminde Docker tarafından yönetilen bir dizinde saklanır: /var/lib/docker/volumes/. Her bir birimin (volume) içeriği daha sonra o birimi kullanan herhangi bir konteynere bağlanır (mount edilir). Bu, konteynerler arasında veri ve kod paylaşımını mümkün kılar.
The networks anahtarı, konteynerler arasında iletişimi sağlayan köprü ağını (bridge network) tanımlar. Aynı köprü ağındaki webserver ve db gibi konteynerler, trafiği dış ağa maruz bırakmadan portlar aracılığıyla güvenli bir şekilde iletişim kurabilir. Ön uç web sitesi sayfalarına erişime izin vermek için yalnızca 80 portunu dışarıya açıyoruz.
Tamamlanmış docker-compose.yml dosyası şu şekilde görünecektir:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
version: '3' services: #MySQL Servisi db: image: mysql:8.0 container_name: db restart: unless-stopped env_file: .env environment: - MYSQL_DATABASE=wordpress volumes: - dbdata:/var/lib/mysql command: '--default-authentication-plugin=mysql_native_password' networks: - app-network #WordPress uygulama kodu Servisi app: depends_on: - db image: wordpress:5.1.1-fpm-alpine container_name: app restart: unless-stopped env_file: .env environment: - WORDPRESS_DB_HOST=db:3306 - WORDPRESS_DB_USER=$MYSQL_USER - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD - WORDPRESS_DB_NAME=wordpress volumes: - app:/var/www/html networks: - app-network #Web sunucusu Nginx servisi webserver: depends_on: - app image: nginx:1.15.12-alpine container_name: webserver restart: unless-stopped ports: - "80:80" volumes: - app:/var/www/html - ./nginx-conf:/etc/nginx/conf.d - certbot-etc:/etc/letsencrypt networks: - app-network #certbot servisi certbot: depends_on: - webserver image: certbot/certbot container_name: certbot volumes: - certbot-etc:/etc/letsencrypt - app:/var/www/html command: certonly --webroot --webroot-path=/var/www/html --email hackins@cloudsigma.com --agree-tos --no-eff-email --staging -d example.com -d www.example.com #Birimler volumes: certbot-etc: app: dbdata: #Ağlar networks: app-network: driver: bridge |
Dosyayı kaydedip kapatabilirsiniz. Bir sonraki adımda, konteyneri başlatıp test edeceğiz ve sertifika taleplerini gerçekleştireceğiz.
Adım 4: Konteynerleri Çalıştırma ve SSL Sertifikalarını Alma
Docker Compose'un en büyük avantajı, tüm servislerinizi docker-compose.yml dosyası ile tüm konteynerleri tek bir komutla başlatabilirsiniz: docker-compose up. Bu komut, belirtilen her talimatı çalıştırır. Alan adı istekleri başarılı olursa, terminalinizde doğru çıkış durumunu görebilmeniz gerekir. Konteynerleri oluşturmak için aşağıdaki komutu girin. -d bayrağı, konteynerleri arka planda çalıştırmak içindir:
|
1 |
docker-compose up -d |
Aşağıdaki ekran görüntüsündeki gibi bir çıktı görüyorsanız, servisler başarıyla oluşturulmuş demektir:
Servislerin durumunu doğrulamak için şu komutu çalıştırın: docker-compose ps komutu:
|
1 |
docker-compose ps |
Her şey başarılı olduysa komutun çıktısı aşağıda gösterildiği gibidir. app, db, ve webserver konteynerlerinin durumu 'up' olmalı ve certbot konteyneri Exit0 durumuna sahip olmalıdır:
Eğer Up dışında bir şey görüyorsanız durum sütununda app, db veya webserver, ya da Exit durumu 0 olmayan bir certbot konteyneri için geçerliyse, bir şeyler ters gitmiş demektir. Her bir konteynerin günlüklerini şu komutu kullanarak kontrol edebilirsiniz: docker-compose logs, ve service_name:
|
1 |
docker-compose logs service_name |
Örneğin, certbot konteynerinin günlüklerini aşağıdaki komutu girerek kontrol edebilirsiniz:
|
1 |
docker-compose logs certbot |
Sertifikaların webserver konteynerine bağlanıp bağlanmadığını kontrol etmek için docker-compose exec komutunu kullanın:
|
1 |
docker-compose exec webserver ls -la /etc/letsencrypt/live |
Eğer example.com dışında gerçek bir kayıtlı alan adı kullandıysanız ve sertifika istekleri başarılı olduysa, buna benzer bir çıktı görmelisiniz:
Sertifika isteğinin başarılı olduğunu onayladıktan sonra, docker-compose.yml dosyasını düzenleyebilir ve --staging bayrağını kaldırabilirsiniz. Dosyayı nano:
|
1 |
nano docker-compose.yml |
Komut seçeneğindeki Certbot servis tanımı bölümüne gidin ve --staging bayrağını --force-renewal bayrağı ile değiştirin. Bu, Certbot'a aynı alan adı için bir sertifika yenileme talebinde bulunduğunuzu bildirir. Certbot servis tanımınız artık şu şekilde görünmelidir:
|
1 2 3 4 5 6 7 8 9 10 |
#certbot service certbot: depends_on: - webserver image: certbot/certbot container_name: certbot volumes: - certbot-etc:/etc/letsencrypt - app:/var/www/html command: certonly --webroot --webroot-path=/var/www/html --email hackins@cloudsigma.com --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com |
Düzenlemeyi bitirdiğinizde dosyayı kaydedin.
Konteyneri yeniden oluşturmak için aşağıdaki komutu girin: certbot konteyneri. Eklenen --no-deps bayrağı, Compose'a web sunucusu zaten çalıştığı için onu yeniden başlatmayı atlamasını söyler:
|
1 |
docker-compose up --force-recreate --no-deps Certbot |
Komut, sertifika isteğinin başarılı olduğunu gösteren aşağıdaki ekran görüntüsünü çıktı olarak verir:
Bu adım için bu kadar. Bir sonraki adımda, SSL sertifikasını dahil etmek için Nginx yapılandırma dosyasını değiştireceksiniz.
Adım 5: Nginx Yapılandırmasında ve Servis Tanımında SSL'i Etkinleştirme
Nginx'in trafiği güvenli SSL üzerinden sunmasını sağlamak için, öncelikle Nginx yapılandırma dosyasına bir HTTP yönlendirmesini HTTPS protokolüne eklemek üzere değiştireceksiniz. Ardından, sertifika ve anahtar konumlarını belirtmeniz ve son olarak güvenlik parametrelerini ve başlıklarını eklemeniz gerekir.
Yapılandırma dosyasını değiştirmeden önce, önerilen Nginx güvenlik parametrelerini Certbot'un GitHub deposundan curl kullanarak aşağıdaki komutla almalısınız:
|
1 |
curl -sSLo nginx-conf/options-ssl-nginx.conf |
Komut çalışır ve çektiği parametreleri options-ssl-nginx.conf adında, nginx-conf dizini içindeki bir dosyaya kaydeder. Aşağıdaki komutlarla yeni bir tane oluşturabilmemiz için Nginx yapılandırma dosyasını kaldırın:
|
1 2 |
rm nginx-conf/nginx.conf nano nginx-conf/nginx.conf |
Şimdi boş olan nginx.conf dosyasına, HTTP protokolünden HTTPS, SSL kimlik bilgisi protokollerine yönlendirme ve güvenlik başlıkları içeren aşağıdaki kodu ekleyin. Daha önce yaptığınız gibi, example.com alan adını kendi kayıtlı alan adınızla değiştirin:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
server { listen 80; listen [::]:80; server_name example.com www.example.com; location ~ /.well-known/acme-challenge { allow all; root /var/www/html; } location / { rewrite ^ https://$host$request_uri? permanent; } } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com www.example.com; index index.php index.html index.htm; root /var/www/html; server_tokens off; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; include /etc/nginx/conf.d/options-ssl-nginx.conf; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-XSS-Protection "1; mode=block" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; add_header Content-Güvenlik-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always; # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; # sıkı taşıma güvenliğini (strict transport security) yalnızca sonuçlarını anlıyorsanız etkinleştirin location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass app:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~ /\.ht { deny all; } location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { log_not_found off; access_log off; allow all; } location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ { expires max; log_not_found off; } } |
Portunu kullanarak güvenli olmayan istekleri işleyen ilk sunucu bloğunda, 80 Certbot yenileme istekleri için webroot'u belirtiyoruz. Ayrıca, yönlendirme yönergesi ekliyoruz; bu yönerge HTTP isteklerini HTTPS.
İkinci sunucu bloğu, HTTPS portundan gelen güvenli trafiği işler. Gördüğünüz gibi, SSL ve 443HTTP2'yi de etkinleştiriyoruz. HTTP/2, sunucunuzun performansını artırır. Bu konuda daha fazla bilgiyi HTTP/2 hakkındaki resmi Nginx belgelerinden okuyabilirsiniz.Bu blokta ayrıca, Nginx'in SSL sertifikası ve anahtar konumlarının yanı sıra, .
curl tarafından nginx-conf/options-ssl-nginx.conf dizinine kaydedilen önerilen Certbot güvenlik parametrelerini içereceğini de belirttik.Ek güvenlik üstbilgileri, web sitenizin
Security Headers ve SSL Labs gibi güvenlik testi sitelerindeki puanlarını artırmaya yarar. Daha fazla bilgi edinmek için bu üstbilgilerdeki bağlantıları takip edebilirsiniz: X-Frame-OptionsReferrer Policy, X-Content-Type-Options, X-XSS-Protection, Content-Security-Policy, . HTTP Strict Transport Security (HSTS) üstbilgisini yorum satırı haline getirdik. Bunun ön yükleme (preload) özelliği hakkında bilgi edinebilir ve etkinleştirmek isteyip istemediğinize karar verebilirsiniz.Geri kalan
root, index, gibi yönergeler ve WordPress'e özel konum blokları, 1. Adım'de ele alındığı gibi kalır. Düzenlemeyi bitirdiğinizde dosyayı kaydedip kapatabilirsiniz.Artık
HTTPS portunu kullanan trafiğini etkinleştirdiğimize göre, bu portu web sunucusunun servis tanımında da etkinleştirmeliyiz. 443, dosyasını nano ile açmak için aşağıdaki komutu girin:
nano docker-compose.yml
|
1 |
dockercompose-yml.
Web sunucusu bölümündeki ports seçeneğinin altına, aşağıda vurgulandığı gibi port |
için bir eşleme ekleyin:443
webserver:
depends_on:
- app
image: nginx:1.15.12-alpine
container_name: webserver
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- app:/var/www/html
- ./nginx-conf:/etc/nginx/conf.d
- certbot-etc:/etc/letsencrypt
networks:
- app-network
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
depends_on: : app- image nginx: alpine:1.15.12-container_name webserver: restart unless: stopped-ports : - "80:80" volumes- "443:443" : app- var:/www/html/ nginx- ./conf-etc:/nginx/conf/d. certbot- etc-etc:/letsencrypt/networks : app- network-Tamamlanmış |
docker-compose.yml dosyası artık şu şekilde görünmelidir: file should now look like this:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
version: '3' services: #MySQL Servisi db: image: mysql:8.0 container_name: db restart: unless-stopped env_file: .env environment: - MYSQL_DATABASE=wordpress volumes: - dbdata:/var/lib/mysql command: '--default-authentication-plugin=mysql_native_password' networks: - app-network #WordPress uygulama kodu Servisi app: depends_on: - db image: wordpress:5.1.1-fpm-alpine container_name: app restart: unless-stopped env_file: .env environment: - WORDPRESS_DB_HOST=db:3306 - WORDPRESS_DB_USER=$MYSQL_USER - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD - WORDPRESS_DB_NAME=wordpress volumes: - app:/var/www/html networks: - app-network #Web sunucusu Nginx servisi webserver: depends_on: - app image: nginx:1.15.12-alpine container_name: webserver restart: unless-stopped ports: - "80:80" - "443:443" volumes: - app:/var/www/html - ./nginx-conf:/etc/nginx/conf.d - certbot-etc:/etc/letsencrypt networks: - app-network #certbot servisi certbot: depends_on: - webserver image: certbot/certbot container_name: certbot volumes: - certbot-etc:/etc/letsencrypt - app:/var/www/html command: certonly --webroot --webroot-path=/var/www/html --email hackins@cloudsigma.com --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com #Hacimler volumes: certbot-etc: app: dbdata: #Ağlar networks: app-network: driver: bridge |
Her şeyin doğru göründüğünü onayladıktan sonra dosyayı kaydedip kapatın. Ardından, webserver servisini yeniden oluşturmak için aşağıdaki komutu çalıştırın:
|
1 |
docker-compose up -d --force-recreate --no-deps webserver |
|
1 |
docker-compose ps |
Artık tüm konteynerleriniz çalıştığına göre, web arayüzünden WordPress yapılandırmasına devam edebilirsiniz.
Adım 6: WordPress Yapılandırmanızı Web Arayüzünden Tamamlayın
Kuruluma devam etmek için sunucunuzun alan adına gidin. WordPress kurulum ana sayfasını görmelisiniz. Devam etmeden önce dilinizi seçmeniz için sizi karşılar:
Dilinizi seçin ve tıklayın Continue bir sonraki sayfaya geçmek için:
Bu sayfada, web sitenizin başlığını doldurun, akılda kalıcı bir kullanıcı adı ve güçlü bir şifre seçin. Güvenlik nedenleriyle kullanıcı adı olarak Admin kullanmamanız önerilir. E-postanızı girin ve WordPress kurulumunu başlatmak için Install WordPress butonuna tıklayın.
Kurulum tamamlandığında, belirlediğiniz kullanıcı adı ve şifreyi gireceğiniz giriş ekranına yönlendirileceksiniz. Geçerli kimlik bilgilerini girdiğinizde, WordPress panelinizi görebilmelisiniz:
Artık WordPress'i başarıyla kurdunuz! Sırada, SSL sertifikalarının otomatik olarak yenilenmesini sağlamak için adımları uygulamanız gerekiyor.
Adım 7: Otomatik SSL Sertifikası Yenilemesini Yapılandırma
Let’s Encrypt TLS/SSL sertifikaları yalnızca 90 gün boyunca geçerlidir. Sürelerinin dolmamasını sağlamak için otomatik yenileme yapılandırması oluşturmak size kalmıştır. Bunu bir betik oluşturup cron job aracı ile zamanlayarak gerçekleştirebilirsiniz. Bu adımda, sertifikaları yenileyecek bir betiği nasıl oluşturacağınızı göstereceğiz. Ardından, son kullanma tarihi yaklaştığında sertifikaları periyodik olarak çalıştırmak ve yenilemek için bunu cron job aracı ile zamanlayacağız.
Inside the wordpress_docker proje dizininde, ssl_renewer.sh betiğini nano:
|
1 |
nano ssl_renewer.sh |
Otomatik yenilemeyi ve Nginx yapılandırmasının yeniden yüklenmesini yönetmek için betiğe aşağıdaki kodu ekleyin. Vurgulanan kullanıcı adını root olmayan kullanıcı adınızla değiştirmeyi unutmayın:
|
1 2 3 4 5 6 7 8 |
#!/bin/bash COMPOSE="/usr/local/bin/docker-compose –ansi never" DOCKER="/usr/bin/docker" cd /home/hackins/wordpress_docker/ $COMPOSE run certbot renew --dry-run && $COMPOSE kill -s SIGHUP webserver $DOCKER system prune -af |
Bu betikte, docker-compose ikili dosyasını COMPOSE adlı bir değişkene atıyoruz. Ayrıca betiğe –ansi never seçeneğini de dahil ediyoruz; bu seçenek betiğe docker-compose komutlarını ANSI kontrol karakterleri olmadan çalıştırmasını söyler. Ayrıca Docker ikili dosyasını DOCKER.
adlı bir değişkene atıyoruz. Betik daha sonra proje dizinimiz olan wordpress_docker dizinine geçer ve aşağıdaki komutları yürütür:
docker-compose run: certbot konteynerini başlatır ve certbot servis tanımında sağladığımız komutu geçersiz kılar. certonly alt komutunu çalıştırmak yerine, süresi dolmak üzere olan Let’s Encrypt SSL/TLS sertifikalarını yenileyecek olan renew alt komutunu çalıştırır.docker-compose kill: Nginx yapılandırmalarını yeniden yüklemek için SIGHUP sinyaliniwebserverkonteynerine gönderir. Docker'ın şu konudaki eğitimine göz atmak isteyebilirsiniz: Resmi Nginx Docker görüntüsünün nasıl kullanılacağı.docker system prune: bu komut kullanılmayan tüm konteynerleri ve görüntüleri kaldırır.
Düzenlemeyi bitirdiğinizde dosyayı kaydedip kapatın. Ardından, yürütülebilir hale getirmek için aşağıdaki komutu çalıştırın:
|
1 |
chmod +x ssl_renewer.sh |
Yürütülebilir hale getirdikten sonra, betiği belirteceğimiz aralıklarla periyodik olarak çalıştırmak için root crontab dosyanızı açın:
|
1 |
sudo crontab -e |
Eğer ilk kez kullanıyorsanız, crontab tercih ettiğiniz düzenleyiciyi seçmenizi ister:
Tercih ettiğiniz düzenleyiciyi seçin ve dosyayı açmak için Enter tuşuna basın. Dosyanın en altına aşağıdaki satırı ekleyin:
|
1 |
*/5 * * * * /home/hackins/wordpress_docker/ssl_renewer.sh >> /var/log/cron_docker.log 2>&1 |
Bu, yenileme betiğimizin çalışıp çalışmayacağını test etmemizi sağlamak için aralığı beş dakika olarak ayarlar. Ayrıca işten gelen çıktıyı tutacak bir günlük (log) dosyası da belirttik: cron_docker.log.
Beş dakika bekleyin ve şunu kontrol edin: cron.log betiğin yenileme isteğinde başarılı olup olmadığını görmek için:
|
1 |
tail -f /var/log/cron_docker.log |
İstekler başarılı olduysa aşağıdaki ekran görüntüsüne benzer bir şey görmelisiniz:
Artık test edip çalıştığını onayladığımıza göre, crontab dosyasını günlük bir yenileme belirtecek şekilde değiştirebilirsiniz. Örneğin, betiğin her gün saat 18:00'de çalışmasını belirtmek isteyebilirsiniz. Bunu yapmak için, crontab dosyasının son satırını şu şekilde görünecek şekilde değiştirin:
|
1 |
0 18 * * * /home/hackins/wordpress_docker/ssl_renewer.sh >> /var/log/cron_docker.log 2>&1 |
Ek olarak, –dry-run bayrağını ssl_renewer.sh betiğinden kaldırmanız gerekir, böylece çalıştığında gerçek yenileme gerçekleşir. Şöyle görünmelidir:
|
1 2 3 4 5 6 7 8 |
#!/bin/bash COMPOSE="/usr/local/bin/docker-compose --ansi never" DOCKER="/usr/bin/docker" cd /home/hackins/wordpress_docker/ $COMPOSE run certbot renew && $COMPOSE kill -s SIGHUP webserver $DOCKER system prune -af |
Ardından, dosyayı kaydedip kapatın. Bunu yaptıktan sonra, cron işi sertifikalarınızı 90 günlük süre dolmadan önce yenileyerek geçerli tutacaktır.
Sonuç
Eğitimde bu noktaya kadar geldiyseniz, kendinizi bir DevOps Mühendisi olmaya bir adım daha yakın sayabilirsiniz. Bir Nginx yapılandırma betiği oluşturabildiniz, bir docker-compose.yml dosyası oluşturdunuz ve Docker ile Docker Compose kullanarak bir WordPress uygulamasını çalıştırmak için gerekli birkaç hizmeti tanımladınız. Web sunucunuzun güvenli olmasını sağlamak için Let’s Encrypt'ten SSL/TLS sertifikaları aldınız. Son olarak, sertifikaların süresinin dolmamasını sağlamak için bir cron işi oluşturdunuz. İyi iş!
DevOps konusunda daha da derinleşmek istiyorsanız, konteynerlerle ilgili daha fazla kaynağa şuradan göz atabilirsiniz: blogumuz:
- Kubernetes'i Tanımak
- Ubuntu 20.04 Üzerinde Docker ile Node.js (Express.js) Uygulaması Nasıl Dağıtılır
- Ubuntu 18.04 ile Kubernetes Kümesi Üzerinde PHP Uygulaması Dağıtma.
- Docker Compose ile Laravel, Nginx ve MySQL Dağıtımı
Keyifli Bilişimler!










Yorumlar
Henüz yorum yapılmamış. İlk siz olun.