supernova32
Plug.Static is unable to serve files in production
Hi everyone,
I have been banging my head against a wall for the last couple of days because of a really weird problem I’m having in production.
I have a very simple Phoenix app that lets an admin user upload an image when creating a “note”. I’m using arc and arc-ecto to handle the file uploads. Everything works great in development. I’m able to upload the images without issues, and I can see them on the “notes” page.
However, when the app is running in production, I am able to upload the images without errors, but Phoenix is giving me a 404 when trying to fetch the images.
I already added the Plug.Static declaration to may endpoint.ex file, which is why I am able to see the images in dev, but no matter what I try in production, I always get a 404.
I have this in my endpoint.ex file. I already tried replacing Path.expand("./uploads") with the full path of where the files are when in production, and no luck.
plug Plug.Static,
at: "/uploads",
from: Path.expand("./uploads/"),
gzip: false
I know Elixir has access to this folder in production, because after uploading the images, they are there.
I’m using Distillery to create the release for production, and I’m deploying the app as a Docker image using docker-compose. I already made sure that the destination of the uploaded files is mounted as a volume on the Docker image, so that they don’t get destroyed after each deploy.
What could possibly be happening here?
I’m really close to just giving up trying to get Plug.Static to work in prod, and just Base64 encode the images and inlining them in the HTML file.
Any help, or guidance you can give me is greatly appreciated!
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #hex
- #performance










First 10 of 26 Posts
NobbZ
WHat does
Path.expand("./uploads/")return? Is it as expected and really the folder you have configured as target for copying the uploaded files to? relative pathes can be mean at times, especially if one isn’t careful or conscious about the actual working directory.Sadly you haven’t told us how you are starting your application… That could give some hints about the actual working directory.
wojtekmach
See this excerpt from the docs
have you tried it with tuple?
supernova32
@wojtekmach I should have mentioned I tried that as well without any luck.
@NobbZ The path I want to access is
/app/uploads. Docker mounts the app in/appso if I run a remote console to the running app in production and doPath.expand("./uploads")I get the correct path:/app/uploads. Plus, Arc is able to write to the correct path without any further modifications.I think posting my Docker file might help:
The app is started when
docker-composecreates thewebservice with theforegroundoptionOvermindDL1
Really should set it to
/app/uploadsthen, don’t use relative paths without the tuple format and even then only within an application itself, not outside of it. The CWD can change in unexpected ways in a massively concurrent system.I am curious if Plug.Static requires things it is serving to be local though, hmm…
supernova32
Thanks for the suggestion, but I already tried “hardcoding” the full path, and it did not work either.
Is it possible to define environment specific plugs, or would having 2 plugs be good enough? The paths are different on prod and dev, so if I hardcode them to “/app/uploads” dev breaks.
NobbZ
As plug is a macro, I’m not even sure if it resolve the path during compile time or runtime. Wrap an
IO.insoectand watch application build as well as start carefully for output. The:labeloption is of great help for such things.OvermindDL1
At compile-time for Plug.Static.
And I just tested it here with an absolute directory and it worked, so there is something else going on that’s possibly not related to the path for Plug.Static?
supernova32
Yeah, I thought about that myself, but I really do not want to start a marathon of a debugging session when simply a
Base64encode of the image will solve my issues. Once this application gets more usage, uploaded assets will be stored on S3 anyways, but I just can’t fight this nagging feeling. What I’m trying to do should work.I just can’t figure out why.OvermindDL1
Any chance at making an SSCCE that we can just git clone and spool up or so?
supernova32
Are you working with a Docker image as well?