dockerfile-rails 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 438d7f814f08f6180930a72f8b2e6437cb3b53b45ff495d99a0e5abf5c85e361
4
- data.tar.gz: 71d21d72fc2aea9062fa9ba15e491083d279caa050f264e36de424a42e70ef44
3
+ metadata.gz: 0d84e3358f7afd8b5729d49e6b427e03f92eb6fe5da6a258689e933c09d721a2
4
+ data.tar.gz: 897d2a5f53c344c7162953e757b751ff646192ecd880f61cfb1754da5dfbb76d
5
5
  SHA512:
6
- metadata.gz: eb59c4587e1f9b0b9dbd93b7e71e49a2211659bb3e8c9c9a58919f39b3d30963a41b954ad182c418c19df2edabbf68578494bce069306bc1947c18af1fcf1c7a
7
- data.tar.gz: d3c30f95c8f17c44e1f4bc09639ed67a246e6d3b10646a758602bf97937e0da54507e1156b9728261a15ebba8de6618266002b5e6b5b02699bf0661f45da128b
6
+ metadata.gz: dd9b469a7c2c562c4cf137670c0d2fa177449c00ccb109e9aca65e0c48cb07d35b0a614c64daaaae699596eb2e191c7da4fcde1fc3da0566c3deed56e1b82494
7
+ data.tar.gz: 4ec4f71ecc02555da309027504872e137ccffa936b42ef42c935f2d0349b49cbccdfc39924f284653c952096bc3ea8014d9218eed92e7e71cfac15555e860705
data/README.md CHANGED
@@ -1,6 +1,10 @@
1
- ## Purpose
1
+ ## Overview
2
2
 
3
- Provide Rails generators to produce Dockerfiles and related files.
3
+ Provides Rails generators to produce Dockerfiles and related files. This is being proposed as the generator to be included in Rails 7.1, and a substantial number of pull requests along those lines have already been merged. This repository contains fixes and features beyond those pull requests. Highlights:
4
+
5
+ * Supports all [Rails supported releases](https://guides.rubyonrails.org/maintenance_policy.html), not just Rails 7.1, and likely works with a number of previous releases.
6
+ * Can be customized using flags on the `generate dockerfile` command, and rerun to produce a custom tailored dockerfile based on detecting the actual features used by your application.
7
+ * Can produce a `docker-compose.yml` file for locally testing your configuration before deploying.
4
8
 
5
9
  ## Usage
6
10
 
@@ -28,9 +32,17 @@ additional support may be needed:
28
32
  * `--redis` - add redis libraries
29
33
  * `--sqlite3` - add sqlite3 libraries
30
34
 
35
+ Optimizations:
36
+
37
+ * `--fullstaq` - use [fullstaq](https://fullstaqruby.org/) [images](https://github.com/evilmartians/fullstaq-ruby-docker) on [quay.io](https://quay.io/repository/evl.ms/fullstaq-ruby?tab=tags&tag=latest)
38
+ * `--jemalloc` - use [jemalloc](https://jemalloc.net/) memory allocator
39
+ * `--yjit` - enable [YJIT](https://github.com/ruby/ruby/blob/master/doc/yjit/yjit.md) optimizing compiler.
40
+ * `--swap=n` - allocate swap space. See [falloc options](https://man7.org/linux/man-pages/man1/fallocate.1.html#OPTIONS) for suffixes.
41
+
31
42
  Links:
32
43
 
33
44
  * [Demos](./DEMO.md)
34
45
  * [Preparations for Rails 7.1](https://community.fly.io/t/preparations-for-rails-7-1/9512)
35
46
  * [Rails Dockerfile futures](https://discuss.rubyonrails.org/t/rails-dockerfile-futures/82091/1)
36
47
  * [Fly Cookbooks](https://fly.io/docs/rails/cookbooks/)
48
+ * [app/templates/Dockerfile.tt](https://github.com/rails/rails/blob/main/railties/lib/rails/generators/rails/app/templates/Dockerfile.tt)
@@ -1,3 +1,5 @@
1
+ require 'erb'
2
+
1
3
  class DockerfileGenerator < Rails::Generators::Base
2
4
  include DockerfileRails::Scanner
3
5
 
@@ -10,10 +12,13 @@ class DockerfileGenerator < Rails::Generators::Base
10
12
  class_option :parallel, type: :boolean, default: false,
11
13
  desc: 'use build stages to install gems and node modules in parallel'
12
14
 
15
+ class_option :swap, type: :string, default: nil,
16
+ desc: 'allocate swapspace'
17
+
13
18
  class_option :compose, type: :boolean, default: false,
14
19
  desc: 'generate a docker-compose.yml file'
15
20
 
16
- class_option :redit, type: :boolean, default: false,
21
+ class_option :redis, type: :boolean, default: false,
17
22
  desc: 'include redis libraries'
18
23
 
19
24
  class_option :sqlite3, aliases: '--sqlite', type: :boolean, default: false,
@@ -52,6 +57,30 @@ class DockerfileGenerator < Rails::Generators::Base
52
57
 
53
58
  private
54
59
 
60
+ def render(options)
61
+ scope = (Class.new do
62
+ def initialize(obj, locals)
63
+ @_obj = obj
64
+ @_locals = OpenStruct.new(locals)
65
+ end
66
+
67
+ def method_missing(method, *args, &block)
68
+ if @_locals.respond_to? method
69
+ @_locals.send method, *args, &block
70
+ else
71
+ @_obj.send method, *args, &block
72
+ end
73
+ end
74
+
75
+ def get_binding
76
+ binding
77
+ end
78
+ end).new(self, options[:locals] || {})
79
+
80
+ template = IO.read(File.join(source_paths.last, "_#{options[:partial]}.erb"))
81
+ ERB.new(template, trim_mode: '-').result(scope.get_binding).strip
82
+ end
83
+
55
84
  def using_node?
56
85
  return @using_node if @using_node != nil
57
86
  @using_node = File.exist? 'package.json'
@@ -61,6 +90,10 @@ private
61
90
  options.redis? or @redis
62
91
  end
63
92
 
93
+ def using_execjs?
94
+ @gemfile.include? 'execjs'
95
+ end
96
+
64
97
  def parallel?
65
98
  using_node? && options.parallel
66
99
  end
@@ -88,9 +121,13 @@ private
88
121
  # ActiveStorage preview support
89
122
  packages << "libvips" if @gemfile.include? 'ruby-vips'
90
123
 
124
+ # Rmagick gem
125
+ packages += %w[pkg-config libmagickwand-dev] if @gemfile.include? 'rmagick'
126
+
91
127
  # node support, including support for building native modules
92
128
  if using_node?
93
- packages += %w(curl unzip node-gyp pkg-config)
129
+ packages += %w(node-gyp pkg-config)
130
+ packages += %w(curl unzip) unless using_execjs?
94
131
 
95
132
  # module build process depends on Python, and debian changed
96
133
  # how python is installed with the bullseye release. Below
@@ -129,6 +166,9 @@ private
129
166
  # ActiveStorage preview support
130
167
  packages << "libvips" if @gemfile.include? 'ruby-vips'
131
168
 
169
+ # Rmagick gem
170
+ packages << 'imagemagick' if @gemfile.include? 'rmagick'
171
+
132
172
  packages.sort
133
173
  end
134
174
 
@@ -184,7 +224,7 @@ private
184
224
  end
185
225
 
186
226
  def depend_on_bootsnap?
187
- @gemfile.include? 'bootstrap'
227
+ @gemfile.include? 'bootsnap'
188
228
  end
189
229
 
190
230
  def api_only?
@@ -3,35 +3,7 @@
3
3
  # Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile
4
4
  ARG RUBY_VERSION=<%= RUBY_VERSION %>
5
5
  <% if api_client_dir -%>
6
- ARG NODE_VERSION=<%= node_version %>
7
-
8
- FROM node:$NODE_VERSION-slim as client
9
-
10
- WORKDIR /rails/<%= api_client_dir %>
11
-
12
- ENV NODE_ENV=production
13
-
14
- # Install node modules
15
- COPY <%= api_client_files.join(' ') %> .
16
- <% if api_client_files.join.include? 'yarn' -%>
17
- <% if options.cache? -%>
18
- RUN --mount=type=cache,id=bld-yarn-cache,target=/root/.yarn \
19
- YARN_CACHE_FOLDER=/root/.yarn yarn install
20
- <% else -%>
21
- RUN yarn install
22
- <% end -%>
23
- <% else -%>
24
- <% if options.cache? -%>
25
- RUN --mount=type=cache,id=bld-yarn-cache,target=/root/.npm \
26
- npm install
27
- <% else -%>
28
- RUN npm install
29
- <% end -%>
30
- <% end -%>
31
-
32
- # build client application
33
- COPY <%= api_client_dir %> .
34
- RUN npm run build
6
+ <%= render partial: 'node_client' %>
35
7
 
36
8
 
37
9
  <% end -%>
@@ -49,23 +21,24 @@ ENV RAILS_ENV="production" \
49
21
  BUNDLE_PATH="vendor/bundle" \
50
22
  BUNDLE_WITHOUT="<%= options.ci? ? 'test' : 'development:test' %>"
51
23
 
24
+ # Update gems and preinstall the desired version of bundler
52
25
  ARG BUNDLER_VERSION=<%= Bundler::VERSION %>
53
26
  RUN gem update --system --no-document && \
54
27
  gem install -N bundler -v ${BUNDLER_VERSION}
55
28
 
29
+ <% if using_execjs? -%>
30
+ # Install packages needed to install nodejs
31
+ <%= render partial: 'apt_install', locals: {packages: %w(curl unzip), clean: true} %>
32
+
33
+ <%= render partial: 'install_node', locals: {yarn_version: nil} %>
34
+
35
+ <% end -%>
56
36
 
57
37
  # Throw-away build stage<%= parallel? ? 's' : '' %> to reduce size of final image
58
38
  FROM base as <%= parallel? ? 'pre' : '' %>build
59
39
 
60
- # Install packages need to build gems<%= using_node? ? " and node modules" : "" %>
61
- <% if options.cache? %>
62
- RUN --mount=type=cache,id=dev-apt-cache,sharing=locked,target=/var/cache/apt \
63
- --mount=type=cache,id=dev-apt-lib,sharing=locked,target=/var/lib/apt \
64
- apt-get update -qq && \
65
- <% else -%>
66
- RUN apt-get update -qq && \
67
- <% end -%>
68
- apt-get install -y <%= build_packages.join(" ") %>
40
+ # Install packages needed to build gems<%= using_node? ? " and node modules" : "" %>
41
+ <%= render partial: 'apt_install', locals: {packages: build_packages, clean: false} %>
69
42
 
70
43
  <% if parallel? -%>
71
44
 
@@ -73,24 +46,11 @@ FROM prebuild as node
73
46
 
74
47
  <% end -%>
75
48
  <% if using_node? -%>
76
- # Install JavaScript dependencies
77
- ARG NODE_VERSION=<%= node_version %>
78
- ARG YARN_VERSION=<%= yarn_version %>
79
- RUN curl -fsSL https://fnm.vercel.app/install | bash && \
80
- /root/.local/share/fnm/fnm install $NODE_VERSION
81
- ENV PATH=/root/.local/share/fnm/aliases/default/bin/:$PATH
82
- RUN npm install -g yarn@$YARN_VERSION
49
+ <%= render partial: 'install_node', locals: {node_version: using_execjs? ? nil : node_version} %>
83
50
 
84
51
  <% end -%>
85
52
  <% if parallel? -%>
86
- # Install node modules
87
- COPY package.json yarn.lock ./
88
- <% if options.cache? -%>
89
- RUN --mount=type=cache,id=bld-yarn-cache,target=/root/.yarn \
90
- YARN_CACHE_FOLDER=/root/.yarn yarn install
91
- <% else -%>
92
- RUN yarn install
93
- <% end -%>
53
+ <%= render partial: 'npm_install', locals: {sources: %w(package.json yarn.lock)} %>
94
54
 
95
55
 
96
56
  FROM prebuild as build
@@ -103,25 +63,23 @@ RUN --mount=type=cache,id=bld-gem-cache,sharing=locked,target=/srv/vendor \
103
63
  bundle config set app_config .bundle && \
104
64
  bundle config set path /srv/vendor && \
105
65
  bundle _${BUNDLER_VERSION}_ install && \
66
+ <% if depend_on_bootsnap? -%> && \
67
+ bundle exec bootsnap precompile --gemfile && \
68
+ <% end -%>
106
69
  bundle clean && \
107
70
  mkdir -p vendor && \
108
71
  bundle config set path vendor && \
109
72
  cp -ar /srv/vendor .
110
73
  <% else -%>
111
- RUN bundle _${BUNDLER_VERSION}_ install
74
+ RUN bundle _${BUNDLER_VERSION}_ install<% if depend_on_bootsnap? -%> && \
75
+ bundle exec bootsnap precompile --gemfile
76
+ <% end -%>
112
77
  <% end -%>
113
78
 
114
79
  <% if parallel? -%>
115
80
  asdf
116
81
  <% elsif using_node? -%>
117
- # Install node modules
118
- COPY package.json yarn.lock ./
119
- <% if options.cache? -%>
120
- RUN --mount=type=cache,id=bld-yarn-cache,target=/root/.yarn \
121
- YARN_CACHE_FOLDER=/root/.yarn yarn install
122
- <% else -%>
123
- RUN yarn install
124
- <% end -%>
82
+ <%= render partial: 'npm_install', locals: {sources: %w(package.json yarn.lock)} %>
125
83
 
126
84
  <% end -%>
127
85
  # Copy application code
@@ -129,7 +87,7 @@ COPY . .
129
87
 
130
88
  <% if depend_on_bootsnap? -%>
131
89
  # Precompile bootsnap code for faster boot times
132
- RUN bundle exec bootsnap precompile --gemfile app/ lib/
90
+ RUN bundle exec bootsnap precompile app/ lib/
133
91
 
134
92
  <% end -%>
135
93
  <% unless binfile_fixups.empty? -%>
@@ -147,17 +105,8 @@ RUN SECRET_KEY_BASE<%= Rails::VERSION::MAJOR<7 || Rails::VERSION::STRING.start_w
147
105
  FROM base
148
106
  <% unless deploy_packages.empty? -%>
149
107
 
150
- # Install packages need for deployment
151
- <% if options.cache? -%>
152
- RUN --mount=type=cache,id=dev-apt-cache,sharing=locked,target=/var/cache/apt \
153
- --mount=type=cache,id=dev-apt-lib,sharing=locked,target=/var/lib/apt \
154
- apt-get update -qq && \
155
- apt-get install --no-install-recommends -y <%= deploy_packages.join(" ") %>
156
- <% else -%>
157
- RUN apt-get update -qq && \
158
- apt-get install --no-install-recommends -y <%= deploy_packages.join(" ") %> && \
159
- rm -rf /var/lib/apt/lists /var/cache/apt/archives
160
- <% end -%>
108
+ # Install packages needed for deployment
109
+ <%= render partial: 'apt_install', locals: {packages: deploy_packages, clean: true} %>
161
110
  <% end -%>
162
111
 
163
112
  # Copy built application from previous stage
@@ -0,0 +1,10 @@
1
+ <% if options.cache? -%>
2
+ RUN --mount=type=cache,id=dev-apt-cache,sharing=locked,target=/var/cache/apt \
3
+ --mount=type=cache,id=dev-apt-lib,sharing=locked,target=/var/lib/apt \
4
+ apt-get update -qq && \
5
+ apt-get install --no-install-recommends -y <%= packages.join(" ") %>
6
+ <% else -%>
7
+ RUN apt-get update -qq && \
8
+ apt-get install --no-install-recommends -y <%= packages.join(" ") %><% if clean %> && \
9
+ rm -rf /var/lib/apt/lists /var/cache/apt/archives<% end %>
10
+ <% end -%>
@@ -0,0 +1,21 @@
1
+ <% if node_version and yarn_version -%>
2
+ # Install JavaScript dependencies
3
+ <% elsif node_version -%>
4
+ # Install Node.js
5
+ <% elsif yarn_version -%>
6
+ # Install yarn
7
+ <% end -%>
8
+ <% if node_version -%>
9
+ ARG NODE_VERSION=<%= node_version %>
10
+ <% end -%>
11
+ <% if yarn_version -%>
12
+ ARG YARN_VERSION=<%= yarn_version %>
13
+ <% end -%>
14
+ <% if node_version -%>
15
+ RUN curl -fsSL https://fnm.vercel.app/install | bash && \
16
+ /root/.local/share/fnm/fnm install $NODE_VERSION
17
+ ENV PATH=/root/.local/share/fnm/aliases/default/bin/:$PATH
18
+ <% end -%>
19
+ <% if yarn_version -%>
20
+ RUN npm install -g yarn@$YARN_VERSION
21
+ <% end -%>
@@ -0,0 +1,13 @@
1
+ ARG NODE_VERSION=<%= node_version %>
2
+
3
+ FROM node:$NODE_VERSION-slim as client
4
+
5
+ WORKDIR /rails/<%= api_client_dir %>
6
+
7
+ ENV NODE_ENV=production
8
+
9
+ <%= render partial: 'npm_install', locals: {sources: api_client_files} %>
10
+
11
+ # build client application
12
+ COPY <%= api_client_dir %> .
13
+ RUN npm run build
@@ -0,0 +1,17 @@
1
+ # Install node modules
2
+ COPY <%=sources.join(' ') %> .
3
+ <% if sources.join.include? 'yarn' -%>
4
+ <% if options.cache? -%>
5
+ RUN --mount=type=cache,id=bld-yarn-cache,target=/root/.yarn \
6
+ YARN_CACHE_FOLDER=/root/.yarn yarn install
7
+ <% else -%>
8
+ RUN yarn install
9
+ <% end -%>
10
+ <% else -%>
11
+ <% if options.cache? -%>
12
+ RUN --mount=type=cache,id=bld-npm-cache,target=/root/.npm \
13
+ npm install
14
+ <% else -%>
15
+ RUN npm install
16
+ <% end -%>
17
+ <% end -%>
@@ -1,5 +1,15 @@
1
1
  #!/bin/bash
2
2
 
3
+ <% if options.swap -%>
4
+ # allocate swap space
5
+ fallocate -l <%= options.swap %> /swapfile
6
+ chmod 0600 /swapfile
7
+ mkswap /swapfile
8
+ echo 10 > /proc/sys/vm/swappiness
9
+ swapon /swapfile
10
+ echo 1 > /proc/sys/vm/overcommit_memory
11
+
12
+ <% end -%>
3
13
  # If running the rails server then create or migrate existing database
4
14
  if [ "${*}" == "./bin/rails server" ]; then
5
15
  ./bin/rails <%= dbprep_command %>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dockerfile-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Ruby
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-16 00:00:00.000000000 Z
11
+ date: 2023-01-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -36,9 +36,12 @@ files:
36
36
  - Rakefile
37
37
  - lib/dockerfile-rails.rb
38
38
  - lib/dockerfile-rails/scanner.rb
39
- - lib/erbtest.rb
40
39
  - lib/generators/dockerfile_generator.rb
41
40
  - lib/generators/templates/Dockerfile.erb
41
+ - lib/generators/templates/_apt_install.erb
42
+ - lib/generators/templates/_install_node.erb
43
+ - lib/generators/templates/_node_client.erb
44
+ - lib/generators/templates/_npm_install.erb
42
45
  - lib/generators/templates/docker-compose.yml.erb
43
46
  - lib/generators/templates/docker-entrypoint.erb
44
47
  - lib/generators/templates/dockerignore.erb
data/lib/erbtest.rb DELETED
@@ -1,41 +0,0 @@
1
- TEMPLATE = <<-EOF
2
- value is <%= five %>
3
- other is <%= three %>
4
- EOF
5
-
6
- require 'delegate'
7
- require 'forwardable'
8
- class Scope < SimpleDelegator
9
- end
10
-
11
- require 'erb'
12
- class ShoppingList
13
- def five
14
- 'FiVe'
15
- end
16
-
17
- def initialize
18
- renderer = ERB.new(TEMPLATE)
19
- puts '***'
20
-
21
- values = {one: 'One', three: 'tHrEe'}
22
-
23
- scope = (Class.new(SimpleDelegator) do
24
- extend Forwardable
25
- def_delegators values, :one, :three
26
-
27
- def three
28
- 3
29
- end
30
- end).new(self)
31
-
32
- puts renderer.result(scope.get_binding)
33
- end
34
-
35
- def get_binding
36
- binding
37
- end
38
- end
39
-
40
- puts '?'
41
- test = ShoppingList.new