docker 应用程序的 NGINX 反向代理
NGINX reverse proxy to docker applications
我目前正在学习设置 nginx,但我已经遇到了问题。我的 vps 上有 gitlab 和 nextcloud 运行,两者都可以通过正确的端口访问。因此,我用一个简单的 proxy_pass
命令创建了一个 nginx 配置,但我总是 reveice 502 Bad Gateway
。
Nextcloud、Gitlab 和 NGINX 是 docker 容器,并且 NGINX 已打开端口 80。其余两个容器打开了端口 3000 和 3100。
/etc/nginx/conf.d/gitlab.domain.com.conf
upstream gitlab {
server x.x.x.x:3000;
}
server {
listen 80;
server_name gitlab.domain.com;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://gitlab/;
}
}
/var/logs/error.log
2018/04/12 08:10:41 [error] 7#7: *1 connect() failed (113: Host is unreachable) while connecting to upstream, client: xx.201.226.19, server: gitlab.domain.com, request: "GET / HTTP/1.1", upstream: "http://xxx.249.7.15:3000/", host: "gitlab.domain.com"
2018/04/12 08:10:42 [error] 7#7: *1 connect() failed (113: Host is unreachable) while connecting to upstream, client: xx.201.226.19, server: gitlab.domain.com, request: "GET /favicon.ico HTTP/1.1", upstream: "http://xxx.249.7.15:3000/favicon.ico", host: "gitlab.domain.com", referrer: "http://gitlab.domain.com/
我的配置有什么问题?
我认为您可以使用比这更简单的配置方式。
也许是这样的:
http {
...
server {
listen 80;
charset utf-8;
...
location / {
proxy_pass http://gitlab:3000;
}
}
}
我假设您正在使用 docker 的内部 DNS 来访问容器,例如 gitlab 指向 gitlab 容器的内部 IP。如果是这种情况,那么您可以打开一个容器并尝试从另一个容器 ping gitlab 容器。
例如,您可以像这样从 nginx 容器中 ping gitlab 容器:
$ docker ps (use this to get the container id)
现在做:
$ docker exec -it <container_id_for_nginx_container> bash
# apt-get update -y
# apt-get install iputils-ping -y
# ping -c 2 gitlab
如果无法 ping 通,则表示容器之间无法相互通信。你在使用 docker-compose 吗?如果您是,那么我建议您查看 "links" 关键字,该关键字用于 link 应该能够相互通信的容器。因此,例如,您可能 link gitlab 容器到 postgresql。
如果这有帮助,请告诉我。
另一个利用 Docker 容器只是独立控制组中的进程这一优势的选项是将每个进程(容器)绑定到主机网络上的端口(而不是独立的网络组).这会绕过 Docker 路由,因此请注意主机上的端口可能不会重叠(与共享同一主机网络的任何正常进程没有区别。
您提到了 运行 Nginx 和 Nextcloud(我假设您使用的是 nextcloud fpm 映像,因为 FastCGI 支持)。在这种情况下,我必须在我的 Arch Linux 机器上执行以下操作:
/usr/share/webapps/nextcloud
绑定(绑定安装)到 /var/www/html
处的容器。
- 主机和容器进程的UID必须相同(在我的例子中,用户主机
http
和容器www-data
的UID=33)
- nginx.conf 中的 443 服务器块必须将 root 设置为主机的 nextcloud 路径,
root /usr/share/webapps/nextcloud;
。
- 必须调整通过 FastCGI 调用 php-fpm 的每个服务器块的 FastCGI 脚本路径,以引用 Docker 容器的 Nextcloud 基本路径
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
。换句话说,您不能像往常一样使用 $document_root
,因为它指向主机的 nextcloud 根路径。
- 可选:调整
config.php
文件中数据库和 Redis 的路径以不使用 localhost
,而是主机的主机名。 localhost
尽管已绑定到主机的主网络,但似乎引用了容器的主机。
我目前正在学习设置 nginx,但我已经遇到了问题。我的 vps 上有 gitlab 和 nextcloud 运行,两者都可以通过正确的端口访问。因此,我用一个简单的 proxy_pass
命令创建了一个 nginx 配置,但我总是 reveice 502 Bad Gateway
。
Nextcloud、Gitlab 和 NGINX 是 docker 容器,并且 NGINX 已打开端口 80。其余两个容器打开了端口 3000 和 3100。
/etc/nginx/conf.d/gitlab.domain.com.conf
upstream gitlab {
server x.x.x.x:3000;
}
server {
listen 80;
server_name gitlab.domain.com;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://gitlab/;
}
}
/var/logs/error.log
2018/04/12 08:10:41 [error] 7#7: *1 connect() failed (113: Host is unreachable) while connecting to upstream, client: xx.201.226.19, server: gitlab.domain.com, request: "GET / HTTP/1.1", upstream: "http://xxx.249.7.15:3000/", host: "gitlab.domain.com"
2018/04/12 08:10:42 [error] 7#7: *1 connect() failed (113: Host is unreachable) while connecting to upstream, client: xx.201.226.19, server: gitlab.domain.com, request: "GET /favicon.ico HTTP/1.1", upstream: "http://xxx.249.7.15:3000/favicon.ico", host: "gitlab.domain.com", referrer: "http://gitlab.domain.com/
我的配置有什么问题?
我认为您可以使用比这更简单的配置方式。
也许是这样的:
http {
...
server {
listen 80;
charset utf-8;
...
location / {
proxy_pass http://gitlab:3000;
}
}
}
我假设您正在使用 docker 的内部 DNS 来访问容器,例如 gitlab 指向 gitlab 容器的内部 IP。如果是这种情况,那么您可以打开一个容器并尝试从另一个容器 ping gitlab 容器。 例如,您可以像这样从 nginx 容器中 ping gitlab 容器:
$ docker ps (use this to get the container id)
现在做:
$ docker exec -it <container_id_for_nginx_container> bash
# apt-get update -y
# apt-get install iputils-ping -y
# ping -c 2 gitlab
如果无法 ping 通,则表示容器之间无法相互通信。你在使用 docker-compose 吗?如果您是,那么我建议您查看 "links" 关键字,该关键字用于 link 应该能够相互通信的容器。因此,例如,您可能 link gitlab 容器到 postgresql。
如果这有帮助,请告诉我。
另一个利用 Docker 容器只是独立控制组中的进程这一优势的选项是将每个进程(容器)绑定到主机网络上的端口(而不是独立的网络组).这会绕过 Docker 路由,因此请注意主机上的端口可能不会重叠(与共享同一主机网络的任何正常进程没有区别。
您提到了 运行 Nginx 和 Nextcloud(我假设您使用的是 nextcloud fpm 映像,因为 FastCGI 支持)。在这种情况下,我必须在我的 Arch Linux 机器上执行以下操作:
/usr/share/webapps/nextcloud
绑定(绑定安装)到/var/www/html
处的容器。- 主机和容器进程的UID必须相同(在我的例子中,用户主机
http
和容器www-data
的UID=33) - nginx.conf 中的 443 服务器块必须将 root 设置为主机的 nextcloud 路径,
root /usr/share/webapps/nextcloud;
。 - 必须调整通过 FastCGI 调用 php-fpm 的每个服务器块的 FastCGI 脚本路径,以引用 Docker 容器的 Nextcloud 基本路径
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
。换句话说,您不能像往常一样使用$document_root
,因为它指向主机的 nextcloud 根路径。 - 可选:调整
config.php
文件中数据库和 Redis 的路径以不使用localhost
,而是主机的主机名。localhost
尽管已绑定到主机的主网络,但似乎引用了容器的主机。