ruby-on-rails - Rails Assets 缓存未清除 - Docker、Rails、Nginx

标签 ruby-on-rails ruby docker nginx

我目前正在使用 Rails、Docker 和 Nginx 的组合(Rails 和 Nginx 都作为 Docker 镜像提供服务)。老实说,我不知道这种情况出了什么问题。 Rails 在生产环境中提供旧的和不存在的 JavaScript 和 CSS 文件。肯定是缓存问题。我怎么知道?我加载了之前的 Docker 镜像(它正在运行),将旧 URL 复制并粘贴到最新的镜像中,它们成功了!即使他们不在项目中!

我已经做了一些研究,但没有发现问题:

这是我所做的:

  • 修剪整个系统(docker system prune -a -p)。
  • 正确拉取最新的 Docker 镜像。
  • 从 Rails 中删除了 /tmp/cache/assets 文件夹
  • 使用了以下命令:RAILS_ENV='production' rails assets:precompile, rails assets:precompile, RAILS_ENV='production' rails assets:cleanrails assets:cleanrails assets:clobberRAILS_ENV='production' rails assets:clobber
  • 手动删除了 public/assets 文件夹。还是什么都没有
  • 我什至通过 config.assets.cache_store = :null_store 禁用了缓存存储

我有什么:

  • rails 5.1.5
  • Nginx 1.13.1
  • Docker 组合 3.2

这是为 Assets 提供服务的 Nginx 部分:

  # We enable gzip as a compression mechanism.
  location ~ ^/(assets|images|javascripts|stylesheets)/   {    
      try_files $uri @rails;     
      access_log off;    
      gzip_static on; 

      # to serve pre-gzipped version     
      expires max;    
      add_header Cache-Control public;     

      add_header Last-Modified "";    
      add_header ETag "";    
      break;  
   } 

有什么想法吗?我在新的 CSS 和 JavaScript 上收到错误 500。

编辑: 还有一件事。 Rails 确实为较新的 Assets 显示了正确的 URL,但是它们遇到了 500 服务器错误。

编辑 x2(添加了 Docker Compose 文件)*: 这个用于开发:

# WARNING!! Indentation is important! Be careful how you indent.
# All paths that point to the actual disk (not the Docker image) 
# are relative to the location of *this* file! 
# This is the development version of the file. The production one, the
# one that you need to upload is in ./docker-server/docker-compose.yml.
version: '3'
services:
  db:
    image: mariadb:10.3.5
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: "rootPassword"
      MYSQL_USER: "ruby"
      MYSQL_PASSWORD: "userPassword"
      MYSQL_DATABASE: "dev"
    ports:
    - "3306:3306"
    volumes:
      - db-data:/var/lib/mysql/data
      - ./db/rails_cprint.sql:/docker-entrypoint-initdb.d/rails_cprint.sql:ro
    networks: 
      - db
  pma:
    image: phpmyadmin/phpmyadmin
    depends_on:
      - db
    ports:
      - "4000:80"
    networks:
      - db
  app:
    build: .
    depends_on:
      - db
    environment:
      RAILS_ENV: development
      LOGSTASH_HOST: localhost
      SECRET_MYSQL_HOST: 'db'
      SECRET_MYSQL_DATABASE: 'dev'
      SECRET_MYSQL_USERNAME: 'ruby'
      SECRET_MYSQL_PASSWORD: 'userPassword'
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3001 -b '0.0.0.0'"
    stdin_open: true
    tty: true
    links:
      - db
    volumes:
      - "./:/var/www/cprint"
    ports:
      - "3001:3001"
      - "1234:1234"
    expose:
      - "3001"
    networks:
      - elk
      - db
  ipmask:
    build: ./reverse_proxy .
    restart: always
    command: "npm run debug"
    ports:
      - "5050:5050"
      - "9229:9229"
    volumes:
      - "./reverse_proxy/:/var/www/cprint"
    networks:
      - db
      - elk
    # Only on development!!
    depends_on:
      - db

# Volumes are the recommended storage mechanism of Docker. 
volumes:
  db-data:
    driver: local
  elasticsearch:
    driver: local

networks:
    elk:
      driver: bridge
    db:
      driver: bridge

这是在生产中使用的:

# This is the production docker-compose.ymlf ile. 
# This is a docker compose file that will pull from the private
# repo and will use all the images. 
# This will be an equivalent for production.

# The version is super important.
version: '3.2'
services:
  app:
    image: #The private rails URL rails:latest
    restart: always
    environment:
      RAILS_ENV: production
      RAILS_PRODUCTION_FULL_DEBUG: 'true'
      RAILS_LOG_TO_STDOUT: 'true'
    # https://github.com/docker/compose/issues/1393
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -e production -p 5000 -b '0.0.0.0'"
    volumes:
      - /var/www/app
    ports:
      - "5000:5000"
    expose:
      - "5000"
    networks:
      - elk
    links:
      - logstash
  # Uses Nginx as a web server
  # https://stackoverflow.com/questions/30652299/having-docker-access-external-files
  # 
  web:
    image: # the private NGINX image URL 
    # Runs it in debug
    # command: [nginx-debug, '-g', 'daemon off;']
    depends_on:
      - elasticsearch
      - kibana
      - app
      - ipmask
    restart: always
    # Maps the SSL at the same exact location in the server.
    volumes:
      # https://stackoverflow.com/a/48800695/1057052
      # - "/etc/ssl/:/etc/ssl/"
      - type: bind
        source: /etc/ssl/certs
        target: /etc/ssl/certs
      - type: bind
        source: /etc/ssl/private/
        target: /etc/ssl/private
      - type: bind
        source: /etc/nginx/.htpasswd
        target: /etc/nginx/.htpasswd
      - type: bind
        source: /etc/letsencrypt/
        target: /etc/letsencrypt/
    ports:
      - "80:80"
      - "443:443"
    networks:
      - elk
      - nginx
    links:
      - elasticsearch
      - kibana
  # Defining the ELK Stack! 
  # If you're moving servers, check the nmap issue.
  # https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:6.2.3
    restart: always
    container_name: elasticsearch
    networks:
      - elk
    # Default config from elastic.co
    environment:
      - cluster.name=docker-cluster
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    # Default config from elastic.co
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - elasticsearch:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
  logstash:
    image: docker.elastic.co/logstash/logstash:6.2.3
    restart: always
    container_name: logstash
    volumes:
      - ./elk/logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml
      - ./elk/logstash/pipeline/logstash.conf:/etc/logstash/conf.d/logstash.conf
    command: logstash -f /etc/logstash/conf.d/logstash.conf
    ports:
      - "5228:5228"
    environment:
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    networks:
      - elk
    links:
      - elasticsearch
    depends_on:
      - elasticsearch
  kibana:
    image: docker.elastic.co/kibana/kibana:6.2.3
    restart: always
    volumes:
      - ./elk/kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml
    ports:
      - "5601:5601"
    networks:
      - elk
    links:
      - elasticsearch
    depends_on:
      - elasticsearch
  ipmask:
    image: # the private image URL 
    command: "npm start"
    restart: always
    environment:
      - "NODE_ENV=production"
    expose:
      - "5050"
    ports:
      - "5050:5050"
    links:
      - app
    networks:
      - nginx


# # Volumes are the recommended storage mechanism of Docker. 
volumes:
  elasticsearch:
    driver: local
  rails:
    driver: local

networks:
    elk:
      driver: bridge
    nginx:
      driver: bridge

ruby Dockerfile:

# Main Dockerfile that contains the Rails application.
# https://docs.docker.com/compose/rails/#define-the-project

FROM ruby:2.5.0
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs vim

ENV RAILS_ROOT /var/www/app

RUN mkdir -p $RAILS_ROOT

WORKDIR $RAILS_ROOT


COPY Gemfile ./
COPY Gemfile.lock ./

RUN bundle install

COPY . .

注意:我已经从中删除了所有敏感信息。

编辑 x 3 我发现了问题。我正在研究解决方案。 我深入研究了 Nginx 的 Docker 镜像,并看到列出了 Rails 的公共(public)文件夹。我打开一看,里面的 Assets 是旧的。找到正确的解决方案后,我会发回。

编辑 x 4 只是正常的 Nginx 500 错误: enter image description here

最佳答案

找到解决方案!

长话短说

Rails 不是罪魁祸首,Docker 也不是……是我(图 🙄)。问题是我在为 Nginx 容器构建 Docker 镜像时手动复制了 public 文件夹,但我从未将其映射作为 Rails 和 Nginx 之间的共享卷。

解释及解决办法:

我忘记发布我的 Nginx Dockerfile。它包含一行内容:

# copy over static assets
COPY public public/

将 Rails 的公共(public)文件夹复制到 Docker 镜像。需要注意的是,这在我重建图像时运行!由于没有对 Nginx 进行任何更改,因此无需重建镜像!

解决方法是在 Rails 和 Nginx 之间的 docker-compose.yml 中创建共享卷:

# Some lines are omitted 
 app:
    image: rails:latest
    restart: always
    environment:
      RAILS_ENV: production
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -e production -p 5000 -b '0.0.0.0'"
    volumes:
      - public-files:/var/www/app/public
web:
    image: nginx:latest
    # Runs it in debug
    # command: [nginx-debug, '-g', 'daemon off;']
    depends_on:
      - elasticsearch
      - kibana
      - app
      - ipmask
    restart: always
    # Maps the SSL at the same exact location in the server.
    volumes:
      # https://stackoverflow.com/a/48800695/1057052
      # - "/etc/ssl/:/etc/ssl/"
      # We need to map this so Nginx can read the public files
      - public-files:/var/www/app/public:ro

关于ruby-on-rails - Rails Assets 缓存未清除 - Docker、Rails、Nginx,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51788285/

相关文章:

ruby-on-rails - ruby on rails 程序员会重构吗?

ruby-on-rails - 如何为 datetime_select 助手设置时区

javascript - 我可以在 Hyperstack 中制作功能组件吗?

python - 将文件作为参数传递给 Docker 容器

linux - NGINX docker 容器无法在网络浏览器中访问

hadoop - 如何在 Docker Swarm 中设置 Hadoop?

javascript - 冗余 Amazon S3/Rails

ruby-on-rails - Heroku、Postgresql、composite_primary_keys

ruby-on-rails - 设计注册功能

ruby-on-rails - 事件模型序列化程序和自定义 JSON 结构