web-dev-qa-db-fra.com

Comment lier correctement les conteneurs php-fpm et Nginx Docker?

J'essaie de relier 2 conteneurs distincts:

Le problème est que les scripts php ne fonctionnent pas. Peut-être que la configuration php-fpm est incorrecte. Voici le code source, qui est dans mon référentiel . Voici le fichier docker-compose.yml:

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

et Dockerfile que j’ai utilisé pour construire une image personnalisée basée sur celle de nginx:

FROM nginx

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

Enfin, voici ma configuration personnalisée de l'hôte virtuel 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;
    }
}

Quelqu'un pourrait-il m'aider à configurer ces conteneurs correctement pour exécuter des scripts php?

P.S. J'exécute les conteneurs via docker-composer comme ceci:

docker-compose up

depuis le répertoire racine du projet.

84
Victor Bocharsky

Ne codez pas l'adresse IP des conteneurs dans nginx config, docker link ajoute le nom d'hôte de la machine liée au fichier hosts du conteneur et vous devriez pouvoir faire un ping par nom d'hôte.

EDIT: Docker 1.9 La mise en réseau ne vous oblige plus à lier des conteneurs. Lorsque plusieurs conteneurs sont connectés au même réseau, leur fichier hôtes est mis à jour afin qu'ils puissent se joindre par nom d'hôte.

Chaque fois qu'un conteneur docker monte d'une image (même s'il arrête/démarre un conteneur existant), les conteneurs reçoivent de nouvelles adresses IP attribuées par l'hôte docker. Ces adresses IP ne sont pas dans le même sous-réseau que vos machines réelles.

voir docker link docs (c'est ce que compose utilise en arrière-plan)

mais plus clairement expliqué dans la docker-compose docs sur links & expose

liens

links:
 - db
 - db:database
 - redis

Une entrée portant le nom de l’alias sera créée dans/etc/hosts dans les conteneurs de ce service, par exemple:

172.17.2.186  db
172.17.2.186  database
172.17.2.187  redis

expose

Exposer les ports sans les publier sur la machine hôte - ils ne seront accessibles qu'aux services liés . Seul le port interne peut être spécifié.

et si vous configurez votre projet pour obtenir les ports + d'autres informations d'identification via des variables d'environnement, les liens définissent automatiquement un groupe de variables système :

Pour voir quelles variables d'environnement sont disponibles pour un service, exécutez docker-compose run SERVICE env.

name_PORT

URL complète, par exemple DB_PORT = tcp: //172.17.0.5: 5432

name_PORT_num_protocol

URL complète, par exemple DB_PORT_5432_TCP=tcp://172.17.0.5:5432

name_PORT_num_protocol_ADDR

Adresse IP du conteneur, par exemple DB_PORT_5432_TCP_ADDR=172.17.0.5

name_PORT_num_protocol_PORT

Numéro de port exposé, par exemple DB_PORT_5432_TCP_PORT=5432

name_PORT_num_protocol_PROTO

Protocole (TCP ou UDP), par ex. DB_PORT_5432_TCP_PROTO=tcp

name_NAME

Nom de conteneur qualifié complet, par exemple. DB_1_NAME=/myapp_web_1/myapp_db_1

30
Vincent De Smet

Je sais que c'est un vieux billet, mais j'ai le même problème et je ne comprends pas pourquoi votre code ne fonctionne pas. Après beaucoup de tests, j'ai découvert pourquoi.

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/
75
Rafael Quintela

Comme indiqué précédemment, le problème était que les fichiers n'étaient pas visibles par le conteneur fpm. Cependant, pour partager des données entre des conteneurs, le modèle recommandé utilise des conteneurs de données uniquement (comme expliqué dans cet article ).

Longue histoire: créez un conteneur qui ne contient que vos données, partagez-le avec un volume et liez ce volume dans vos applications avec volumes_from.

En utilisant compose (1.6.2 dans ma machine), le fichier docker-compose.yml se lirait comme suit:

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

Notez que data publie un volume lié aux services nginx et fpm. Ensuite, le Dockerfile du service data, qui contient votre code source:

FROM busybox

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

Et le Dockerfile pour nginx, qui remplace simplement la configuration par défaut:

FROM nginx

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

Par souci d’achèvement, voici le fichier de configuration requis pour que l’exemple fonctionne:

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

qui indique simplement à nginx d’utiliser le volume partagé en tant que racine du document et définit la bonne configuration pour que nginx puisse communiquer avec le conteneur fpm (par exemple, le droit Host:PORT, qui est fpm:9000 grâce au noms d’hôte définis par compose et le SCRIPT_FILENAME).

22
iKanor

Nouvelle réponse

Docker Compose a été mis à jour. Ils ont maintenant un format de fichier version 2 .

Les fichiers de la version 2 sont pris en charge par Compose 1.6.0+ et nécessitent un moteur Docker de la version 1.10.0+.

Ils supportent maintenant la fonctionnalité réseau de Docker qui, lorsqu’il est exécuté, configure un réseau par défaut appelé myapp_default

De leur documentation votre fichier ressemblerait à ce qui suit:

version: '2'

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

Comme ces conteneurs sont automatiquement ajoutés au réseau par défaut myapp_default , ils pourraient communiquer entre eux. Vous auriez alors dans la configuration Nginx:

fastcgi_pass fpm:9000;

Comme mentionné par @treeface dans les commentaires, n'oubliez pas de vous assurer que PHP-FPM écoute sur le port 9000. Pour ce faire, éditez /etc/php5/fpm/pool.d/www.conf où vous aurez besoin de listen = 9000.

Ancienne réponse

J'ai gardé le ci-dessous ici pour ceux qui utilisent une version plus ancienne de Docker/Docker Composer et aimeraient les informations.

Je n'arrivais pas à trébucher sur cette question sur Google lorsque j'essayais de trouver une réponse à cette question, mais ce n'était pas tout à fait ce que je cherchais en raison de l'accent mis sur les questions/réponses sur la composition docker (qui au moment de la rédaction n'a qu'un support expérimental pour fonctionnalités de réseau de docker). Alors voici mon point de vue sur ce que j'ai appris.

Docker a récemment obsolète son lien caractéristique en faveur de son fonctionnalité réseaux

Par conséquent, en utilisant la fonctionnalité Réseaux Docker, vous pouvez lier des conteneurs en procédant comme suit. Pour des explications complètes sur les options, consultez les documents liés précédemment.

Créez d'abord votre réseau

docker network create --driver bridge mynetwork

Ensuite, exécutez votre conteneur PHP-FPM en veillant à ouvrir le port 9000 et à l’affecter à votre nouveau réseau (mynetwork).

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

Le bit important ici est le --name php-fpm à la fin de la commande qui est le nom, nous en aurons besoin plus tard.

Ensuite, exécutez à nouveau votre conteneur Nginx et attribuez-le au réseau que vous avez créé.

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

Pour les conteneurs PHP et Nginx, vous pouvez également ajouter les commandes --volumes-from, etc.

Vient maintenant la configuration de Nginx. Ce qui devrait ressembler à ceci:

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

Notez le fastcgi_pass php-fpm:9000; dans le bloc d’emplacement. C’est ce que dit le conteneur de contacts php-fpm sur le port 9000. Lorsque vous ajoutez des conteneurs à un réseau Docker Bridge, ils obtiennent tous automatiquement une mise à jour du fichier hosts qui ajoute le nom de leur conteneur à leur adresse IP. Ainsi, lorsque Nginx s’aperçoit qu’il saura contacter le conteneur PHP-FPM que vous avez nommé php-fpm plus tôt et attribué à votre réseau mynetwork Docker.

Vous pouvez ajouter cette configuration Nginx pendant le processus de construction de votre conteneur Docker ou ultérieurement, à vous de décider.

14
DavidT

Comme les réponses précédentes ont résolu pour, mais doivent être énoncées très explicitement: le code php doit résider dans le conteneur php-fpm, tandis que les fichiers statiques doivent résider dans le conteneur nginx. Pour simplifier, la plupart des gens viennent d’attacher tout le code aux deux, comme je l’ai également fait ci-dessous. Si l'avenir, je vais probablement séparer ces différentes parties du code dans mes propres projets afin de minimiser les conteneurs qui ont accès à quelles parties.

Mis à jour mes exemples de fichiers ci-dessous avec cette dernière révélation (merci @alaline)

Cela semble être la configuration minimale pour docker 2.0 forward (car les choses sont devenues beaucoup plus faciles dans 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

(MISE À JOUR le fichier docker-compose.yml ci-dessus: Pour les sites contenant des fichiers css, javascript, fichiers statiques, etc., vous aurez besoin de ces fichiers accessibles au conteneur nginx. Tout en conservant tout le code php accessible à Encore une fois, comme mon code de base est un mélange désordonné de CSS, JS et PHP, cet exemple attache tout le code aux deux conteneurs)

Dans le même dossier:

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

Dans le code du dossier:

./code/index.php:

<?php
phpinfo();

et n'oubliez pas de mettre à jour votre fichier hosts:

127.0.0.1 site.local.[YOUR URL].com

et lancez votre docker-composez

$docker-compose up -d

et essayez l'URL de votre navigateur préféré

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

Je pense que nous devons également donner au conteneur fpm le volume, n’est-ce pas? So =>

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

Si je ne le fais pas, je rencontre cette exception lors du lancement d'une requête, car fpm ne peut pas trouver le fichier demandé:

[erreur] 6 # 6: * 4 FastCGI envoyé dans stderr: "Script principal inconnu" lors de la lecture de l'en-tête de réponse en amont, client: 172.17.42.1, serveur: localhost, requête: "GET/HTTP/1.1", en amont: "fastcgi : //172.17.0.81: 9000 ", hôte:" localhost "

6
leberknecht

Pour quiconque

Erreur Nginx 403: l'index des répertoires de [dossier] est interdit

lorsqu’on utilise index.php alors que index.html fonctionne parfaitement et qu’il a inclus index.php dans l’index du bloc serveur de la configuration de leur site dans sites-enabled

server {
    listen 80;

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

    index index.php

    ...
}

Assurez-vous que votre fichier nginx.conf dans /etc/nginx/nginx.conf charge effectivement la configuration de votre site dans le bloc http ...

http {

    ...

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

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