Локальные изменения, не отражающие изменения в браузере при использовании томов docker

#ruby-on-rails #ruby #docker #docker-compose #docker-volume

#ruby-on-rails #ruby #docker #docker-compose #docker-volume

Вопрос:

У меня есть приложение rails, и я использую тома docker для сохранения кода. Всякий раз, когда я что-либо изменяю в local, код отражается в контейнере docker, но эти изменения отражаются в браузере. Я не уверен, что я что-то упускаю.

Прямо сейчас каждый раз, когда в коде происходят изменения, я перезапускаю контейнеры, что делать неправильно. Ниже приведен мой файл docker-compose

 version: '3'
services:
  webapp:
    build: .
    ports:
      - '3001:3001'
    volumes:
      - '.:/data/checklist'
    depends_on:
      - db
      - redis
    environment:
      DB_USERNAME: "root"
      DB_PASSWORD: "Mission2019"
      DB_DATABASE: "list"
      DB_PORT: 3306
      DB_HOST: db
      RAILS_ENV: production 
      RAILS_MAX_THREADS: 5
  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_DATABASE: "list"
      MYSQL_ROOT_PASSWORD: "Mission2019"
      MYSQL_USERNAME: "root"
  redis:
    image: redis:4.0-alpine
    command: redis-server
    ports:
      - '6379:6379'
  sidekiq:
    depends_on:
      - "db"
      - "redis"
    build: .
    command: bundle exec sidekiq -C config/sidekiq.yml
  

Это мой файл dockerfile

 FROM ubuntu:16.04


ENV RUBY_MAJOR="2.6" 
    RUBY_VERSION="2.6.3" 
    RUBYGEMS_VERSION="3.0.8" 
    BUNDLER_VERSION="1.17.3" 
    RAILS_VERSION="5.2.1" 
    RAILS_ENV="development" 
    GEM_HOME="/usr/local/bundle"
ENV BUNDLE_PATH="$GEM_HOME" 
    BUNDLE_BIN="$GEM_HOME/bin" 
    BUNDLE_SILENCE_ROOT_WARNING=1 
    BUNDLE_APP_CONFIG="$GEM_HOME"

ENV PATH="$BUNDLE_BIN:$GEM_HOME/bin:$GEM_HOME/gems/bin:$PATH"

USER root
RUN apt-get update amp;amp; 
      apt-get -y install sudo
RUN echo "%sudo ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers amp;amp; 
    addgroup --gid 1024 stars amp;amp; 
    useradd -G stars,sudo -d /home/user --shell /bin/bash -m user
RUN mkdir -p /usr/local/etc 
    amp;amp; echo 'install: --no-document' >> /usr/local/etc/gemrc 
    amp;amp; echo 'update: --no-document' >> /usr/local/etc/gemrc

USER user
RUN sudo apt-get -y install --no-install-recommends vim make gcc zlib1g-dev autoconf build-essential libssl-dev libsqlite3-dev 
    curl htop unzip mc openssh-server openssl bison libgdbm-dev ruby git libmysqlclient-dev tzdata mysql-client
    
RUN sudo rm -rf /var/lib/apt/lists/* 
    amp;amp; sudo curl -fSL -o ruby.tar.gz "http://cache.ruby-lang.org/pub/ruby/$RUBY_MAJOR/ruby-$RUBY_VERSION.tar.gz" 
    amp;amp; sudo mkdir -p /usr/src/ruby 
    amp;amp; sudo tar -xzf ruby.tar.gz -C /usr/src/ruby --strip-components=1 
    amp;amp; sudo rm ruby.tar.gz

USER root
RUN cd /usr/src/ruby 
    amp;amp; { sudo echo '#define ENABLE_PATH_CHECK 0'; echo; cat file.c; } > file.c.new amp;amp; mv file.c.new file.c 
    amp;amp; autoconf 
    amp;amp; ./configure --disable-install-doc

USER user
RUN cd /usr/src/ruby 
    amp;amp; sudo make -j"$(nproc)" 
    amp;amp; sudo make install 
    amp;amp; sudo gem update --system $RUBYGEMS_VERSION 
    amp;amp; sudo rm -r /usr/src/ruby
RUN sudo gem install bundler --version "$BUNDLER_VERSION"

RUN sudo mkdir -p "$GEM_HOME" "$BUNDLE_BIN" 
    amp;amp; sudo chmod 777 "$GEM_HOME" "$BUNDLE_BIN" 
    amp;amp; sudo gem install rails --version "$RAILS_VERSION"
RUN mkdir -p ~/.ssh amp;amp; 
    chmod 0700 ~/.ssh amp;amp; 
    ssh-keyscan github.com > ~/.ssh/known_hosts
ARG ssh_pub_key
ARG ssh_prv_key
RUN echo "$ssh_pub_key" > ~/.ssh/id_rsa.pub amp;amp; 
    echo "$ssh_prv_key" > ~/.ssh/id_rsa amp;amp; 
    chmod 600 ~/.ssh/id_rsa.pub amp;amp; 
    chmod 600 ~/.ssh/id_rsa
USER root
RUN curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
RUN apt-get install -y nodejs
USER user
WORKDIR /data
RUN sudo mkdir /data/checklist
WORKDIR /data/checklist
ADD Gemfile Gemfile.lock ./

RUN sudo chown -R user /data/checklist
RUN bundle install
ADD . .
RUN sudo chown -R user /data/checklist
EXPOSE 3001
ENV RAILS_ENV production
ENV RAILS_SERVE_STATIC_FILES true
ENV RAILS_LOG_TO_STDOUT true
ENTRYPOINT ["sh", "./config/docker/startup.sh"]
  
 #! /bin/sh

# Wait for DB services

# Prepare DB (Migrate - If not? Create db amp; Migrate)
kill -9 `cat /data/checklist/tmp/pids/server.pid`
sh ./config/docker/prepare-db.sh

# Pre-comple app assets
sh ./config/docker/asset-pre-compile.sh

# Start Application
rails s -p 3001 -b 0.0.0.0
  

production.rb

 Rails.application.configure do
  # Settings specified here will take precedence over those in config/application.rb.

  # Code is not reloaded between requests.
  config.cache_classes = true

  # Eager load code on boot. This eager loads most of Rails and
  # your application in memory, allowing both threaded web servers
  # and those relying on copy on write to perform better.
  # Rake tasks automatically ignore this option for performance.
  config.eager_load = true

  # Full error reports are disabled and caching is turned on.
  config.consider_all_requests_local       = false
  config.action_controller.perform_caching = true

  # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
  # or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
  # config.require_master_key = true

  # Disable serving static files from the `/public` folder by default since
  # Apache or NGINX already handles this.
  config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?

  # Compress JavaScripts and CSS.
  config.assets.js_compressor = :uglifier
  # config.assets.css_compressor = :sass

  # Do not fallback to assets pipeline if a precompiled asset is missed.
  config.assets.compile = false

  # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb

  # Enable serving of images, stylesheets, and JavaScripts from an asset server.
  # config.action_controller.asset_host = 'http://assets.example.com'

  # Specifies the header that your server uses for sending files.
  # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
  # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX

  # Store uploaded files on the local file system (see config/storage.yml for options)
  config.active_storage.service = :local

  # Mount Action Cable outside main process or domain
  # config.action_cable.mount_path = nil
  # config.action_cable.url = 'wss://example.com/cable'
  # config.action_cable.allowed_request_origins = [ 'http://example.com', /http://example.*/ ]

  # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
  # config.force_ssl = true

  # Use the lowest log level to ensure availability of diagnostic information
  # when problems arise.
  config.log_level = :debug

  # Prepend all log lines with the following tags.
  config.log_tags = [ :request_id ]

  # Use a different cache store in production.
  # config.cache_store = :mem_cache_store

  # Use a real queuing backend for Active Job (and separate queues per environment)
  # config.active_job.queue_adapter     = :resque
  # config.active_job.queue_name_prefix = "Checklist_#{Rails.env}"

  config.action_mailer.perform_caching = false

  # Ignore bad email addresses and do not raise email delivery errors.
  # Set this to true and configure the email server for immediate delivery to raise delivery errors.
  # config.action_mailer.raise_delivery_errors = false

  # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
  # the I18n.default_locale when a translation cannot be found).
  config.i18n.fallbacks = true

  # Send deprecation notices to registered listeners.
  config.active_support.deprecation = :notify

  # Use default logging formatter so that PID and timestamp are not suppressed.
  config.log_formatter = ::Logger::Formatter.new

  # Use a different logger for distributed setups.
  # require 'syslog/logger'
  # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
  config.action_mailer.default_url_options = { :host => 'localhost:3000', protocol: 'http' }
  config.action_mailer.smtp_settings = {
    address: "smtp.gmail.com",
    port: 587,
    domain: "example.com",
    authentication: "plain",
    enable_starttls_auto: true,
    user_name: ENV["EMAIL"],
    password: ENV["EMAIL_PASSWORD"]
  }
  if ENV["RAILS_LOG_TO_STDOUT"].present?
    logger           = ActiveSupport::Logger.new(STDOUT)
    logger.formatter = config.log_formatter
    config.logger    = ActiveSupport::TaggedLogging.new(logger)
  end

  # Do not dump schema after migrations.
  config.active_record.dump_schema_after_migration = false
end
  

Комментарии:

1. можете ли вы поделиться startup.sh и производственные файлы.rb?

2. Рабочая конфигурация не обновляет файлы. Используйте development для этой цели. Возможно, у вас проблема с прослушивателем файловой системы. В вашей config/development.rb попытке прокомментировать эту строку config.file_watcher = ActiveSupport::EventedFileUpdateChecker посмотрите, поможет ли это.

3. Я попытался прокомментировать упомянутую строку, она не работает. @DannyB

4. Стандартной практикой Docker, ориентированной на производство, было бы удаление volumes: , повторный запуск docker build , а также удаление и воссоздание контейнера при изменении кода приложения. Вы можете использовать некоторую комбинацию Bundler и rvm или rbenv , чтобы получить изолированную локальную среду разработки Ruby. Вы можете значительно упростить этот файл Dockerfile: не устанавливайте sudo и не пытайтесь настраивать доступ по ssh вообще, а рассмотрите возможность использования ruby образа Docker Hub в качестве основы.

Ответ №1:

Как правило, Rails не выполняет горячую перезагрузку кода в рабочей среде (по очень веским причинам, включая безопасность, стабильность и скорость), поэтому я бы подумал о переходе на среду разработки rails.

Следующее, чего следует опасаться, это того, что docker может не воспринять изменения таким образом, чтобы Rails «заметил», что файлы изменились (даже в development ). Чтобы помочь с этим, добавьте строку:

 config.file_watcher = ActiveSupport::FileUpdateChecker
  

в ваш production.rb файл (или development.rb в случае, если вы переключаетесь).