Php-fpm ve Nginx Docker konteynerleri nasıl doğru bir şekilde bağlanır?


105

2 ayrı kapsayıcıyı birbirine bağlamaya çalışıyorum:

Sorun, php betiklerinin çalışmamasıdır. Belki de php-fpm yapılandırması yanlıştır. İşte benim kaynak kod vardır depo . İşte dosya docker-compose.yml:

nginx:
    build: .
    ports:
        - "80:80"
        - "443:443"
    volumes:
        - ./:/var/www/test/
    links:
        - fpm
fpm:
    image: php:fpm
    ports:
        - "9000:9000"

ve Dockerfilenginx one'ı temel alan özel bir görüntü oluşturmak için kullandığım şey:

FROM nginx

# Change Nginx config here...
RUN rm /etc/nginx/conf.d/default.conf
ADD ./default.conf /etc/nginx/conf.d/

Son olarak, işte özel Nginx sanal ana bilgisayar yapılandırmam:

server {
    listen  80;

    server_name localhost;
    root /var/www/test;

    error_log /var/log/nginx/localhost.error.log;
    access_log /var/log/nginx/localhost.access.log;

    location / {
        # try to serve file directly, fallback to app.php
        try_files $uri /index.php$is_args$args;
    }

    location ~ ^/.+\.php(/|$) {
        fastcgi_pass 192.168.59.103:9000;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTPS off;
    }
}

Bu kapsayıcıları php betiklerini yürütmek için doğru şekilde yapılandırmama yardım eden var mı?

Not: Container'ları docker-composer aracılığıyla şu şekilde çalıştırıyorum:

docker-compose up

proje kök dizininden.


1
Şimdiye kadar bunları nasıl yapılandırmaya çalıştınız veya hangi kodu kullandınız? Lütfen tahmin etmekte saçma olduğumu tahmin ettirme.
Matthew Brown aka Lord Matt

1
@MatthewBrown Huh, kodumu GitHub'daki herkese açık depoya koydum ve bunun yeterli olacağını düşünüyorum, ama haklısın, benim sorumda da kodu göstermen daha iyi.
Victor Bocharsky

görüntüler döndüğünde, docker execçalışan konteynere ve ping fpm'ye girebilir misiniz ?
Vincent De Smet

1
@MatthewBrown evet, ben kazandım, teşekkürler
Victor Bocharsky

1
PS Ayrıca linke bir iş çözümü elde Nginxve PHP-FPM birlikte Vagrant ve yanıtlayıcı 'ile. İsterseniz repom github.com/bocharsky-bw/vagrant-ansible-docker'ı kontrol edin .
Victor Bocharsky

Yanıtlar:


33

Nginx yapılandırmasında kapsayıcıların ip kodlarını kodlamayın, docker bağlantısı bağlantılı makinenin ana bilgisayar adını kabın ana bilgisayar dosyasına ekler ve ana makine adına göre ping yapabilmeniz gerekir.

DÜZENLEME: Docker 1.9 Ağ iletişimi artık kapsayıcıları bağlamanızı gerektirmiyor, aynı ağa birden fazla kapsayıcı bağlandığında ana bilgisayar dosyası güncellenecek ve böylece birbirlerine ana bilgisayar adına göre erişebilecekler.

Bir docker container'ı bir görüntüden her döndüğünde (hatta var olan bir kapsayıcıyı durdurur / başlatırsa), kapsayıcılar docker ana bilgisayarı tarafından atanan yeni ip'leri alır. Bu ip'ler, gerçek makinelerinizle aynı alt ağda değildir.

docker bağlama belgelerine bakın (bu, compose'un arka planda kullandığı şeydir)

ancak docker-composebağlantılarla ilgili belgelerde daha net bir şekilde açıklanmıştır ve

bağlantılar

links:
 - db
 - db:database
 - redis

Bu hizmet için kapsayıcıların içinde / etc / hosts içinde takma adla bir giriş oluşturulur, örneğin:

172.17.2.186  db
172.17.2.186  database
172.17.2.187  redis

maruz bırakmak

Bağlantı noktalarını ana makineye yayınlamadan gösterin - bunlara yalnızca bağlantılı hizmetler tarafından erişilebilir . Yalnızca dahili bağlantı noktası belirtilebilir.

ve projenizi, ortam değişkenleri aracılığıyla bağlantı noktalarını + diğer kimlik bilgilerini alacak şekilde ayarlarsanız , bağlantılar otomatik olarak bir dizi sistem değişkenini ayarlar :

Bir hizmette hangi ortam değişkenlerinin mevcut olduğunu görmek için çalıştırın docker-compose run SERVICE env.

name_PORT

Tam URL, örneğin DB_PORT = tcp: //172.17.0.5: 5432

name_PORT_num_protocol

Tam URL, ör. DB_PORT_5432_TCP=tcp://172.17.0.5:5432

name_PORT_num_protocol_ADDR

Konteynerin IP adresi, ör. DB_PORT_5432_TCP_ADDR=172.17.0.5

name_PORT_num_protocol_PORT

Açık bağlantı noktası numarası, ör. DB_PORT_5432_TCP_PORT=5432

name_PORT_num_protocol_PROTO

Protokol (tcp veya udp), ör. DB_PORT_5432_TCP_PROTO=tcp

name_NAME

Tam nitelikli kapsayıcı adı, ör. DB_1_NAME=/myapp_web_1/myapp_db_1


2
ayrıca ana bilgisayarda 9000 numaralı bağlantı noktasını yayınlamanıza gerek yoktur, bağlantı noktasını doğrudan ana bilgisayarınızdan gidermek istemediğiniz sürece bağlantı noktaları bağlantılı docker konteynerleri arasında açıktır.
Vincent De Smet

Evet, haklısın, teşekkürler. Benim durumumda doğrudan ip yerine fastcgi_pass fpm: 9000 kullanmalıyım. Docker'ın onu otomatik olarak barındırmaya eklediğini bilmiyorum, benim hatam.
Victor Bocharsky

Bağlantı noktası ne olacak , bağlantı noktaları yerine açığa çıkarmak daha mı iyi ? Veya bu bağlantı noktalarından hiçbirini kullanıp yönergeleri açığa çıkaramadım çünkü bağlantılı kapsayıcılar bu bağlantı noktasına erişime sahip olacak?
Victor Bocharsky

Özür geç cevap için - üzgün şu anda kontrol edemez, açığa kullanması gerekebilir düşünüyorum
Vincent De Smet

3
--linksreferans verdiğiniz docker belgesine göre artık kullanılmıyor. Onlar hala vardır şu anda desteklenen ancak bunları obsoleted edilecek için bariz bir plan.
2018

86

Bunun biraz eski bir gönderi olduğunu biliyorum, ama aynı sorunu yaşadım ve kodunuzun neden çalışmadığını anlayamadım. Bir sürü testten sonra nedenini buldum.

Görünüşe göre fpm nginx'ten tam yolu alıyor ve dosyaları fpm konteynerinde bulmaya çalışıyor, bu nedenle server.rootnginx konteynerinde olmasa bile nginx yapılandırmasındaki ile tam olarak aynı olması gerekiyor .

Göstermek:

docker-compose.yml

nginx:
    build: .
    ports:
        - "80:80"
    links:
        - fpm
fpm:
    image: php:fpm
    ports:
        - ":9000"

    # seems like fpm receives the full path from nginx
    # and tries to find the files in this dock, so it must
    # be the same as nginx.root
    volumes:
        - ./:/complex/path/to/files/

/etc/nginx/conf.d/default.conf

server {
    listen  80;

    # this path MUST be exactly as docker-compose.fpm.volumes,
    # even if it doesn't exist in this dock.
    root /complex/path/to/files;

    location / {
        try_files $uri /index.php$is_args$args;
    }

    location ~ ^/.+\.php(/|$) {
        fastcgi_pass fpm:9000;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

Dockerfile

FROM nginx:latest
COPY ./default.conf /etc/nginx/conf.d/

4
AFERİN!!! İşte mesele bu! Nginx kökünü /var/www/htmlbaşarısızlık dışında alternatif bir yola ayarladım .
Alfred Huang

3
Ayrıca, :9000ana makinenizin maruz kaldığı değil, konteynerde kullanılan bağlantı noktası olan bir not . Bunu anlamam 2 saatimi aldı. Umarım zorunda kalmazsın.
çığlık

1
services.fpm.ports is invalid: Invalid port ":9000", should be [[remote_ip:]remote_port[-remote_port]:]port[/protocol]
030

4
Aslında portsburaya bir bölüm eklemenize gerek yok. Sadece gerekebilir expose(o muhtemelen) görüntüde halen açık değilse o. Eğer arası konteyner iletişimi yapıyorsanız, sen olmamalı PHP-FPM portunu açığa olun.
Seer

Bir çözüm arıyordu AH01071: Got error 'Primary script unknown\n've php-fpm kapsayıcısının web düğümleriyle aynı dizini paylaşması gerektiğine çözüm oldu!
cptPH

23

Daha önce de belirtildiği gibi sorun, dosyaların fpm kapsayıcısı tarafından görünmemesiydi. Bununla birlikte, kapsayıcılar arasında veri paylaşmak için önerilen model, salt veri kapsayıcıları kullanmaktır ( bu makalede açıklandığı gibi ).

Uzun lafın kısası: Yalnızca verilerinizi tutan bir kap oluşturun, bir cilt ile paylaşın ve bu hacmi uygulamalarınızda ile bağlayın volumes_from.

Oluşturma (makinemde 1.6.2) kullanıldığında docker-compose.ymldosya şunu okur:

version: "2"
services:
  nginx:
    build:
      context: .
      dockerfile: nginx/Dockerfile
    ports:
      - "80:80"
    links:
      - fpm
    volumes_from:
      - data
  fpm:
    image: php:fpm
    volumes_from:
      - data
  data:
    build:
      context: .
      dockerfile: data/Dockerfile
    volumes:
      - /var/www/html

Ve hizmetlerine databağlı bir cilt yayınladığını unutmayın . Sonra için veri servisi, bu kaynak kodu içerir:nginxfpmDockerfile

FROM busybox

# content
ADD path/to/source /var/www/html

Ve Dockerfilesadece varsayılan yapılandırmanın yerini alan nginx için:

FROM nginx

# config
ADD config/default.conf /etc/nginx/conf.d

Tamamlama adına, örneğin çalışması için gereken yapılandırma dosyası şu şekildedir:

server {
    listen 0.0.0.0:80;

    root /var/www/html;

    location / {
        index index.php index.html;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass fpm:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
    }
}

bu da nginx'e paylaşılan birimi belge kökü olarak kullanmasını söyler ve nginx'in fpm kapsayıcısı ile iletişim kurabilmesi için doğru yapılandırmayı ayarlar (yani HOST:PORT, fpm:9000compose tarafından tanımlanan ana bilgisayar adları sayesinde sağ , ve SCRIPT_FILENAME).


Görünüşe göre Veriler ana bilgisayardan kapsayıcılara güncelleme almıyor ve docker ps yaptığımda veri kabının durduğunu görüyorum, bu bir sorun mu?
Aftab Naveed

2
Beklenen davranış budur. Yalnızca veri içeren bir konteyner herhangi bir komut çalıştırmaz ve yalnızca durdurulmuş olarak listelenir. Ayrıca, Dockerfileveri kabının kaynağı derleme zamanında kaynaklarınızı kapsayıcıya kopyalıyor. Bu nedenle, ana bilgisayardaki dosyaları değiştirirseniz güncellenmezler. Kaynakları ana bilgisayar ve kapsayıcı arasında paylaşmak istiyorsanız, dizini bağlamanız gerekir. Değişim datayüke oluşturma dosyasında hizmet image: busyboxve içinde volumesbölüm girmek ./sources:/var/www/html, ./sourceskonakta Kaynaklarınızda yoludur.
iKanor

17

Yeni Cevap

Docker Compose güncellendi. Artık sürüm 2 dosya biçimine sahipler .

Sürüm 2 dosyaları, Compose 1.6.0+ tarafından desteklenir ve 1.10.0+ sürümünün Docker Engine'i gerektirir.

Artık Docker'ın ağ oluşturma özelliğini destekliyorlar ve çalıştırıldığında myapp_default adlı varsayılan bir ağ kuruyorlar.

Gönderen onların belgelerine Dosyanızın aşağıdaki gibi görünecektir:

version: '2'

services:
  web:
    build: .
    ports:
      - "8000:8000"
  fpm:
    image: phpfpm
  nginx
    image: nginx

Bu kapsayıcılar varsayılan myapp_default ağına otomatik olarak eklendiğinden , birbirleriyle konuşabilirler. Daha sonra Nginx yapılandırmasına sahip olursunuz:

fastcgi_pass fpm:9000;

Ayrıca yorumlarda @treeface tarafından belirtildiği gibi, PHP-FPM'nin 9000 numaralı bağlantı noktasını dinlediğinden emin olmayı unutmayın, bu, /etc/php5/fpm/pool.d/www.confihtiyacınız olan yerde düzenleme yaparak yapılabilir listen = 9000.

Eski Cevap

Aşağıdakileri Docker / Docker compose'un eski sürümünü kullananlar için burada tuttum ve bilgi almak istiyorum.

Bu soruya bir cevap bulmaya çalışırken Google'da bu soruya sürekli tökezledim, ancak docker-compose üzerindeki Q / A vurgusu nedeniyle aradığım şey tam olarak değildi (ki bu yazım sırasında yalnızca deneysel desteğe sahiptir) docker ağ özellikleri). İşte öğrendiklerimle ilgili görüşüm.

Docker, ağ özelliği lehine yakın zamanda bağlantı özelliğini kullanımdan kaldırdı

Bu nedenle Docker Networks özelliğini kullanarak bu adımları izleyerek kapsayıcıları bağlayabilirsiniz. Seçeneklerle ilgili tam açıklamalar için daha önce bağlantısı verilen belgelerde okuyun.

Önce ağınızı oluşturun

docker network create --driver bridge mynetwork

Ardından, 9000 numaralı bağlantı noktasını açmanızı ve yeni ağınıza ( mynetwork) atamanızı sağlayarak PHP-FPM kabınızı çalıştırın .

docker run -d -p 9000 --net mynetwork --name php-fpm php:fpm

Burada önemli --name php-fpmolan isim olan komutun sonundaki kısımdır, buna daha sonra ihtiyacımız olacak.

Daha sonra Nginx konteynırınızı tekrar çalıştırın oluşturduğunuz ağa atayın.

docker run --net mynetwork --name nginx -d -p 80:80 nginx:latest

PHP ve Nginx kapsayıcıları için --volumes-fromgerektiğinde komutlar vb. Ekleyebilirsiniz .

Şimdi Nginx yapılandırması geliyor. Buna benzer bir şeye benzemesi gereken:

server {
    listen 80;
    server_name localhost;

    root /path/to/my/webroot;

    index index.html index.htm index.php;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php-fpm:9000; 
        fastcgi_index index.php;
        include fastcgi_params;
    }
}

fastcgi_pass php-fpm:9000;Konum bloğundaki işaretine dikkat edin . Bu php-fpm, limanda konteynır diyor 9000. Bir Docker köprü ağına kapsayıcılar eklediğinizde, hepsi otomatik olarak kapsayıcı adlarını IP adreslerine yerleştiren bir ana bilgisayar dosyası güncellemesi alır. Dolayısıyla, Nginx, php-fpmdaha önce adlandırdığınız ve mynetworkDocker ağınıza atadığınız PHP-FPM kapsayıcısıyla iletişim kuracağını bildiğini gördüğünde .

Bu Nginx yapılandırmasını Docker konteynerinizin derleme işlemi sırasında veya daha sonra size kalmış olarak ekleyebilirsiniz.


Ayrıca emin olun unutmayın php-fpmBu olacağını port 9000 tarihinde dinleme listen = 9000içinde /etc/php5/fpm/pool.d/www.conf.
ağaç yüzlü

Teşekkürler @treeface iyi nokta. Yorumunuzla güncelledim.
DavidT

8

Önceki cevapların çözüldüğü gibi, ancak çok açık bir şekilde ifade edilmelidir: php kodunun php-fpm kapsayıcısında yaşaması gerekirken statik dosyaların nginx kabında yaşaması gerekir. Basit olması açısından, aşağıda da yaptığım gibi, çoğu insan tüm kodu her ikisine de eklemiştir. Gelecekte, hangi konteynerlerin hangi parçalara erişebileceğini en aza indirmek için muhtemelen kodun bu farklı bölümlerini kendi projelerimde ayıracağım.

Aşağıdaki örnek dosyalarım bu son vahiy ile güncellendi (teşekkür ederim @ alkaline)

Bu, docker 2.0 ileriye dönük minimum kurulum gibi görünüyor (çünkü docker 2.0'da işler çok daha kolay hale geldi)

docker-compose.yml:

version: '2'
services:
  php:
    container_name: test-php
    image: php:fpm
    volumes:
      - ./code:/var/www/html/site
  nginx:
    container_name: test-nginx
    image: nginx:latest
    volumes:
      - ./code:/var/www/html/site
      - ./site.conf:/etc/nginx/conf.d/site.conf:ro
    ports:
      - 80:80

( Yukarıdaki docker-compose.yml GÜNCELLENMİŞTİR : css, javascript, statik dosyalar vb. İçeren siteler için, nginx konteynerinin erişebileceği bu dosyalara ihtiyacınız olacak. Yine de fpm konteynerine erişilebilen tüm php koduna sahipken. benim temel kodum css, js ve php'nin dağınık bir karışımıdır, bu örnek sadece tüm kodu her iki kaba ekler)

Aynı klasörde:

site.conf:

server
{
    listen   80;
    server_name site.local.[YOUR URL].com;

    root /var/www/html/site;
    index index.php;

    location /
    {
        try_files $uri =404;
    }

    location ~ \.php$ {
        fastcgi_pass   test-php:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

Klasör kodunda:

./code/index.php:

<?php
phpinfo();

ve hosts dosyanızı güncellemeyi unutmayın:

127.0.0.1 site.local.[YOUR URL].com

ve docker-compose up'ınızı çalıştırın

$docker-compose up -d

ve favori tarayıcınızın URL'sini deneyin

site.local.[YOUR URL].com/index.php

1
Nginx yapılandırma dosyanız, web sitenizin yalnızca php dosyalarına sahip olduğunu varsayar. Statik dosyalar (jpg, txt, svg, ...) için bir nginx konum kuralı oluşturmak ve php yorumlayıcısından kaçınmak en iyi uygulamadır. Bu durumda hem nginx hem de php kapsayıcılarının web sitesi dosyalarına erişmesi gerekir. @iKanor'un yukarıdaki cevabı bununla ilgileniyor.
Bernard

Teşekkürler @Alkaline, statik dosyalar orijinal cevabımla ilgili sorun. Aslında, nginx'in düzgün çalışması için en azından css ve js dosyalarının o makineye yerel olması gerekir.
Phillip

7

Sanırım fpm konteynırına hacmi de vermemiz gerekiyor, değil mi? Yani =>

fpm:
    image: php:fpm
    volumes:
        - ./:/var/www/test/

Bunu yapmazsam, fpm istenen dosyayı bulamadığından bir isteği başlatırken bu istisnayla karşılaşırım:

[hata] 6 # 6: * 4 stderr'de gönderilen FastCGI: Yukarı akıştan yanıt başlığı okunurken "Birincil komut dosyası bilinmiyor", istemci: 172.17.42.1, sunucu: localhost, istek: "GET / HTTP / 1.1", yukarı akış: "fastcgi : //172.17.0.81: 9000 ", ana bilgisayar:" localhost "


1
Evet haklısın! Dosyaları fpm ve nginx ile paylaşmalıyız
Victor Bocharsky

GitHub ile Nginxve PHP-FPMüzerinde çalışma
örneğim var

1

Başkası almak için

Nginx 403 hatası: [klasör] dizin dizini yasak

index.phpwhile kullanırken index.htmlmükemmel çalışır ve index.phpsitelerinin sunucu bloğundaki dizine dahil edildiğindesites-enabled

server {
    listen 80;

    # this path MUST be exactly as docker-compose php volumes
    root /usr/share/nginx/html;

    index index.php

    ...
}

Adresindeki nginx.conf dosyanızın /etc/nginx/nginx.confaslında site yapılandırmanızı httpblokta yüklediğinden emin olun ...

http {

    ...

    include /etc/nginx/conf.d/*.conf;

    # Load our websites config 
    include /etc/nginx/sites-enabled/*;
}

bunun için teşekkürler, eski ama yine de bilgilendirici, / usr / share / nginx / html kullanmak zorunda kaldım 👍, teşekkürler
Simon Davies
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.