dockerfile-rails 1.6.25 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 749745baff7e3b0f67b72f9f94c2df9086c344c9665e2d67498c02c33cfbcbab
4
- data.tar.gz: 1b62d4bcf87fd0872057ee0e796b8f529a3b29b811e13447e7ac7df60961ab80
3
+ metadata.gz: 8309aa1e1fe7194297188df68c64c458d2fc7e892c0d4b0c0dadc9fe9b1d3a6e
4
+ data.tar.gz: c0d684a6bde26b27aa40c12e8cdd24bbdbd15d220258f48468ac6d4780fd15d3
5
5
  SHA512:
6
- metadata.gz: a88d05eac975d08d6ad47766300a996740c56e7a273488c7ec4e3f59729841d3edf132d91740a82410b7e60aff8017fb5aeabd15095b7ea0673f3088d08dd49f
7
- data.tar.gz: b78e868ec797f8c2bdb01e0afc7214e60b7a134414a06b15cc2151e8fcee62e6a59cfcbdde6898af22bb38a3742f4af433187b0e3aaa323c6dd85f956df3f012
6
+ metadata.gz: 0444b3658976d0b1f3e363848616a0774886e24a4c156daf0102f40c983ecb902f927af387be92c0f91447fad2c521a8ea1e378ca799d0a967400f8ffadc8ada
7
+ data.tar.gz: b174840c7d365257c77f706d82ac979a231d2cb91c633fcc79e2806f9deaa4ccdf1818e389bd2c6d9d115e978bb823f97ff091f9344f75121cd5ef0025441ace
data/README.md CHANGED
@@ -67,6 +67,7 @@ are actually using. But should you be using DATABASE_URL, for example, at runti
67
67
  additional support may be needed:
68
68
 
69
69
  * `--litefs` - use [LiteFS](https://fly.io/docs/litefs/)
70
+ * `--litestream` - use [LiteFS](https://litestream.io/)
70
71
  * `--mysql` - add mysql libraries
71
72
  * `--postgresql` - add postgresql libraries
72
73
  * `--redis` - add redis libraries
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "erb"
4
4
  require "json"
5
+ require "shellwords"
5
6
  require_relative "../dockerfile-rails/scanner.rb"
6
7
 
7
8
  class DockerfileGenerator < Rails::Generators::Base
@@ -15,10 +16,11 @@ class DockerfileGenerator < Rails::Generators::Base
15
16
  "compose" => false,
16
17
  "fullstaq" => false,
17
18
  "gemfile-updates" => true,
18
- "jemalloc" => false,
19
+ "jemalloc" => true,
19
20
  "label" => {},
20
21
  "link" => false,
21
22
  "litefs" => false,
23
+ "litestream" => false,
22
24
  "lock" => true,
23
25
  "max-idle" => nil,
24
26
  "migrate" => "",
@@ -74,7 +76,8 @@ class DockerfileGenerator < Rails::Generators::Base
74
76
  "node-gyp" => "gyp",
75
77
  "pkg-config" => "pkgconfig",
76
78
  "python" => "python3",
77
- "python-is-python3" => "python3"
79
+ "python-is-python3" => "python3",
80
+ "sqlite3" => "sqlite",
78
81
  }
79
82
 
80
83
  # load defaults from config file
@@ -162,6 +165,9 @@ class DockerfileGenerator < Rails::Generators::Base
162
165
  class_option :litefs, type: :boolean, default: OPTION_DEFAULTS.litefs,
163
166
  desc: "replicate sqlite3 databases using litefs"
164
167
 
168
+ class_option :litestream, type: :boolean, default: OPTION_DEFAULTS.litestream,
169
+ desc: "replicate sqlite3 databases using litesream"
170
+
165
171
  class_option :tigris, type: :boolean, default: OPTION_DEFAULTS.tigris,
166
172
  desc: "configure active storage to use tigris"
167
173
 
@@ -346,6 +352,10 @@ class DockerfileGenerator < Rails::Generators::Base
346
352
  fly_attach_consul
347
353
  end
348
354
 
355
+ if using_litestream?
356
+ template "litestream.rake.erb", "lib/tasks/litestream.rake"
357
+ end
358
+
349
359
  if File.exist?("fly.toml") && (fly_processes || !options.prepare || options.swap || deploy_database == "sqlite3")
350
360
  if File.stat("fly.toml").size > 0
351
361
  template "fly.toml.erb", "fly.toml"
@@ -488,6 +498,10 @@ private
488
498
  @gemfile.include?("litestack")
489
499
  end
490
500
 
501
+ def using_litestream?
502
+ options.litestream?
503
+ end
504
+
491
505
  def using_node?
492
506
  return @using_node if @using_node != nil
493
507
  return if using_bun?
@@ -594,6 +608,10 @@ private
594
608
  system "bundle add mysql2 --skip-install" unless has_mysql_gem?
595
609
  end
596
610
 
611
+ if options.litestream?
612
+ system "bundle add litestream --skip-install" unless @gemfile.include? "litestream"
613
+ end
614
+
597
615
  if options.redis? || using_redis?
598
616
  system "bundle add redis --skip-install" unless @gemfile.include? "redis"
599
617
  end
@@ -662,19 +680,30 @@ private
662
680
  end
663
681
 
664
682
  def base_packages
665
- packages = []
683
+ packages = %w(curl) # work with the default healthcheck strategy in Kamal
666
684
  packages += @@packages["base"] if @@packages["base"]
667
685
 
686
+ packages << "libjemalloc2" if options.jemalloc? && !options.fullstaq?
687
+
688
+ # start with databases: sqlite3, postgres, mysql
689
+ packages << "postgresql-client" if options.postgresql? || @postgresql
690
+ packages << "default-mysql-client" if options.mysql? || @mysql
691
+ packages << "freetds-bin" if options.sqlserver? || @sqlserver
692
+ if options.sqlite3? || @sqlite3
693
+ packages << "sqlite3" unless packages.include? "sqlite3"
694
+ end
695
+
696
+ # ActiveStorage preview support
697
+ packages << "libvips" if @gemfile.include? "ruby-vips"
698
+
668
699
  if using_execjs?
669
700
  if node_version == "lts"
670
701
  packages += %w(nodejs npm)
671
- else
672
- packages += %w(curl)
673
702
  end
674
703
  end
675
704
 
676
705
  if using_puppeteer?
677
- packages += %w(curl gnupg)
706
+ packages += %w(gnupg)
678
707
  end
679
708
 
680
709
  # charlock_holmes. Placed here as the library itself is
@@ -725,9 +754,6 @@ private
725
754
  # add git if needed to install gems
726
755
  packages << "git" if @git
727
756
 
728
- # ActiveStorage preview support
729
- packages << "libvips" if @gemfile.include? "ruby-vips"
730
-
731
757
  # Rmagick gem
732
758
  packages += %w[pkg-config libmagickwand-dev] if @gemfile.include? "rmagick"
733
759
 
@@ -736,7 +762,7 @@ private
736
762
  packages += %w(node-gyp pkg-config)
737
763
 
738
764
  unless using_execjs? || using_puppeteer?
739
- packages << "curl"
765
+ # packages << "curl"
740
766
  end
741
767
 
742
768
  # module build process depends on Python, and debian changed
@@ -762,7 +788,7 @@ private
762
788
  end
763
789
 
764
790
  if using_bun?
765
- packages += %w(curl unzip)
791
+ packages += %w(unzip)
766
792
  end
767
793
 
768
794
  if options.alpine?
@@ -773,18 +799,9 @@ private
773
799
  end
774
800
 
775
801
  def deploy_packages
776
- packages = %w(curl) # work with the default healthcheck strategy in MRSK
802
+ packages = []
777
803
  packages += @@packages["deploy"] if @@packages["deploy"]
778
804
 
779
- # start with databases: sqlite3, postgres, mysql
780
- packages << "postgresql-client" if options.postgresql? || @postgresql
781
- packages << "default-mysql-client" if options.mysql? || @mysql
782
- packages << "freetds-bin" if options.sqlserver? || @sqlserver
783
- packages << "libjemalloc2" if options.jemalloc? && !options.fullstaq?
784
- if options.sqlite3? || @sqlite3
785
- packages << "libsqlite3-0" unless packages.include? "sqlite3"
786
- end
787
-
788
805
  # litefs
789
806
  packages += ["ca-certificates", "fuse3", "sudo"] if options.litefs?
790
807
 
@@ -865,7 +882,7 @@ private
865
882
  packages = []
866
883
 
867
884
  if using_passenger?
868
- packages += %w(gnupg curl)
885
+ packages += %w(curl gnupg)
869
886
  repos += [
870
887
  "curl https://oss-binaries.phusionpassenger.com/auto-software-signing-gpg-key.txt |",
871
888
  " gpg --dearmor > /etc/apt/trusted.gpg.d/phusion.gpg &&",
@@ -891,7 +908,7 @@ private
891
908
  packages = []
892
909
 
893
910
  if using_puppeteer? && deploy_packages.include?("google-chrome-stable")
894
- packages += %w(gnupg curl)
911
+ packages += %w(gnupg)
895
912
  repos += [
896
913
  "curl https://dl-ssl.google.com/linux/linux_signing_key.pub |",
897
914
  " gpg --dearmor > /etc/apt/trusted.gpg.d/google-archive.gpg &&",
@@ -979,8 +996,8 @@ private
979
996
  end
980
997
 
981
998
  if options.jemalloc? && !options.fullstaq?
982
- env["LD_PRELOAD"] = "libjemalloc.so.2"
983
- env["MALLOC_CONF"] = "dirty_decay_ms:1000,narenas:2,background_thread:true"
999
+ # env["LD_PRELOAD"] = "libjemalloc.so.2"
1000
+ # env["MALLOC_CONF"] = "dirty_decay_ms:1000,narenas:2,background_thread:true"
984
1001
  end
985
1002
 
986
1003
  if using_puppeteer?
@@ -1133,6 +1150,30 @@ private
1133
1150
  end
1134
1151
  end
1135
1152
 
1153
+ def start_command
1154
+ if !options.procfile.blank?
1155
+ ["foreman", "start", "--procfile=#{options.procfile}"]
1156
+ elsif procfile.size > 1
1157
+ ["foreman", "start", "--procfile=Procfile.prod"]
1158
+ else
1159
+ command = Shellwords.split(procfile.values.first)
1160
+
1161
+ if command.first == "./bin/thrust"
1162
+ command[1..]
1163
+ else
1164
+ command
1165
+ end
1166
+ end
1167
+ end
1168
+
1169
+ def shellescape(string)
1170
+ if %r{\A[-\w._/= ]+\z}.match?(string)
1171
+ string.inspect
1172
+ else
1173
+ Shellwords.escape(string)
1174
+ end
1175
+ end
1176
+
1136
1177
  def node_version
1137
1178
  return unless using_node? || using_execjs?
1138
1179
 
@@ -1252,6 +1293,10 @@ private
1252
1293
  }
1253
1294
  end
1254
1295
 
1296
+ if using_litestream? && base[:rails]
1297
+ base[:rails] = "./bin/rake litestream:run " + base[:rails]
1298
+ end
1299
+
1255
1300
  if solidq_launcher == :procfile
1256
1301
  base["solidq"] = "bundle exec rake solid_queue:start"
1257
1302
  end
@@ -1263,6 +1308,10 @@ private
1263
1308
  options.thruster? || @gemfile.include?("thruster")
1264
1309
  end
1265
1310
 
1311
+ def using_kamal?
1312
+ @gemfile.include?("kamal")
1313
+ end
1314
+
1266
1315
  def fly_processes
1267
1316
  return unless File.exist? "fly.toml"
1268
1317
  return unless using_sidekiq? || using_solidq? || using_thruster?
@@ -1468,6 +1517,10 @@ private
1468
1517
  list[primary] = list[primary].sub(/^.*thrust /, "")
1469
1518
  end
1470
1519
 
1520
+ if using_litestream? && list["app"]
1521
+ list["app"] = "./bin/rake litestream:run #{list["app"]}"
1522
+ end
1523
+
1471
1524
  if toml.include? "[processes]"
1472
1525
  toml.sub!(/\[processes\].*?(\n\n|\n?\z)/m, "[processes]\n" +
1473
1526
  list.map { |name, cmd| " #{name} = #{cmd.inspect}" }.join("\n") + '\1')
@@ -1,6 +1,15 @@
1
- # syntax = docker/dockerfile:1
1
+ # syntax=docker/dockerfile:1
2
+ # check=error=true
3
+ <% if using_kamal? -%>
2
4
 
3
- # Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile
5
+ # This Dockerfile is designed for production, not development. Use with Kamal or build'n'run by hand:
6
+ # docker build -t demo .
7
+ # docker run -d -p 80:80 -e RAILS_MASTER_KEY=<value from config/master.key> --name demo demo
8
+
9
+ # For a containerized dev environment, see Dev Containers: https://guides.rubyonrails.org/getting_started_with_devcontainer.html
10
+ <% end -%>
11
+
12
+ # Make sure RUBY_VERSION matches the Ruby version in .ruby-version
4
13
  ARG RUBY_VERSION=<%= RUBY_VERSION %>
5
14
  <% if api_client_dir -%>
6
15
  <%= render partial: 'node_client' %>
@@ -27,18 +36,18 @@ WORKDIR /rails
27
36
  ARG <%= base_args.map {|key, value| "#{key}=#{value.inspect}"}.join(" \\\n ") %>
28
37
 
29
38
  <% end -%>
30
- # Set production environment
31
- ENV <%= base_env.join(" \\\n ") %>
32
-
33
39
  # Update gems and bundler
34
40
  RUN gem update --system <% if RUBY_VERSION.start_with? '2' %>3.4.22 <% end %>--no-document && \
35
41
  gem install -N <%= base_gems.join(" ") %>
36
42
 
37
43
  <% unless base_packages.empty? -%>
38
- # Install packages<% unless base_requirements.empty? -%> needed to install <%= base_requirements %><% end %>
44
+ # Install base packages<% unless base_requirements.empty? -%> needed to install <%= base_requirements %><% end %>
39
45
  <%= render partial: 'apt_install', locals: {packages: base_packages, clean: true, repos: base_repos} %>
40
46
 
41
47
  <% end -%>
48
+ # Set production environment
49
+ ENV <%= base_env.join(" \\\n ") %>
50
+
42
51
  <% if using_execjs? and node_version != 'lts' -%>
43
52
  <%= render partial: 'install_node', locals: {yarn_version: nil} %>
44
53
 
@@ -54,7 +63,7 @@ FROM base AS <%= parallel? ? 'pre' : '' %>build
54
63
 
55
64
  <% end -%>
56
65
  # Install packages needed to build gems<%= using_node? ? " and node modules" : "" %>
57
- <%= render partial: 'apt_install', locals: {packages: build_packages, clean: false, repos: ''} %>
66
+ <%= render partial: 'apt_install', locals: {packages: build_packages, clean: true, repos: ''} %>
58
67
 
59
68
  <% if parallel? -%>
60
69
 
@@ -113,13 +122,12 @@ RUN --mount=type=cache,id=bld-gem-cache,sharing=locked,target=/srv/vendor \
113
122
  RUN --mount=type=secret,id=gemserver_credentials,target=/kaniko/gemserver_credentials \
114
123
  <%= private_gemserver_env_variable_name %>="$(cat /kaniko/gemserver_credentials)" && \
115
124
  export <%= private_gemserver_env_variable_name %> && \
116
- bundle install<% if depend_on_bootsnap? && options.precompile != "defer" -%> && \
117
- bundle exec bootsnap precompile --gemfile<% end %> && \
125
+ bundle install && \
118
126
  <% else -%>
119
- RUN <% if options["precompiled-gems"] != true %>bundle config set force_ruby_platform true && \<%= "\n " %><% end %>bundle install<% if depend_on_bootsnap? && options.precompile != "defer" -%> && \
120
- bundle exec bootsnap precompile --gemfile<% end %> && \
127
+ RUN <% if options["precompiled-gems"] != true %>bundle config set force_ruby_platform true && \<%= "\n " %><% end %>bundle install && \
121
128
  <% end -%>
122
- rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git
129
+ rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git<% if depend_on_bootsnap? && options.precompile != "defer" -%> && \
130
+ bundle exec bootsnap precompile --gemfile<% end %>
123
131
 
124
132
  <% end -%>
125
133
  <% if using_passenger? -%>
@@ -298,7 +306,11 @@ COPY <<-"EOF" /rails/Procfile.prod
298
306
  EOF
299
307
 
300
308
  <% end -%>
309
+ <% if using_thruster? -%>
310
+ # Start server via Thruster by default, this can be overwritten at runtime
311
+ <% else -%>
301
312
  # Start the server by default, this can be overwritten at runtime
313
+ <% end -%>
302
314
  EXPOSE <%= using_thruster? ? '80' : '3000' %>
303
315
  <% if deploy_database == 'sqlite3' -%>
304
316
  VOLUME /data
@@ -4,6 +4,14 @@
4
4
  #!/bin/bash -e
5
5
  <% end -%>
6
6
 
7
+ <% if options.jemalloc? -%>
8
+ # Enable jemalloc for reduced memory usage and latency.
9
+ if [ -z "${LD_PRELOAD+x}" ]; then
10
+ LD_PRELOAD=$(find /usr/lib -name libjemalloc.so.2 -print -quit)
11
+ export LD_PRELOAD
12
+ fi
13
+
14
+ <% end -%>
7
15
  <% if options.swap && !File.exist?("fly.toml")-%>
8
16
  <% if run_as_root? or using_passenger? -%>
9
17
  <% @space = "" -%>
@@ -36,17 +44,13 @@ fi
36
44
  <% end -%>
37
45
  <% if options.prepare -%>
38
46
  <% if !options.procfile.blank? -%>
39
- if [ "${*}" == "foreman start --procfile=<%= options.procfile %>" ]; then
47
+ # If running the specified procfile then create or migrate existing database
40
48
  <% elsif procfile.size > 1 -%>
41
49
  # If running the production procfile then create or migrate existing database
42
- if [ "${*}" == "foreman start --procfile=Procfile.prod" ]; then
43
- <% elsif procfile.values.first.start_with? "./bin/rails server" -%>
44
- # If running the rails server then create or migrate existing database
45
- if [ "${1}" == "./bin/rails" ] && [ "${2}" == "server" ]<% if using_litefs? %> && [ "$FLY_REGION" == "$PRIMARY_REGION" ]<%end%>; then
46
50
  <% else -%>
47
51
  # If running the rails server then create or migrate existing database
48
- if [ "${*}" == <%= procfile.values.first.inspect %> <% if using_litefs? %>-a "$FLY_REGION" == "$PRIMARY_REGION" <%end%>]; then
49
52
  <% end -%>
53
+ if <%= start_command.map.with_index {|word, index| "[ \"${@: #{index - start_command.length}:1}\" == #{shellescape(word)} ]"}.join(" && ") %><% if using_litefs? %> && [ "$FLY_REGION" == "$PRIMARY_REGION" ]<%end%>; then
50
54
  <% if options.precompile == "defer" -%>
51
55
  ./bin/rails assets:precompile
52
56
  <% end -%>
@@ -2,13 +2,13 @@
2
2
 
3
3
  # Ignore git directory.
4
4
  /.git/
5
+ /.gitignore
5
6
 
6
7
  # Ignore bundler config.
7
8
  /.bundle
8
9
 
9
- # Ignore all environment files (except templates).
10
+ # Ignore all environment files.
10
11
  /.env*
11
- !/.env*.erb
12
12
 
13
13
  # Ignore all default key files.
14
14
  /config/master.key
@@ -50,4 +50,18 @@ GEMSERVER_CREDENTIALS.secret.txt
50
50
  <% end -%>
51
51
  /public/assets
52
52
  <% end -%>
53
+
54
+ # Ignore CI service files.
55
+ /.github
56
+
57
+ # Ignore Kamal files.
58
+ /config/deploy*.yml
59
+ /.kamal
60
+
61
+ # Ignore development files
62
+ /.devcontainer
63
+
64
+ # Ignore Docker-related files
65
+ /.dockerignore
66
+ /Dockerfile*
53
67
  <%= more_docker_ignores -%>
@@ -0,0 +1,55 @@
1
+ LITESTREAM_CONFIG = ENV["LITESTREAM_CONFIG"] || Rails.root.join("tmp/litestream.yml").to_s
2
+
3
+ LITESTREAM_TEMPLATE = <<-EOF
4
+ # This is the configuration file for litestream.
5
+ #
6
+ # For more details, see: https://litestream.io/reference/config/
7
+ #
8
+ dbs:
9
+ <%% for db in @dbs -%>
10
+ - path: <%%= db %>
11
+ replicas:
12
+ - type: s3
13
+ endpoint: $AWS_ENDPOINT_URL_S3
14
+ bucket: $BUCKET_NAME
15
+ path: storage/<%%= File.basename(db) %>
16
+ access-key-id: $AWS_ACCESS_KEY_ID
17
+ secret-access-key: $AWS_SECRET_ACCESS_KEY
18
+ <%% end -%>
19
+ EOF
20
+
21
+ namespace :litestream do
22
+ task prepare: "db:load_config" do
23
+ require "erubi"
24
+
25
+ @dbs =
26
+ ActiveRecord::Base
27
+ .configurations
28
+ .configs_for(env_name: "production", include_hidden: true)
29
+ .select { |config| [ "sqlite3", "litedb" ].include? config.adapter }
30
+ .map(&:database)
31
+
32
+ result = eval(Erubi::Engine.new(LITESTREAM_TEMPLATE).src)
33
+
34
+ unless File.exist?(LITESTREAM_CONFIG) && File.read(LITESTREAM_CONFIG) == result
35
+ File.write(LITESTREAM_CONFIG, result)
36
+ end
37
+
38
+ @dbs.each do |db|
39
+ next if File.exist?(db) or !ENV["BUCKET_NAME"]
40
+ system "litestream restore -config #{LITESTREAM_CONFIG} -if-replica-exists #{db}"
41
+ exit $?.exitstatus unless $?.exitstatus == 0
42
+ end
43
+ end
44
+
45
+ task :run do
46
+ require "shellwords"
47
+
48
+ exec(*%w[bundle exec litestream replicate -config],
49
+ LITESTREAM_CONFIG, "-exec", Shellwords.join(ARGV[1..-1]))
50
+ end
51
+ end
52
+
53
+ namespace :db do
54
+ task prepare: "litestream:prepare"
55
+ end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dockerfile-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.25
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Ruby
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-12-12 00:00:00.000000000 Z
10
+ date: 2025-01-06 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: rails
@@ -24,7 +23,6 @@ dependencies:
24
23
  - - ">="
25
24
  - !ruby/object:Gem::Version
26
25
  version: 3.0.0
27
- description:
28
26
  email: rubys@intertwingly.net
29
27
  executables: []
30
28
  extensions: []
@@ -52,6 +50,7 @@ files:
52
50
  - lib/generators/templates/dockerignore.erb
53
51
  - lib/generators/templates/fly.toml.erb
54
52
  - lib/generators/templates/litefs.yml.erb
53
+ - lib/generators/templates/litestream.rake.erb
55
54
  - lib/generators/templates/node-version.erb
56
55
  - lib/generators/templates/rollbar.rb.erb
57
56
  - lib/generators/templates/sentry.rb.erb
@@ -60,7 +59,6 @@ licenses:
60
59
  - MIT
61
60
  metadata:
62
61
  homepage_uri: https://github.com/fly-apps/dockerfile-rails
63
- post_install_message:
64
62
  rdoc_options: []
65
63
  require_paths:
66
64
  - lib
@@ -75,8 +73,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
75
73
  - !ruby/object:Gem::Version
76
74
  version: '0'
77
75
  requirements: []
78
- rubygems_version: 3.5.18
79
- signing_key:
76
+ rubygems_version: 3.6.2
80
77
  specification_version: 4
81
78
  summary: Dockerfile generator for Rails
82
79
  test_files: []