Serve files from public folder in ruby on rails app

535 views Asked by At

I have been handed a Ruby Project that creates a document and serves it to the user, when I try to access the file on a local environment it it is delivered correctly, (this is the code that does so).

filepath = Rails.root.join("public",@records.document.url)
send_file (filepath)

So I know the file is constructed correctly and sending it to the user using send_file works at least in a local environment.

But when it's deployed on the production server (running Amazon EC2, ubuntu, deployed with dokku) I get a 500 Internal server error:

ActionController::MissingFile (Cannot read file *path of the file*)

Few things I'm noticing: doing a find / -iname "*filename*" tells me the file is stored in var/lib/docker/overlay2/*container_name*/merged/app/public/filename and var/lib/docker/overlay2/*container_name*/diff/app/public/filename but the result of joining Rails.root with the filename is app/public/filename, do I need to pass send_file the whole filepath?

I googled for a couple hours and it seems nginx has no access to the public folder because it's running in the host machine while the app is inside a container? How would I know if that is the case and if so, how should I serve the file?

The person who originally wrote the code told me to use OpenURI.open_uri() but googling it doesn't seem to turn up anything applicable to the situation.

1

There are 1 answers

2
max On

Nothing you're doing here actually makes sense - its sounds like you're just following a bunch of misinformation down a bunch of rabbit holes.

The way this is supposed to work is that the files in /public - not /app/public are served directly by the HTTP server (NGinX or Apache) in production and your Rails application in development (so you don't have to configure a local HTTP server). The /app directory is for your application code and uncompiled assets. Do not serve files from there - ever.

The /public directory is used for your compiled assets and stuff like robots.txt, the default error pages and various icons. Serving the files directly by your HTTP server is far more efficient then serving them through your Rails application. You can do a litmus test to see if serving static assets are working by sending curl -v YOUR_URL/robots.txt.

If this isn't working in production you need to check your NGinX configuration. There is no shortage of guides on how to serve static files with NGinX and Docker.

Serving files with a Rails controller and send_data / send_file should only be done when its actually needed:

  • The file is not a static file or something that can be compiled at deploy time.
  • You need to provide access control to the files with your application.
  • Your proxying files from another source.