php-fpmとNginx Dockerコンテナを正しくリンクする方法は?


102

2つの個別のコンテナーをリンクしようとしています。

問題は、phpスクリプトが機能しないことです。おそらくphp-fpm設定が正しくありません。これが私のリポジトリにあるソースコードです。ここにファイルがありますdocker-compose.yml

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

そしてDockerfile私はnginxのものに基づいてカスタムイメージを構築するために使用しました:

FROM nginx

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

最後に、これが私のカスタムNginx仮想ホスト構成です。

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;
    }
}

誰かがこれらのコンテナを正しく構成してphpスクリプトを実行するのを手伝ってくれる?

PS 私は次のようにdocker-composerを介してコンテナーを実行します:

docker-compose up

プロジェクトのルートディレクトリから。


1
これまでにそれらをどのように構成しようとしたか、またはどのコードを使用しましたか。私が推測でゴミだと推測させないでください。
Matthew Brown、別名Lord Matt

1
@MatthewBrownええと、私は自分のコードをGitHubのパブリックレポジトリに配置し、これで十分だと思います。
Victor Bocharsky、2015

画像がスピンアップしたらdocker exec、実行中のコンテナにアクセスしてfpmにping できますか?
Vincent De Smet 2015

1
はい@MatthewBrown、私は感謝、それを獲得した
ビクターBocharsky

1
PS私はまた 、VagrantとAnsible をリンクNginxしてPHP-FPM一緒にする作業ソリューションを実現しました。必要に応じて、私のリポジトリgithub.com/bocharsky-bw/vagrant-ansible-dockerを確認してください。
Victor Bocharsky 2015年

回答:


32

nginx設定でコンテナのIPをハードコードしないでください。Dockerリンクは、リンクされたマシンのホスト名をコンテナのホストファイルに追加し、ホスト名でpingできるはずです。

編集:Docker 1.9ネットワークでは、コンテナーをリンクする必要がなくなりました。複数のコンテナーが同じネットワークに接続されている場合、それらのホストファイルは更新され、ホスト名で相互に到達できるようになります。

Dockerコンテナーがイメージからスピンアップするたびに(既存のコンテナーを停止/開始する場合でも)、コンテナーは、Dockerホストによって割り当てられた新しいIPを取得します。これらのIPは、実際のマシンと同じサブネットにはありません。

Dockerリンクドキュメントを参照してください(これは、composeがバックグラウンドで使用するものです)

docker-composeリンクと公開に関するドキュメントでより明確に説明されています

リンク

links:
 - db
 - db:database
 - redis

エイリアス名のエントリは、このサービスのコンテナ内の/ etc / hostsに作成されます。例:

172.17.2.186  db
172.17.2.186  database
172.17.2.187  redis

露出する

ホストマシンに公開せずにポートを公​​開しますリンクされたサービスにのみアクセスできます。内部ポートのみ指定できます。

また、環境変数を通じてポートとその他の認証情報を取得するようにプロジェクトを設定した場合、リンクは一連のシステム変数を自動的に設定します

サービスで使用できる環境変数を確認するには、を実行しdocker-compose run SERVICE envます。

name_PORT

完全なURL、例:DB_PORT = tcp://172.17.0.5:5432

name_PORT_num_protocol

完全なURL、例えば DB_PORT_5432_TCP=tcp://172.17.0.5:5432

name_PORT_num_protocol_ADDR

コンテナのIPアドレス。 DB_PORT_5432_TCP_ADDR=172.17.0.5

name_PORT_num_protocol_PORT

公開されたポート番号、例えば DB_PORT_5432_TCP_PORT=5432

name_PORT_num_protocol_PROTO

プロトコル(tcpまたはudp)、例えば DB_PORT_5432_TCP_PROTO=tcp

name_NAME

完全修飾コンテナ名、例えば DB_1_NAME=/myapp_web_1/myapp_db_1


2
また、ホストでポート9000を公開する必要はありません。ポートをホストから直接トラブルシューティングする場合を除き、リンクされたDockerコンテナー間でポートが開いています。
Vincent De Smet 2015

はい、ありがとうございます。私の場合、直接IPの代わりにfastcgi_pass fpm:9000を使用する必要があります。Dockerが自動的にホストに追加することを知りません。
Victor Bocharsky、2015

ポートについてはどうですか?ポートの代わりに公開を使用する方が良いですか?または、リンクされたコンテナーがこのポートにアクセスできるため、このポートを使用してディレクティブを公開できませんでしたか?
Victor Bocharsky、2015

返信が遅くなって申し訳ありません-公開を使用する必要があるかもしれません。申し訳ありませんが、現在確認できません
Vincent De Smet

2
--links参照しているドッカーのドキュメントによると、現在は廃止されています。彼らはまだされている現在サポートされていますが、彼らが廃止されるのを見かけ計画があります。
therobyouknow

85

古い投稿であることはわかっていますが、同じ問題が発生し、コードが機能しない理由を理解できませんでした。多くのテストの結果、その理由がわかりました。

fpmはnginxからフルパスを受け取り、fpmコンテナー内のファイルを検索しようとするようです。そのためserver.root、nginxコンテナー内に存在しない場合でも、nginx構成とまったく同じである必要があります。

実証するには:

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
よくやった!!!それがまさにポイントです!nginxルートを/var/www/html失敗時以外の代替パスに設定しました。
Alfred Huang

3
また、:9000ホストに公開されているポートではなく、コンテナで使用されているポートであることに注意してください。これを理解するのに2時間かかった。うまくいけば、あなたがする必要はありません。
2016年

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

4
portsここにセクションを含める必要はまったくありません。expose画像に含まれていない場合(おそらく画像に含まれている場合)に必要なだけです。コンテナー間通信を行う場合、PHP-FPMポートを公開しないでください。
2017年

AH01071: Got error 'Primary script unknown\n'php-fpmコンテナーがWebノードと同じディレクトリを共有する必要があるという解決策を探していましたが、それが解決策でした!
cptPH

23

前に指摘したように、問題はファイルがfpmコンテナーに表示されないことでした。ただし、コンテナー間でデータを共有するために推奨されるパターンは、データのみのコンテナーを使用することですこの記事で説明しています)。

簡単に言えば、データを保持するだけのコンテナを作成し、それをボリュームと共有し、アプリ内のこのボリュームをとリンクしますvolumes_from

compose(私のマシンでは1.6.2)を使用すると、docker-compose.ymlファイルは次のようになります。

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

とサービスにdataリンクされているボリュームを公開することに注意してください。その後のためのデータソースコードが含まれているサービス:nginxfpmDockerfile

FROM busybox

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

そしてDockerfilenginxの場合、それはデフォルトの設定を置き換えるだけです:

FROM nginx

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

完成させるために、この例が機能するために必要な構成ファイルを次に示します。

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;
    }
}

これは単にnginxに共有ボリュームをドキュメントルートとして使用するように指示し、nginxの適切な設定をfpmコンテナと通信できるように設定します(つまり、composeで定義されたホスト名HOST:PORTとのfpm:9000おかげで適切なSCRIPT_FILENAME)。


データがホストからコンテナーに更新されないように見えますが、docker ps -aを実行すると、データコンテナーが停止しているのがわかりますか?
Aftab Naveed

2
これが予想される動作です。データのみのコンテナーはコマンドを実行せず、停止したものとしてリストされます。また、Dockerfileデータコンテナのは、ビルド時にソースをコンテナにコピーしています。そのため、ホスト内のファイルを変更しても更新されません。ホストとコンテナの間でソースを共有する場合は、ディレクトリをマウントする必要があります。変更しdata、負荷へのコンファイルでサービスをimage: busyboxし、中volumes節入力し./sources:/var/www/html./sourcesホストであなたのソースへのパスです。
iKanor 2016

16

新しい答え

Docker Composeが更新されました。彼らは、今持っているバージョン2のファイル形式を

バージョン2のファイルはCompose 1.6.0以降でサポートされており、バージョン1.10.0以降のDockerエンジンが必要です。

Dockerのネットワーク機能をサポートするようになりました。実行すると、myapp_defaultというデフォルトのネットワークがセットアップされます。

彼らのドキュメントからあなたのファイルは以下のようになります:

version: '2'

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

これらのコンテナーは自動的にデフォルトのmyapp_defaultネットワークに追加されるため、相互に通信できます。次に、Nginxの設定を使用します。

fastcgi_pass fpm:9000;

また、コメントの@treefaceで言及されているように、PHP-FPMがポート9000でリッスンしていることを確認して/etc/php5/fpm/pool.d/www.confくださいlisten = 9000。これは、必要な場所を編集することで実行できます。

古い答え

以前のバージョンのDocker / Docker composeを使用していて、情報が欲しい方のために、以下をここに残しました。

私はこの質問への答えを見つけようとするときにグーグルでこの質問につまずき続けましたが、Docker-composeのQ / A重視のため、探していたものではありませんでした(執筆時点では、実験的なサポートしかありません) Dockerネットワーク機能)。だからここに私が学んだことに対する私の見解があります。

Dockerは最近、そのネットワーク機能を優先して、そのリンク機能を非推奨にしました

したがって、Docker Networks機能を使用すると、次の手順に従ってコンテナーをリンクできます。オプションの完全な説明については、以前にリンクされたドキュメントを参照してください。

最初にネットワークを作成します

docker network create --driver bridge mynetwork

次に、PHP-FPMコンテナーを実行して、ポート9000を開き、新しいネットワークに割り当てます(mynetwork)。

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

ここで重要なの--name php-fpmは、コマンドの最後にある名前です。これは後で必要になります。

次に、Nginxコンテナを実行して、作成したネットワークに再度割り当てます。

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

PHPおよびNginxコンテナの場合--volumes-from、必要に応じてコマンドなどを追加することもできます。

これでNginxの構成になります。これは次のようになります。

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;ロケーションブロックのに注意してください。php-fpmポートのコンテナに連絡してください9000。コンテナーをDockerブリッジネットワークに追加すると、すべてのコンテナーが自動的にホストファイルの更新を取得し、IPアドレスに対してコンテナー名が入力されます。そのため、Nginxは、php-fpm以前に名前を付けてmynetworkDockerネットワークに割り当てたPHP-FPMコンテナーに接続することを認識していることを確認します。

そのNginx構成は、Dockerコンテナーのビルドプロセス中に追加することも、後から追加することもできます。


また、確認するために覚えてphp-fpmこれは次のようになり、ポート9000でリッスンしているlisten = 9000中で/etc/php5/fpm/pool.d/www.conf
treeface

@treeface良い点に感謝します。コメントを更新しました。
DavidT 2016

8

以前の回答は解決されましたが、非常に明確に述べる必要があります。phpコードはphp-fpmコンテナーに配置する必要があり、静的ファイルはnginxコンテナーに配置する必要があります。簡単にするために、ほとんどの人は両方にすべてのコードを添付しました。将来的には、どのコンテナーがどの部分にアクセスできるかを最小限に抑えるために、私は自分のプロジェクトでコードのこれらの異なる部分を分離する可能性があります。

以下の私のサンプルファイルをこの最新の啓示で更新しました(ありがとう@alkaline)

これはdocker 2.0 forwardの最小セットアップのようですdocker 2.0で物事がずっと簡単になったため)。

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

上記のdocker-compose.ymlを更新:css、javascript、静的ファイルなどがあるサイトの場合、nginxコンテナーにアクセスできるファイルが必要です。すべてのphpコードをfpmコンテナーにアクセスできるようにしてください。ここでも、私の基本コードはcss、js、およびphpの乱雑な組み合わせです。この例では、すべてのコードを両方のコンテナーにアタッチします)

同じフォルダ内:

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;
    }
}

フォルダコード:

./code/index.php:

<?php
phpinfo();

そして、ホストファイルを更新することを忘れないでください:

127.0.0.1 site.local.[YOUR URL].com

そしてあなたのdocker-composeを実行してください

$docker-compose up -d

お気に入りのブラウザからURLを試してください

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

1
nginx構成ファイルは、Webサイトにphpファイルのみがあることを前提としています。静的ファイル(jpg、txt、svgなど)のnginxロケーションルールを作成し、phpインタープリターを使用しないことがベストプラクティスです。その場合、nginxコンテナーとphpコンテナーの両方がWebサイトファイルにアクセスする必要があります。上記の@iKanorの回答がそれを処理します。
Bernard

@Alkalineに感謝します。静的ファイルは私の元の答えに問題があります。実際、nginxが正しく機能するためには、少なくとも、最低限、cssファイルとjsファイルがそのマシンに対してローカルである必要があります。
Phillip

7

fpmコンテナーにもボリュームを与える必要があると思いますか?だから=>

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

fpmが要求されたファイルを見つけることができないため、これを行わない場合、要求の起動時にこの例外が発生します。

[エラー] 6#6:* 4 FastCGIがstderrで送信されました: "Primary script unknown"が上流からの応答ヘッダーの読み取り中に、クライアント:172.17.42.1、サーバー:localhost、要求: "GET / HTTP / 1.1"、上流: "fastcgi ://172.17.0.81:90​​00 "、ホスト:" localhost "


1
はい、そうです!
fpm

私はGitHubでの作業例を持っNginxPHP-FPMます
Victor Bocharsky 2015

1

他の誰かのために

Nginx 403エラー:[フォルダ]のディレクトリインデックスは禁止されています

使用しているときindex.phpながらindex.html完璧な作品と含まれたindex.php自分のサイトの設定のサーバブロック内のインデックスにsites-enabled

server {
    listen 80;

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

    index index.php

    ...
}

nginx.confファイルが/etc/nginx/nginx.conf実際にサイトhttp構成をブロックにロードすることを確認してください...

http {

    ...

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

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

このおかげで、古くはありますが有益です。/usr/share/nginx/htmlを使用する必要がありましたthanks、ありがとう
Simon Davies
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.