You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker容器化部署Rails应用时静态资源无法加载如何解决

问题根因

静态资源加载失败是4处配置错误共同导致的:

  • docker-compose配置的匿名卷覆盖了镜像构建阶段预编译的静态文件:app服务下配置的- /var/wwww/quickcard、- /var/wwww/quickcard/public为匿名挂载,容器启动时会用空卷覆盖镜像内对应路径的所有内容,Dockerfile中执行assets:precompile生成的public/assets下的文件会被直接清空;同时路径存在笔误,正确路径为/var/www,配置中多写了一个w。
  • Nginx容器未挂载静态资源目录:nginx服务的volumes配置仅挂载了日志目录,配置中写的/var/www/quickcard/public路径在nginx容器内部为空,根本无法读取到静态文件。
  • Nginx静态资源匹配规则错误:/assets/路径下多余的rewrite规则逻辑错误,会打乱正常的文件查找路径。
  • 运行环境配置不统一:Dockerfile中预编译资产时未指定RAILS_ENV=production,原compose中启动命令强制指定了development环境,Rails开发环境默认不会读取预编译的静态资产,也不会主动托管public目录下的静态文件。
修复步骤
  • 修正docker-compose.yml配置
    删除错误的匿名卷配置,改用命名卷在app和nginx容器间共享静态资源,统一环境变量为生产模式,修正路径笔误,参考配置如下:
    version: '2.2'
    services:
      app:
        build: 
          context: .
          dockerfile: ./Dockerfile
        command: ['bundle','exec','puma', '-C', 'config/puma.rb']
        environment:
          RAILS_ENV: production
          RAILS_SERVE_STATIC_FILES: true
        volumes:
          - assets_volume:/var/www/quickcard/public
          - app_tmp:/var/www/quickcard/tmp
        ports:
          - 5000:5000
      sidekiq:
        build: .
        command: bundle exec sidekiq -C config/sidekiq.yml
        environment:
          RAILS_ENV: production
        volumes:
          - app_tmp:/var/www/quickcard/tmp
      nginx:
        build:
          context: .
          dockerfile: ./nginx.Dockerfile
        volumes:
          - ./log-nginx:/var/log/nginx/
          - assets_volume:/var/www/quickcard/public:ro
        ports:
          - 80:80
        depends_on:
          - app
    volumes:
      assets_volume:
      app_tmp:
    
  • 修正Dockerfile资产预编译逻辑
    找到Dockerfile中预编译静态资源的行,替换为指定生产环境的执行命令,避免环境差异导致的资产路径不匹配:
    RUN RAILS_ENV=production bundle exec rake assets:precompile --trace
    
  • 修正Nginx配置规则
    删除/assets/路径下错误的rewrite规则,调整根路径匹配逻辑,优先读取本地静态文件,读不到再转发给Puma处理,参考配置如下:
    upstream puma {
       server app:5000 fail_timeout=0;
    }
    
    server {
        listen 80 default_server deferred;
        root /var/www/quickcard/public;
        index index.html index.htm;
        access_log /var/www/quickcard/log/nginx.access.log;
        error_log /var/www/quickcard/log/nginx.error.log;
    
        location / {
            try_files $uri $uri/index.html $uri.html @puma;
        }
    
        location @puma {
            proxy_pass http://puma;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_redirect off;
        }
    
        location ^~ /assets/ {
            gzip_static on;
            expires max;
            add_header Cache-Control public;
            add_header Strict-Transport-Security "";
            try_files $uri =404;
        }
    
        error_page 500 502 503 504 /500.html;
        client_max_body_size 4G;
        keepalive_timeout 10;
    }
    
  • 清理旧缓存后重新部署
    之前生成的错误匿名卷会残留脏数据,执行以下命令彻底清理后重新构建启动:
    docker compose down -v
    docker compose build --no-cache
    docker compose up -d
    
验证方法

启动后执行命令进入nginx容器检查静态文件是否存在:

docker compose exec nginx ls /var/www/quickcard/public/assets

如果输出列表中能看到编译日志里带hash的css、图片文件,访问页面时静态资源请求返回200状态码,即修复完成。

内容的提问来源于stack exchange,提问作者Saad Saddique

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 16:03:30