Docker-scaling nginx dan php-fpm secara terpisah

Saya telah bermain-main dengan docker dan docker-compose dan memiliki pertanyaan.

Saat ini docker-compose saya.yml terlihat seperti ini:

app:    image: myname/php-app    volumes:        - /var/www    environment:        <SYMFONY_ENVIRONMENT>: devweb:    image: myname/nginx    ports:        - 80    links:        - app    volumes_from:        - app

Aplikasi berisi php-fpm pada port 9000 dan kode aplikasi saya.Web adalah nginx dengan beberapa bit konfigurasi.

Ini berfungsi seperti yang saya harapkan namun untuk menghubungkan nginx ke php-fpm saya memiliki baris ini:

fastcgi_pass    app:9000;

Bagaimana Saya bisa menskalakan ini secara efektif? Jika saya ingin, misalnya, menjalankan satu wadah nginx tetapi tiga wadah aplikasi berjalan maka saya pasti akan memiliki tiga instance php-fpm yang semuanya mencoba mendengarkan pada port 9000.

Bagaimana Saya bisa memiliki setiap instance php-fpm pada port yang berbeda tetapi masih tahu di mana mereka berada di konfigurasi nginx saya pada waktu tertentu?

Apakah saya mengambil pendekatan yang salah?

Terima kasih!

Salah satu solusinya adalah menambahkan instance php-fpm tambahan ke file Docker-compose Anda dan kemudian menggunakan upstream nginx seperti yang disebutkan dalam jawaban lain untuk memuat keseimbangan di antara mereka. Ini dilakukan dalam contoh ini repo docker-compose: https://github.com/iamyojimbo/docker-nginx-php-fpm/blob/master/nginx/nginx.conf#L137

upstream php {    #If there's no directive here, then use round_robin.    #least_conn;    server dockernginxphpfpm_php1_1:9000;    server dockernginxphpfpm_php2_1:9000;    server dockernginxphpfpm_php3_1:9000;}

Ini tidak terlalu ideal karena perlu mengubah konfigurasi nginx dan docker-compose.yml ketika Anda ingin skala atas atau bawah.

Perhatikan bahwa port 9000 internal ke wadah dan bukan host Anda yang sebenarnya, jadi tidak masalah Anda memiliki beberapa wadah php-fpm pada port 9000.

Docker mengakuisisi Tutum musim gugur ini. Mereka memiliki solusi yang menggabungkan wadah HAProxy dengan api mereka untuk secara otomatis menyesuaikan konfigurasi load-balancer ke wadah yang sedang berjalan itu adalah load-balancing. Itu adalah solusi yang bagus. Kemudian nginx menunjuk ke nama host yang ditetapkan ke load-balancer. Mungkin Docker akan lebih mengintegrasikan jenis solusi ini ke dalam alat mereka setelah akuisisi Tutum. Ada artikel tentang itu di sini: https://web.archive.org/web/20160628133445/https://support.tutum.co/support/solutions/articles/5000050235-load-balancing-a-web-service

Tutum saat ini merupakan layanan berbayar. Rancher adalah proyek open-source yang menyediakan fitur load-balancing serupa. Mereka juga memiliki " rancher-compose.yml " yang dapat menentukan penyeimbangan beban dan penskalaan pengaturan layanan di docker-compose.yml. http://rancher.com/the-magical-moment-when-container-load-balancing-meets-service-discovery/ http://docs.rancher.com/rancher/concepts/#load-balancer

Pembaruan 2017/03/06: saya telah menggunakan proyek yang disebut interlock itu berfungsi dengan Docker untuk memperbarui konfigurasi nginx secara otomatis dan memulai ulang. Lihat juga @iwaseatenbyagrue's jawaban yang memiliki pendekatan tambahan.

Anda dapat menggunakan upstream untuk menentukan beberapa backend, seperti yang dijelaskan di sini:

https://stackoverflow.com/questions/5467921/how-to-use-fastcgi-next-upstream-in-nginx

Anda juga ingin konfigurasi diperbarui setiap kali backend baru mati / mulai berfungsi dengan sesuatu seperti:

https://github.com/kelseyhightower/confd

Meskipun posting ini dari tahun 2015 dan saya merasa saya necroing( komunitas maaf), saya merasa sangat berharga untuk menambahkan pada saat ini:

Saat ini (dan karena Kubernetes disebutkan) ketika Anda bekerja dengan Docker, Anda dapat menggunakan Kubernetes atau Docker Swarm dengan sangat mudah untuk menyelesaikan masalah ini. Kedua orkestra akan mengambil node docker Anda (satu node = satu server dengan Docker di atasnya) dan Anda dapat menerapkan layanan kepada mereka dan mereka akan mengelola tantangan port untuk Anda menggunakan jaringan overlay.

Karena saya lebih berpengalaman dalam Docker Swarm, ini adalah bagaimana Anda akan melakukannya untuk mendekati masalah ini (dengan asumsi Anda memiliki satu node Docker):

Inisialisasi swarm:

docker swarm init

cd ke akar proyek Anda

cd some/project/root

buat tumpukan swarm dari docker-compose Anda.yml (alih-alih menggunakan docker-compose):

docker stack deploy -c docker-compose.yml myApp

Ini akan membuat tumpukan layanan kawanan buruh pelabuhan yang disebut" myApp " dan akan mengelola port untuk anda. Ini berarti: Anda hanya perlu menambahkan satu definisi" port: 9000:9000 " ke layanan php-fpm Anda di file docker-compose Anda dan kemudian Anda dapat meningkatkan layanan php-fpm, katakanlah ke 3 instance, sementara swarm akan secara otomatis memuat-menyeimbangkan permintaan antara tiga instance tanpa perlu pekerjaan lebih lanjut.

Dalam kasus di mana wadah Nginx dan php-fpm Anda berada di host yang sama, Anda dapat mengkonfigurasi kecil dnsmasq contoh pada host yang akan digunakan oleh Nginx kontainer, dan menjalankan script untuk secara otomatis memperbarui catatan DNS Ketika alamat IP kontainer telah berubah.

Saya sudah menulis Naskah Kecil untuk melakukan ini (ditempelkan di bawah), yang secara otomatis memperbarui catatan DNS yang memiliki nama yang sama dengan nama wadah dan mengarahkannya ke alamat IP wadah:

#!/bin/bash# 10 seconds interval time by defaultINTERVAL=${INTERVAL:-10}# dnsmasq config directoryDNSMASQ_CONFIG=${DNSMASQ_CONFIG:-.}# commands used in this scriptDOCKER=${DOCKER:-docker}SLEEP=${SLEEP:-sleep}TAIL=${TAIL:-tail}declare -A service_mapwhile truedo    changed=false    while read line    do        name=${line##* }        ip=$(${DOCKER} inspect --format '{{.NetworkSettings.IPAddress}}' $name)        if [ -z ${service_map[$name]} ] || [ ${service_map[$name]} != $ip ] # IP addr changed        then            service_map[$name]=$ip            # write to file            echo $name has a new IP Address $ip >&2            echo "host-record=$name,$ip"  > "${DNSMASQ_CONFIG}/docker-$name"            changed=true        fi    done < <(${DOCKER} ps | ${TAIL} -n +2)    # a change of IP address occured, restart dnsmasq    if [ $changed = true ]    then        systemctl restart dnsmasq    fi    ${SLEEP} $INTERVALdone

Kemudian, mulai wadah nginx Anda dengan --dns host-ip-address, dimana host-ip-address adalah alamat IP dari host pada antarmuka docker0.

Anda Konfigurasi Nginx harus menyelesaikan nama secara dinamis:

server {  resolver host-ip-address;  listen 80;  server_name @server_name@;  root /var/www/@root@;  index index.html index.htm index.php;  location ~ ^(.+?\.php)(/.*)?$ {    try_files $uri =404;    include fastcgi_params;    fastcgi_param SCRIPT_FILENAME $document_root$1;    set $backend "@fastcgi_server@";    fastcgi_pass $backend;  }}

Referensi:

Jika nginx dan php-fpm Anda berada di host yang berbeda, Anda dapat mencoba jawaban @smaj.

Pendekatan lain mungkin untuk melihat ke dalam sesuatu seperti konsul-template.

Dan tentu saja, di beberapa titik, Kubernetes mungkin perlu disebutkan.

Namun, Anda dapat mempertimbangkan pendekatan 'bit string dan lakban' yang sedikit lebih banyak dengan melihat apa yang dapat dilakukan oleh acara Docker untuk anda (jalankan docker events --since 0 untuk sampel cepat).

Akan cukup sepele untuk memiliki skrip yang melihat peristiwa ini (mengingat ada beberapa paket klien yang tersedia, termasuk untuk python, go, dll), mengubah file konfigurasi, dan memuat ulang nginx (yaitu menggunakan pendekatan konsul-template, tetapi tanpa perlu konsul).

Untuk kembali ke premis asli Anda, meskipun: selama wadah php-fpm Anda dimulai dengan jaringan mereka sendiri (yaitu tidak berbagi wadah lain, seperti yang nginx), maka anda dapat memiliki banyak wadah yang mendengarkan pada port 9000 seperti yang anda inginkan - karena mereka memiliki IP per-wadah, tidak ada masalah dengan port 'bentrok'.

Bagaimana Anda menskalakan ini kemungkinan akan bergantung pada tujuan akhir/kasus penggunaan Anda, tetapi satu hal yang mungkin Anda pertimbangkan adalah menempatkan HAproxy antara nginx dan node php-fpm Anda.Satu hal yang dapat Anda lakukan hanyalah menominasikan rentang (dan mungkin membuat docker network) untuk server php-fpm anda (yaitu 172.18.0.0/24), dan memiliki HAproxy yang dikonfigurasi untuk mencoba dan menggunakan IP apa pun dalam rentang itu sebagai backend. Karena HAproxy memiliki pemeriksaan kesehatan, HAproxy dapat dengan cepat mengidentifikasi alamat mana yang aktif, dan memanfaatkannya.

Lihat https://stackoverflow.com/questions/1358198/nginx-removing-upstream-servers-from-pool untuk diskusi tentang bagaimana nginx vs haproxy berurusan dengan upstream.

Kecuali Anda menggunakan jaringan docker khusus untuk ini, Anda mungkin perlu melakukan beberapa manajemen IP manual untuk node php-fpm Anda.