大家好,我正在尝试使用nginx作为反向代理使我的rails应用工作,rails应用和nginx位于单独的docker容器中,并通过docker-compose服务工作。我直到现在都没有成功。
设置环境production.rb => config.force_ssl = true
我的docker-compose文件是这样的:
version: '3'
services:
nginx:
image: reverse_nginx:latest
ports:
- '80:80'
depends_on:
- web
web:
image: production_my_app:latest
command: rails s -p 3000 -b '0.0.0.0' -e production
ports:
- '3000:3000'
depends_on:
- postgres
- redis
env_file:
- ...
restart: always
对于构建reverse_nginx:latest我将Dockerfile-nginx用于此:
# Base image: debian strech
FROM nginx:stable
RUN apt-get update -qq \
&& apt-get install -y ca-certificates
COPY ssl/server.crt /etc/ssl/certs/server.crt
COPY ssl/server.key /etc/ssl/private/server.key
RUN cd /etc/ssl/private \
&& chmod 600 server.* \
&& cd /etc/ssl/certs \
&& chmod 600 server.* \
&& update-ca-certificates --fresh
# establish where Nginx should look for files
ENV RAILS_ROOT /var/www/my_app/public
# Set working directory inside the image
WORKDIR $RAILS_ROOT
# create log directory
RUN mkdir log
# copy over static assets
COPY public .
# copy custom general nginx conf
COPY config/nginx.conf /etc/nginx/nginx.conf
# copy custom conf for my_app to sites-available folder
COPY config/my.app.conf /etc/nginx/sites-available/my.app.conf
# create sites-enabled folder and soft link custom conf for my_app
RUN mkdir -p /etc/nginx/sites-enabled/ \
&& cd /etc/nginx/sites-enabled/ \
&& ln -s /etc/nginx/sites-available/my.app.conf . \
&& ls -la \
&& nginx -c /etc/nginx/nginx.conf -t
EXPOSE 80
CMD [ "nginx", "-g", "daemon off;" ]
/etc/nginx/nginx.conf文件:
user nginx;
worker_processes auto;
worker_rlimit_nofile 1024;
events {
multi_accept on;
worker_connections 1024;
}
http {
# load configs
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*.conf;
# MIME
include /etc/nginx/mime.types;
default_type application/octet-stream;
# logging
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;
charset utf-8;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
server_tokens off;
log_not_found off;
types_hash_max_size 2048;
client_max_body_size 16M;
# SSL
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# modern configuration
ssl_protocols TLSv1.2;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256;
ssl_prefer_server_ciphers on;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
# resolver_timeout 2s;
}
/etc/nginx/sites-available/my_app.conf文件:
# HTTPS
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name my.app;
root /var/www/myapp/public;
ssl_certificate /etc/ssl/certs/server.crt;
ssl_certificate_key /etc/ssl/private/server.key;
# index.html fallback
location / {
try_files $uri $uri/ /index.html;
}
# reverse proxy
location /var/www/myapp/public {
# proxy_pass needs to be name of service on docker compose to connect with container?
proxy_pass http://web:3000;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
# HTTP redirect to HTTPS
server {
listen 80;
listen [::]:80;
server_name .my.app;
return 301 https://my.app$request_uri;
}
场景:
$ docker-compose up nginx_1 =>消息(如预期):
nginx_1 | "ssl_stapling" ignored, issuer certificate not found for certificate "/etc/ssl/certs/server.crt"
场景1:在浏览器中访问0.0.0.0,URL更改为https://my.app浏览器时说:ERR_SSL_PROTOCOL_ERROR
场景2:在浏览器中访问0.0.0.0:80,将网址更改为https://my.app浏览器时说:ERR_SSL_PROTOCOL_ERROR
场景3:在浏览器中访问0.0.0.0:3000,URL更改为https://0.0.0.0:3000 rails错误日志HTTPS解析错误格式错误的无效HTTP格式解析失败,浏览器说:ERR_SSL_PROTOCOL_ERROR
场景4:访问https://0.0.0.0:80,URL保持不变,nginx_1日志抛出字符:192.168.0.1 - - [28/Nov/2018:21:39:22 +0000] "\x16\x03\x01\x00\xB5\x01\x00\x00\xB1\x03\x03\xD3@kn" 400 166 "-" "-"
我认为问题出在my_app.conf中的proxy_pass指令中,但老实说,我不知道自己现在在做什么。您能帮我了解发生了什么吗?我从未使用过nginx
答案 0 :(得分:1)
您遇到一些问题:
要找到SSL证书,需要对其进行修复,以消除SSL错误
位置应指向您正在访问的网址(这是一个正则表达式)
nginx不了解docker
服务器名称配置不正确
要以相反的顺序解决这些问题,请不要将传递代理到http://web
,而传递给您在以下位置启动容器的地址:http://0.0.0.0:3000
。
接下来,您似乎想要将所有将反向代理击中的Web通信都代理到rails。如果是这种情况,则将其设置为唯一的位置障碍,并将其设置为location / { ... }
。
示例:
# reverse proxy
location / {
# pass everything to rails
proxy_pass http://0.0.0.0:3000;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
您可能需要组合证书,但我首先要检查以确保您的证书实际上位于配置中列出的路径上
Nginx将让多个主机使用相同的IP地址并进行适当的路由。这基于server_name
指令。看来您希望所有通向0.0.0.0
(或最终主机)的流量都被代理到rails。因此,最好的办法就是添加catchall。在:80
和:443
服务器块中,将server_name my.app;
更改为server_name _ my.app;
。此处,_
充当通配符。如果不这样做,您将需要编辑/etc/hosts
文件并将my.app
指向localhost
,然后通过转到https://my.app
而不是0.0.0.0
来访问它。 / p>