I don’t understand why Nginx doesn’t serve assets in my Rails 6 app running in Docker, in production.
Getting 404
for all of them.
Though when I explore the filesystem I see that they are present.
Other files are served correctly.
Here is my Dockerfile:
FROM ruby:2.6.1
RUN curl https://deb.nodesource.com/setup_12.x | bash
RUN curl https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update && apt-get install -y nodejs yarn
WORKDIR /my_app
RUN export RAILS_ENV=production
RUN gem install bundler:2.2.31
COPY Gemfile Gemfile.lock ./
COPY package.json ./
COPY vendor/gems/ vendor/gems/
RUN bundle install
COPY . ./
RUN yarn install --check-files
RUN RAILS_ENV=production bundle exec rake assets:precompile SECRET_KEY_BASE=1
EXPOSE 3000
CMD ["RAILS_ENV=production", "bundle", "exec", "puma", "-C", "config/puma.rb"]
docker-compose.yml
version: '3'
services:
database:
image: mysql:5.7
restart: always
container_name: database
environment:
MYSQL_DATABASE: my_app_production
MYSQL_USER: my_app
MYSQL_PASSWORD: my_app_password
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
ports:
- "3306:3306"
volumes:
- dbdata:/var/lib/mysql
my_app:
image: my_app
container_name: my_app
volumes:
- ./public:/my_app/public
- ./public/assets:/my_app/public/assets
- tmp:/my_app/tmp
- yarn_cache:/var/www/.cache/yarn
command: bash -c "sleep 5 && bundle exec rails db:migrate && bundle exec puma -C config/puma.rb"
environment:
RAILS_ENV: production
SECRET_KEY_BASE: xxxxxxx
DATABASE_PASSWORD: my_app_password
ports:
- "3000:3000"
depends_on:
- database
links:
- database
webserver:
image: nginx:latest
ports:
- 80:80
restart: always
volumes:
- ./nginx/conf/:/etc/nginx/conf.d/:ro
volumes:
dbdata:
tmp:
yarn_cache:
nginx.conf
upstream my_app {
server my_app:3000;
}
server {
server_name my.domain.name;
root /my_app/public;
try_files $uri/index.html $uri @rails;
location ~ ^/(assets|packs)/{
try_files $uri @rails;
access_log off;
gzip_static on;
expires max;
add_header Cache-Control public;
add_header Last-Modified "";
add_header ETag "";
break;
}
location @rails {
proxy_pass http://my_app;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto https;
proxy_redirect off;
proxy_connect_timeout 4m;
proxy_read_timeout 4m;
proxy_send_timeout 4m;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
listen 80;
}
Notes :
I am not sure if I need to add the volume public
at the very end of docker-compose.yml. I’ve tried with it and without it, and in both case assets get 404.
2
Answers
Ok, I finally found the solution
Nginx block in
docker-compose.yml
needs to have the public folder as a volume too :Just be sure to have in place: