#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
в случае, если вы переключаетесь).