skip to Main Content

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


  1. Chosen as BEST ANSWER

    Ok, I finally found the solution

    Nginx block in docker-compose.yml needs to have the public folder as a volume too :

      webserver:
        image: nginx:latest
        ports:
          - 80:80
        restart: always
        volumes:
          - ./nginx/conf/:/etc/nginx/conf.d/:ro
          - ./public:/my_app/public
    

  2. Just be sure to have in place:

    config.serve_static_assets = true
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search