我目前正在使用 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:clean
、rails assets:clean
、rails assets:clobber
、RAILS_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 是旧的。找到正确的解决方案后,我会发回。
最佳答案
找到解决方案!
长话短说
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/