lib/generators/dockerfile_generator.rb in dockerfile-rails-1.3.0 vs lib/generators/dockerfile_generator.rb in dockerfile-rails-1.4.0
- old
+ new
@@ -1,8 +1,9 @@
# frozen_string_literal: true
require "erb"
+require "json"
require_relative "../dockerfile-rails/scanner.rb"
class DockerfileGenerator < Rails::Generators::Base
include DockerfileRails::Scanner
@@ -13,10 +14,11 @@
"compose" => false,
"fullstaq" => false,
"jemalloc" => false,
"label" => {},
"link" => true,
+ "litefs" => false,
"lock" => true,
"max-idle" => nil,
"mysql" => false,
"nginx" => false,
"parallel" => false,
@@ -109,10 +111,13 @@
desc: "include redis libraries"
class_option :sqlite3, aliases: "--sqlite", type: :boolean, default: OPTION_DEFAULTS.sqlite3,
desc: "include sqlite3 libraries"
+ class_option :litefs, type: :boolean, default: OPTION_DEFAULTS.litefs,
+ desc: "replicate sqlite3 databases using litefs"
+
class_option :postgresql, aliases: "--postgres", type: :boolean, default: OPTION_DEFAULTS.postgresql,
desc: "include postgresql libraries"
class_option :mysql, type: :boolean, default: OPTION_DEFAULTS.mysql,
desc: "include mysql libraries"
@@ -231,10 +236,16 @@
template "docker-entrypoint.erb", "bin/docker-entrypoint"
chmod "bin/docker-entrypoint", 0755 & ~File.umask, verbose: false
template "docker-compose.yml.erb", "docker-compose.yml" if options.compose
+ if using_litefs?
+ template "litefs.yml.erb", "config/litefs.yml"
+
+ fly_attach_consul
+ end
+
if @gemfile.include?("vite_ruby")
package = JSON.load_file("package.json")
unless package.dig("scripts", "build")
package["scripts"] ||= {}
package["scripts"]["build"] = "vite build --outDir public"
@@ -294,10 +305,14 @@
def run_as_root?
options.root?
end
+ def using_litefs?
+ options.litefs?
+ end
+
def using_node?
return @using_node if @using_node != nil
@using_node = File.exist? "package.json"
end
@@ -493,10 +508,13 @@
packages << "libsqlite3-0" if options.sqlite3? || @sqlite3
packages << "postgresql-client" if options.postgresql? || @postgresql
packages << "default-mysql-client" if options.mysql? || @mysql
packages << "libjemalloc2" if options.jemalloc? && !options.fullstaq?
+ # litefs
+ packages += ["ca-certificates", "fuse3", "sudo"] if options.litefs?
+
# ActiveStorage preview support
packages << "libvips" if @gemfile.include? "ruby-vips"
# Rmagick gem
if @gemfile.include?("rmagick") || @gemfile.include?("mini_magick")
@@ -599,17 +617,25 @@
end
def deploy_env
env = {}
- env["PORT"] = "3001" if options.nginx? && !using_passenger?
+ env["PORT"] = "3001" if (options.nginx? && !using_passenger?) || using_litefs?
if Rails::VERSION::MAJOR < 7 || Rails::VERSION::STRING.start_with?("7.0")
env["RAILS_LOG_TO_STDOUT"] = "1"
env["RAILS_SERVE_STATIC_FILES"] = "true" unless options.nginx?
end
+ if deploy_database == "sqlite3"
+ if using_litefs?
+ env["DATABASE_URL"] = "sqlite3:///litefs/production.sqlite3"
+ else
+ env["DATABASE_URL"] = "sqlite3:///data/production.sqlite3"
+ end
+ end
+
if options.yjit?
env["RUBY_YJIT_ENABLE"] = "1"
end
if options.jemalloc? && !options.fullstaq?
@@ -637,11 +663,11 @@
env.merge! @@args["deploy"].to_h { |key, value| [key, "$#{key}"] }
end
env.merge! @@vars["base"] if @@vars["base"]
- env.map { |key, value| "#{key}=#{value.inspect}" }
+ env.map { |key, value| "#{key}=#{value.inspect}" }.sort
end
def base_args
args = {}
@@ -714,13 +740,15 @@
binfixups
end
def deploy_database
- if options.postgresql? || @postgresql
+ # note: as database can be overridden at runtime via DATABASE_URL,
+ # use presence of "pg" or "mysql2" in the bundle as evidence of intent.
+ if options.postgresql? || @postgresql || @gemfile.include?("pg")
"postgresql"
- elsif options.mysql? || @mysql
+ elsif options.mysql? || @mysql || @gemfile.include?("mysql2")
"mysql"
else
"sqlite3"
end
end
@@ -850,7 +878,35 @@
ActiveSupport::Duration.parse("PT#{t.upcase}") rescue ActiveSupport::Duration.parse("P#{t.upcase}")
end.sum.seconds
end
rescue ArgumentError
nil
+ end
+
+ # if running on fly v2, make a best effort to attach consul
+ def fly_attach_consul
+ # certainly not fly unless there is a fly.toml
+ return unless File.exist? "fly.toml"
+
+ # Check fly.toml to guess if v1 or v2
+ toml = File.read("fly.toml")
+ return if toml.include?("enable_consul") # v1-ism
+ return unless toml.include?("primary_region") # v2
+
+ # see if flyctl is in the path
+ paths = ENV["PATH"].split(File::PATH_SEPARATOR)
+ cmds = %w(flyctl)
+ exts = ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [""]
+ flyctl = Enumerator.product(paths, cmds, exts).
+ map { |path, cmd, ext| File.join(path, "#{cmd}#{ext}") }.
+ find { |path| File.executable? path }
+ return unless flyctl
+
+ # see if secret is already set?
+ secrets = JSON.parse(`#{flyctl} secrets list --json`)
+ return if secrets.any? { |secret| secret["Name"] == "FLY_CONSUL_URL" }
+
+ # attach consul
+ say_status "execute", "flyctl consul attach", :green
+ system "#{flyctl} consul attach"
end
end