Nginx routing with Docker Rails 5 Postgres app



当我尝试将 Rails 应用程序 Dockerize Rails 应用程序放入容器并在主机上运行 Nginx 时,我遇到了从外向内的路由问题。 我无法访问 rails 应用程序容器中的/public。相反,我可以在主机看到/var/www/app/public

如何从 Nginx 路由到 Docker Rails 容器?

nginx.conf:

upstream puma_app {
server 127.0.0.1:3000;
}
server {
listen 80;
client_max_body_size 4G;
keepalive_timeout 10;
error_page 500 502 504 /500.html;
error_page 503 @503;
server_name localhost app;
root /var/www/app/public;
try_files $uri/index.html $uri @puma_app;
location @puma_app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://puma_app;
# limit_req zone=one;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
}
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
location = /50x.html {
root html;
}
location = /404.html {
root html;
}
location @503 {
error_page 405 = /system/maintenance.html;
if (-f $document_root/system/maintenance.html) {
rewrite ^(.*)$ /system/maintenance.html break;
}
rewrite ^(.*)$ /503.html break;
}
if ($request_method !~ ^(GET|HEAD|PUT|PATCH|POST|DELETE|OPTIONS)$ ){
return 405;
}
if (-f $document_root/system/maintenance.html) {
return 503;
}
location ~ .(php|html)$ {
return 405;
}
}

docker-compose.yml:

version: '2'
services:
app:
build: .
command: bundle exec puma -C config/puma.rb
volumes:
- 'app:/var/www/app'
- 'public:/var/www/app/public'
ports:
- '3000:3000'
depends_on:
- postgres
env_file:
- '.env'
postgres:
image: postgres:latest
environment:
POSTGRES_USER: 'postgres_user'
ports:
- '5432:5432'
volumes:
- 'postgres:/var/lib/postgresql/data'
volumes:
postgres:
app:
public:

Dockerfile

# Base image:
FROM ruby:2.4
# Install dependencies
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
# Set an environment variable where the Rails app is installed to inside of Docker image:
ENV RAILS_ROOT /var/www/app
RUN mkdir -p $RAILS_ROOT
ENV RAILS_ENV production
ENV RACK_ENV production
# Set working directory, where the commands will be ran:
WORKDIR $RAILS_ROOT
# Gems:
COPY Gemfile Gemfile
COPY Gemfile.lock Gemfile.lock
RUN gem install bundler
RUN bundle install
COPY config/puma.rb config/puma.rb
# Copy the main application.
COPY . .
RUN bundle exec rake RAILS_ENV=production assets:precompile
VOLUME ["$RAILS_ROOT/public"]
EXPOSE 3000
# The default command that gets ran will be to start the Puma server.
CMD bundle exec puma -C config/puma.rb

我认为您正在尝试从容器内的主机访问/public/var/www/app/public.

您需要在容器内挂载主机目录。可以在运行容器时使用-v "/public:/var/www/app/public"

您的Dockerfile存在一些问题。我不确定您要如何设置 docker 映像,但似乎您尝试在 docker 卷中使用public目录;我建议将编译的资产存储到 docker 镜像本身中。这样,您可以确保资产始终与图像在一起。

您当前的Dockerfile应该在COPY . .之前运行assets:precompile;这意味着在将资产复制到 docker 映像之前,应先将资产编译到public目录中。

无论如何,在更复杂的项目设置中使用它之前,您应该先尝试运行一个非常简单的 docker 应用程序,这里有一篇可能对您有所帮助的博客文章(免责声明:我写了那篇文章(

在 docker 中,每个容器都有自己的 IP 地址,彼此之间不local。因此,您不能将 Nginx 容器中的127.0.0.1ip 用作 Rails 容器的 ip。幸运的是,docker 容器可以使用它们的服务名称链接在一起。所以你必须替换你的上游

upstream puma_app {
server http://app:3000;
}

此外,您应该将 Nginx 容器添加到您的 docker-compose 文件中(假设您的 nginx conf 文件位于 dirconfig/nginx/conf.d(:

version: '2'
services:
app:
build: .
command: bundle exec puma -C config/puma.rb
volumes:
- app:/var/www/app
- public:/var/www/app/public
- nginx-confs:/var/www/app/config/nginx/conf.d
ports:
- 3000:3000
depends_on:
- postgres
env_file: .env
postgres:
image: postgres:latest
environment:
- POSTGRES_USER=postgres_user
ports:
- 5432:5432
volumes:
- postgres:/var/lib/postgresql/data
nginx:
image: nginx:latest
ports:
- 80:80
- 443:443
volumes:
- nginx-confs:/etc/nginx/conf.d
volumes:
postgres:
app:
public:
nginx-confs:

最新更新