502 - 错误网关/"connection refused while connecting to upstream" 通过完全不受限制的 unix 套接字
502 - Bad Gateway / "connection refused while connecting to upstream" through a fully unrestricted unix socket
长话短说:
我有一个包含链接到 php
容器的 nginx
容器的应用程序,如果我尝试使用两个容器都可以访问的完全不受限制的(0777 模式)unix 套接字访问我的应用程序。
我使用 docker-compose
来管理我的应用程序,它在 OSX
上运行 docker 机器。
我的问题:
我用两个容器 (nginx+php) 建立了一个小项目,它与 TCP 套接字配合得很好。
但我想切换到 unix 套接字,并且在尝试访问我的应用程序时收到 502 - Bad Gateway
和以下日志:
nginx_1 | 2017/07/27 19:12:09 [error] 5#5: *1 connect() to unix:/sock/php.sock failed (111: Connection refused) while connecting to upstream, client: 192.168.99.1, server: 192.168.99.100, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/sock/php.sock:", host: "192.168.99.100:10080"
nginx_1 | 192.168.99.1 - - [27/Jul/2017:19:12:09 +0000] "GET / HTTP/1.1" 502 173 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:52.0) Gecko/20100101 Firefox/52.0"
nginx_1 | 192.168.99.1 - - [27/Jul/2017:19:12:09 +0000] "GET /favicon.ico HTTP/1.1" 502 173 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:52.0) Gecko/20100101 Firefox/52.0"
我已将包含套接字的目录设为安装在两个容器上的命名卷(参见下面的 docker-compose.yml
)
我不明白为什么 unix 套接字可以从两个容器访问并且完全不受限制:
来自 php
容器:
/sock # ls -la
total 8
drwxrwxrwx 2 root root 4096 Jul 27 17:56 .
drwxr-xr-x 57 root root 4096 Jul 27 17:33 ..
-rwxrwxrwx 1 root root 0 Jul 27 17:30 php.sock
来自 nginx
容器:
# cd /sock
# ls -la
total 8
drwxrwxrwx 2 root root 4096 Jul 27 17:56 .
drwxr-xr-x 31 root root 4096 Jul 27 17:33 ..
-rwxrwxrwx 1 root root 0 Jul 27 17:30 php.sock
我检查过:修改一个容器中的 /sock
内容也会修改另一个容器中同一目录的内容。
可能是什么问题?
关于我的项目的详细信息:
我的项目包含以下树状结构:
.
├── docker-compose.yml
├── index.php
├── services
│ ├── app
│ │ └── Dockerfile
│ └── nginx
│ └── nginx.conf
├── [Other php sources files and directories]
└── static
└── foo.html
这是我的 docker-compose.yml
:
version: '3'
services:
db: # I have no problem with the DB so far.
image: mysql
environment:
- MYSQL_ROOT_PASSWORD=XXXXXXXX
- MYSQL_USER=XXXXXXXX
- MYSQL_PASSWORD=XXXXXXXX
- MYSQL_DATABASE=XXXXXXXX
volumes:
- /var/lib/app/app_DB:/var/lib/mysql
nginx:
image: nginx
volumes:
- /var/lib/app/media:/var/www/media:ro
- /Users/vmonteco/Code/web/app/static:/var/www/static:ro
- /Users/vmonteco/Code/web/app/services/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- /Users/vmonteco/Code/web/app:/var/www/html:ro
- unix_socket:/sock
ports:
- "10080:80"
- "10443:443"
app:
build:
context: services/app
# ports:
# - "19000:9000"
links:
- db
volumes:
- /var/lib/app/media:/var/www/media
- /Users/vmonteco/Code/web/app/static:/var/www/static:ro
- /Users/vmonteco/Code/web/app:/var/www/html:ro
- unix_socket:/sock
depends_on:
- db
volumes:
unix_socket:
这是 app
Dockerfile :
FROM php:7.1-fpm-alpine
RUN docker-php-ext-install pdo pdo_mysql
RUN mkdir /sock && chmod -R 777 /sock
VOLUME /sock
RUN sed -i '/;listen.mode = 0660/c\listen.mode = 0777' /usr/local/etc/php-fpm.d/www.conf && sed -i '/listen = 127.0.0.1:9000/c\listen = /sock/php.sock' /usr/local/etc/php-fpm.d/www.conf
nginx
配置文件:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
root /var/www/html/;
server {
listen 80;
server_name 192.168.99.100;
location /media/ {
alias /var/www/media/;
autoindex off;
}
location /static/ {
alias /var/www/static/;
autoindex off;
}
location / {
try_files $uri $uri/ /index.php;
index index.html index.php;
}
location ~ \.php$ {
#try_files $uri =404;
#fastcgi_pass 192.168.99.100:19000;
fastcgi_pass unix:/sock/php.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
fastcgi_index index.php;
}
}
}
(请注意,我可以毫无问题地访问 /static/
或 /media/
网址。)
以及 php
容器中 /usr/local/etc/php-fpm.d/www.conf
文件中所有未注释的行,在构建时修改:
[www]
user = www-data
group = www-data
listen = /sock/php.sock
listen.mode = 0777
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
我终于找到了解释:
配置 fpm 服务的文件不是 /usr/local/etc/php-fpm.d/www.conf
(或者至少不是),而是 /usr/local/etc/php-fpm.d/zz-docker.conf
:
[global]
daemonize = no
[www]
listen = [::]:9000
修改此文件中的 listen
指令解决了问题。
长话短说:
我有一个包含链接到 php
容器的 nginx
容器的应用程序,如果我尝试使用两个容器都可以访问的完全不受限制的(0777 模式)unix 套接字访问我的应用程序。
我使用 docker-compose
来管理我的应用程序,它在 OSX
上运行 docker 机器。
我的问题:
我用两个容器 (nginx+php) 建立了一个小项目,它与 TCP 套接字配合得很好。
但我想切换到 unix 套接字,并且在尝试访问我的应用程序时收到 502 - Bad Gateway
和以下日志:
nginx_1 | 2017/07/27 19:12:09 [error] 5#5: *1 connect() to unix:/sock/php.sock failed (111: Connection refused) while connecting to upstream, client: 192.168.99.1, server: 192.168.99.100, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/sock/php.sock:", host: "192.168.99.100:10080"
nginx_1 | 192.168.99.1 - - [27/Jul/2017:19:12:09 +0000] "GET / HTTP/1.1" 502 173 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:52.0) Gecko/20100101 Firefox/52.0"
nginx_1 | 192.168.99.1 - - [27/Jul/2017:19:12:09 +0000] "GET /favicon.ico HTTP/1.1" 502 173 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:52.0) Gecko/20100101 Firefox/52.0"
我已将包含套接字的目录设为安装在两个容器上的命名卷(参见下面的 docker-compose.yml
)
我不明白为什么 unix 套接字可以从两个容器访问并且完全不受限制:
来自 php
容器:
/sock # ls -la
total 8
drwxrwxrwx 2 root root 4096 Jul 27 17:56 .
drwxr-xr-x 57 root root 4096 Jul 27 17:33 ..
-rwxrwxrwx 1 root root 0 Jul 27 17:30 php.sock
来自 nginx
容器:
# cd /sock
# ls -la
total 8
drwxrwxrwx 2 root root 4096 Jul 27 17:56 .
drwxr-xr-x 31 root root 4096 Jul 27 17:33 ..
-rwxrwxrwx 1 root root 0 Jul 27 17:30 php.sock
我检查过:修改一个容器中的 /sock
内容也会修改另一个容器中同一目录的内容。
可能是什么问题?
关于我的项目的详细信息:
我的项目包含以下树状结构:
.
├── docker-compose.yml
├── index.php
├── services
│ ├── app
│ │ └── Dockerfile
│ └── nginx
│ └── nginx.conf
├── [Other php sources files and directories]
└── static
└── foo.html
这是我的 docker-compose.yml
:
version: '3'
services:
db: # I have no problem with the DB so far.
image: mysql
environment:
- MYSQL_ROOT_PASSWORD=XXXXXXXX
- MYSQL_USER=XXXXXXXX
- MYSQL_PASSWORD=XXXXXXXX
- MYSQL_DATABASE=XXXXXXXX
volumes:
- /var/lib/app/app_DB:/var/lib/mysql
nginx:
image: nginx
volumes:
- /var/lib/app/media:/var/www/media:ro
- /Users/vmonteco/Code/web/app/static:/var/www/static:ro
- /Users/vmonteco/Code/web/app/services/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- /Users/vmonteco/Code/web/app:/var/www/html:ro
- unix_socket:/sock
ports:
- "10080:80"
- "10443:443"
app:
build:
context: services/app
# ports:
# - "19000:9000"
links:
- db
volumes:
- /var/lib/app/media:/var/www/media
- /Users/vmonteco/Code/web/app/static:/var/www/static:ro
- /Users/vmonteco/Code/web/app:/var/www/html:ro
- unix_socket:/sock
depends_on:
- db
volumes:
unix_socket:
这是 app
Dockerfile :
FROM php:7.1-fpm-alpine
RUN docker-php-ext-install pdo pdo_mysql
RUN mkdir /sock && chmod -R 777 /sock
VOLUME /sock
RUN sed -i '/;listen.mode = 0660/c\listen.mode = 0777' /usr/local/etc/php-fpm.d/www.conf && sed -i '/listen = 127.0.0.1:9000/c\listen = /sock/php.sock' /usr/local/etc/php-fpm.d/www.conf
nginx
配置文件:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
root /var/www/html/;
server {
listen 80;
server_name 192.168.99.100;
location /media/ {
alias /var/www/media/;
autoindex off;
}
location /static/ {
alias /var/www/static/;
autoindex off;
}
location / {
try_files $uri $uri/ /index.php;
index index.html index.php;
}
location ~ \.php$ {
#try_files $uri =404;
#fastcgi_pass 192.168.99.100:19000;
fastcgi_pass unix:/sock/php.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
fastcgi_index index.php;
}
}
}
(请注意,我可以毫无问题地访问 /static/
或 /media/
网址。)
以及 php
容器中 /usr/local/etc/php-fpm.d/www.conf
文件中所有未注释的行,在构建时修改:
[www]
user = www-data
group = www-data
listen = /sock/php.sock
listen.mode = 0777
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
我终于找到了解释:
配置 fpm 服务的文件不是 /usr/local/etc/php-fpm.d/www.conf
(或者至少不是),而是 /usr/local/etc/php-fpm.d/zz-docker.conf
:
[global]
daemonize = no
[www]
listen = [::]:9000
修改此文件中的 listen
指令解决了问题。