dockerfile-rails 0.4.0 → 0.4.2

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: 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