http://docs.guzzlephp.org/en/stable/request-options.html でドキュメントを検索して検索し、エラーを確認しました https:/ /curl.haxx.se/libcurl/c/libcurl-errors.html そして、私の人生において、私は何が起こっているのか理解できません。/etc/hostsファイルにapp-oneとapp-twoの両方のURLがありますが、ブラウザーでcURLを使用してターミナルから正常にアクセスできるため、URLが正しいことはわかっています。
私のセットアップ:
次のように構成されたDockerコンテナー:
App 1 = php-fpm - responding app
App 2 = php-fpm - requesting app, using Guzzle 6.3.2
Nginx Reverse Proxy
nginx構成:
アプリ1:
upstream php-app-one {
server php-app-one:9000;
}
server {
listen 80;
listen [::]:80;
server_name app-one.local;
return 301 https://$server_name$request_uri;
}
server {
# SSL configuration
listen 443 ssl;
listen [::]:443 ssl;
ssl on;
ssl_certificate /etc/nginx/certs/app-one.crt;
ssl_certificate_key /etc/nginx/certs/app-one.key;
ssl_dhparam /etc/nginx/certs/dhparam.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
server_name app-one.local;
root /var/www/app-one;
index index.php index.html;
gzip_types text/plain text/css application/json application/x-javascript
text/xml application/xml application/xml+rss text/javascript;
# Add headers to serve security related headers
#
# Disable preloading HSTS for now. You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
# add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header Pragma "no-cache";
add_header Cache-Control "no-cache";
add_header X-uri "$uri";
location ~* \.(eot|otf|ttf|woff|woff2)$ {
add_header Access-Control-Allow-Origin *;
}
location / {
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header Host $Host;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header Authorization $http_authorization;
proxy_pass_header Authorization;
try_files $uri $uri/ /index.php?$args;
}
# Pass all .php files onto a php-fpm/php-fcgi server.
location ~ [^/]\.php(/|$) {
add_header X-debug-message "A php file was used" always;
# regex to split $uri to $fastcgi_script_name and $fastcgi_path
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
# This is a robust solution for path info security issue and
# works with "cgi.fix_pathinfo = 1" in /etc/php.ini (default)
# if (!-f $document_root$fastcgi_script_name) {
# return 404;
# }
# Check that the PHP script exists before passing it
# try_files $fastcgi_script_name =404;
# Bypass the fact that try_files resets $fastcgi_path_info
# see: http://trac.nginx.org/nginx/ticket/321
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
fastcgi_intercept_errors on;
fastcgi_pass php-app-one;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
add_header X-debug-message "A static file was served" always;
expires max;
# log_not_found off;
}
location ~ /\. {
deny all;
}
}
アプリ2:
upstream php-app-two {
server php-app-two:9000;
}
server {
listen 80;
listen [::]:80;
server_name app-two.local;
return 301 https://$server_name$request_uri;
}
server {
# SSL configuration
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /etc/nginx/certs/app-two.crt;
ssl_certificate_key /etc/nginx/certs/app-two.key;
ssl_dhparam /etc/nginx/certs/dhparam.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
server_name app-two.local;
root /var/www/app-two;
index index.php index.html;
gzip_types text/plain text/css application/json application/x-javascript
text/xml application/xml application/xml+rss text/javascript;
# Add headers to serve security related headers
#
# Disable preloading HSTS for now. You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
# add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header Pragma "no-cache";
add_header Cache-Control "no-cache";
add_header X-uri "$uri";
location ~* \.(eot|otf|ttf|woff|woff2)$ {
add_header Access-Control-Allow-Origin *;
}
location / {
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header Host $Host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header Authorization $http_authorization;
proxy_pass_header Authorization;
try_files $uri $uri/ /index.php;
}
# Pass all .php files onto a php-fpm/php-fcgi server.
location ~ [^/]\.php(/|$) {
add_header X-debug-message "A php file was used" always;
# add_header Location "$uri" always;
# regex to split $uri to $fastcgi_script_name and $fastcgi_path
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
# This is a robust solution for path info security issue and
# works with "cgi.fix_pathinfo = 1" in /etc/php.ini (default)
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
# Check that the PHP script exists before passing it
try_files $fastcgi_script_name =404;
# Bypass the fact that try_files resets $fastcgi_path_info
# see: http://trac.nginx.org/nginx/ticket/321
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
fastcgi_intercept_errors on;
fastcgi_pass php-app-two;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
}
Nginxリバースプロキシ:
worker_processes 1;
daemon off;
events {
worker_connections 1024;
}
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
http {
default_type application/octet-stream;
include /etc/nginx/conf/mime.types;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
application/x-font-ttf ttc ttf;
application/x-font-otf otf;
application/font-woff woff;
application/font-woff2 woff2;
application/vnd.ms-fontobject eot;
include /etc/nginx/conf.d/*.conf;
}
docker-compose.yml:
version: '3.3'
services:
# configured to act as a proxy for wp and member portal
nginx:
image: evild/Alpine-nginx:1.9.15-openssl
container_name: nginx
# volumes offer persistent storage
volumes:
- ./app_one:/var/www/app_one/:ro
- ./app_two:/var/www/app_two/:ro
- ./nginx/conf/nginx.conf:/etc/nginx/conf/default.conf:ro
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./certs:/etc/nginx/certs
# ports to bind to
ports:
- 80:80
- 443:443
# allows service to be accessible by other docker containers
expose:
- "80"
- "443"
depends_on:
- php-app_one
- php-app_two
environment:
TZ: "America/Los_Angeles"
# app-two php container
php-app_two:
environment:
TZ: "America/Los_Angeles"
image: joebubna/php
container_name: app_two_php
restart: always
volumes:
- ./app_two:/var/www/app_two
ports:
- 9000:9000
php-app_one:
environment:
TZ: "America/Los_Angeles"
image: joebubna/php
container_name: app_one_php
restart: always
volumes:
- ./app-one:/var/www/app-one
ports:
- 9001:9000
db:
image: mysql:5.6
container_name: app_two_mysql
volumes:
- db-data:/var/lib/mysql
- ./mysql/my.cnf:/etc/mysql/conf.d/ZZ-app-one.cnf:ro
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_DATABASE: cora
TZ: "America/Los_Angeles"
ports:
- 3306:3306
expose:
- "3306"
volumes:
db-data:
アプリ1とアプリ2では、docker-composeによる作成時にインポートされる自己署名証明書でSSLが有効になっています。
アプリ1には、アプリ2がアクセスする必要があるいくつかのAPIエンドポイントがあります。 Guzzle経由でアクセスしようとすると、次のエラーメッセージが表示されます:
Fatal error: Uncaught GuzzleHttp\Exception\ConnectException: cURL error 7: Failed to connect to app-one.local port 443: Connection refused (see http://curl.haxx.se/libcurl/c/libcurl-errors.html) in /var/www/app/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php on line 185
GuzzleHttp\Exception\ConnectException: cURL error 7: Failed to connect to app-one.local port 443: Connection refused (see http://curl.haxx.se/libcurl/c/libcurl-errors.html) in /var/www/app/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php on line 185
Call Stack:
0.0026 366656 1. {main}() /var/www/app/index.php:0
0.2229 3355944 2. Cora\Route->routeProcess() /var/www/app/index.php:45
0.2230 3357208 3. Cora\Route->routeFind() /var/www/app/vendor/cora/cora-framework/system/classes/Route.php:89
0.2240 3357912 4. Cora\Route->routeFind() /var/www/app/vendor/cora/cora-framework/system/classes/Route.php:474
0.2245 3358576 5. Cora\Route->getController() /var/www/app/vendor/cora/cora-framework/system/classes/Route.php:441
0.2364 3477872 6. Controllers\Api\Dashboard->__construct() /var/www/app/vendor/cora/cora-framework/system/classes/Route.php:501
0.2984 4086336 7. GuzzleHttp\Client->get() /var/www/app/controllers/api/controller.Dashboard.php:36
0.2984 4086712 8. GuzzleHttp\Client->__call() /var/www/app/controllers/api/controller.Dashboard.php:36
0.2984 4086712 9. GuzzleHttp\Client->request() /var/www/app/vendor/guzzlehttp/guzzle/src/Client.php:89
0.3521 4321000 10. GuzzleHttp\Promise\RejectedPromise->wait() /var/www/app/vendor/guzzlehttp/guzzle/src/Client.php:131
これが私が現在クライアントを実装している方法です(これを修正するために追加したコードの一部を含みます)。
<?php
namespace Controllers\Api;
use \GuzzleHttp\Client;
// use \GuzzleHttp\Psr7\Uri;
define('URL', 'https://app-one.local/api/');
class Dashboard extends ApiController
{
private $http;
public function __construct($container)
{
// We're using guzzle for our requests to help keep opportunity
// for cURL errors to a minimum
$this->http = new Client([
'base_uri' => URL,
'timeout' => 30.0,
'allow_redirects' => true,
'verify' => false,
'curl' => [
CURLOPT_VERIFYPEER => false
],
'headers' => [
'User-Agent' => 'curl/7.38.0',
],
]);
$response = $this->http->get('member/sales/hasalestest');
var_dump($response);
exit;
}
}
先ほど触れたように、ブラウザを介してこのエンドポイントに問題なくアクセスでき、-k
「安全でない」フラグ。 Guzzleのドキュメントでは5と6の構文の違いがあまり明確でないため、他に何ができるかわかりません。次にDrupal and Laravel =群衆は無関係な問題を抱える傾向があります。
このSOポストは似ているように見えますが(ハードコードされたポート番号とGuzzle v.5を差し引いたものです)、私が試していないものは何も触れられていません: PHP Guzzle 5:処理できませんPORT番号が含まれるURL 。
この質問も興味深いですが、App 1と対話する他のアプリに基づいて、他のアプリが特定のAPIエンドポイントを使用することを許可します: cURLエラー7:maps.googleapis.comポート443に接続できませんでした =
この時点で私が思いつくことができるのは、おそらくnginxの設定の問題でしょうか?正しい方向へのプッシュは、前進するために必要なすべてであり、消費する必要がある残りのエンドポイントを消費します。
ご指導ありがとうございます!
これは比較的単純な修正であることがわかりました。問題は、2つのfpmコンテナーがお互いを認識しておらず、app-twoのリクエストでapp-one.localを参照することで、app-twoが基本的にvoidにリクエストを送信していたことです。この修正は次のとおりです。
version: '3.3'
services:
nginx:
image: evild/Alpine-nginx:1.9.15-openssl
container_name: nginx
volumes:
- ./app-one:/var/www/app-one/:ro
- ./app-two:/var/www/app-two/:ro
- ./nginx/conf/nginx.conf:/etc/nginx/conf/default.conf:ro
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./certs:/etc/nginx/certs
ports:
- 80:80
- 443:443
expose:
- "80"
- "443"
depends_on:
- app-one
- app-two
environment:
TZ: "America/Los_Angeles"
# This is the fix
networks:
default:
aliases:
- app-one.local
- app-two.local
app-one:
environment:
TZ: "America/Los_Angeles"
image: joebubna/php
container_name: app-one
restart: always
volumes:
- ./app-one:/var/www/app-one
ports:
- 9000:9000
# This is the fix
networks:
- default
app-two:
environment:
TZ: "America/Los_Angeles"
image: joebubna/php
container_name: app-two
restart: always
volumes:
- ./app-two:/var/www/app-two
ports:
- 9001:9000
# This is the fix
networks:
- default
db:
image: mysql:5.6
container_name: mysql
volumes:
- db-data:/var/lib/mysql
- ./mysql/my.cnf:/etc/mysql/conf.d/ZZ-mysql.cnf:ro
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_DATABASE: cora
TZ: "America/Los_Angeles"
ports:
- 3306:3306
expose:
- "3306"
# This is the fix
networks:
- default
volumes:
db-data:
# This is the fix
networks:
default:
driver: bridge
私がやったことは、オーバーレイネットワークを作成し、nginxコンテナーに各fpmのドメイン名を認識させることです。これにより、2つのコンテナーは、IPまたはコンテナーID /名前ではなく、FQDNを介して相互に要求を送受信できます。後から見落とす簡単なこと。
問題は、ローカルマシン上のhostsファイルが、DockerインスタンスがIPをホストにマップする方法に影響を与えないことです。
コンテナ名でエンドポイントにアクセスしてみてください...
私の場合、URLが無効でしたが、URLの先頭に「https://」がありませんでした。追加すると大丈夫だった