dockerfile-rails 0.0.1 → 0.1.0

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: 7730245e044329345b271524027cd640794a3577c4b49d2a2ce47a3cf21c94c4
4
- data.tar.gz: 88fe182e5b8ab19d9725391cfaf1c0010e9d89d7cf44a9e3618f680bbe700315
3
+ metadata.gz: 536685e13e342227e5d6af85e3d778539668bbdab81b5430902ae08286a57c62
4
+ data.tar.gz: a3155769a131089493ae0682e195f6108dd4c81d03c79c6774ce21af0eda04be
5
5
  SHA512:
6
- metadata.gz: 411539b040956ad9a1c437437aa36d2ed96a1769354162a2d8e57244c6a5b7dbf7fb1ff45efbd40f86da990b4741c01c6a871c84ac6be735104c4ab8ff39aa17
7
- data.tar.gz: 06b7e3ac3225bca70269b8aae26dcb9e2f9846b911416a09f4af6f0be82137eebd7f365bf815e0ff1a6c0783a7b8d082cf1bf5856f9913e90bb349408868d60f
6
+ metadata.gz: 0547a5c9224213fdab9b99a2ca03e5aa411f086abb723b121561226079968e6da769f9acdf76ee123b1fbd57a64aa7d622c5dc44a48ab05717d9a523322955a1
7
+ data.tar.gz: 37923bd9eaa647b9ca44433ce374d30e0250799e7078669b180f2ac5734241dc7af757a58b12227de999d78e3d4171ae7e3e9ebbbf828e90f2d71184999fb8c7
data/README.md CHANGED
@@ -1,3 +1,29 @@
1
1
  ## Purpose
2
2
 
3
- Provide Rails generators to produce Dockerfiles and related files.
3
+ Provide Rails generators to produce Dockerfiles and related files.
4
+
5
+ ## Usage
6
+
7
+ ```
8
+ bundle add dockerfile-rails
9
+ bin/rails generate dockerfile
10
+ ```
11
+
12
+ General options:
13
+
14
+ * `--force` - overwrite existing files
15
+ * `--ci` - include test gems in deployed image
16
+ * `--cache` - use build caching to speed up builds
17
+ * `--parallel` - use multi-stage builds to install gems and node modules in parallel
18
+ * `--compose` - generate a `docker-compose.yml` file
19
+
20
+ Dependencies:
21
+
22
+ Generally the dockerfile generator will be able to determine what dependencies you
23
+ are actually using. But should you be using DATABASE_URL, for example, at runtime
24
+ additional support may be needed:
25
+
26
+ * `--mysql` - add mysql libraries
27
+ * `--posgresql` - add posgresql libraries
28
+ * `--redis` - add redis libraries
29
+ * `--sqlite3` - add sqlite3 libraries
@@ -18,6 +18,7 @@ module DockerfileRails
18
18
  ### ruby gems ###
19
19
 
20
20
  @gemfile = []
21
+ @git = false
21
22
 
22
23
  if File.exist? 'Gemfile.lock'
23
24
  parser = Bundler::LockfileParser.new(Bundler.read_file('Gemfile.lock'))
@@ -25,7 +26,9 @@ module DockerfileRails
25
26
  end
26
27
 
27
28
  if File.exist? 'Gemfile'
28
- @gemfile += Bundler::Definition.build('Gemfile', nil, []).dependencies.map(&:name)
29
+ gemfile_definition = Bundler::Definition.build('Gemfile', nil, [])
30
+ @gemfile += gemfile_definition.dependencies.map(&:name)
31
+ @git = !gemfile_definition.spec_git_paths.empty?
29
32
  end
30
33
 
31
34
  @sidekiq = @gemfile.include? 'sidekiq'
@@ -62,14 +65,6 @@ module DockerfileRails
62
65
  end
63
66
 
64
67
  @redis = @redis_cable || @redis_cache || @sidekiq
65
-
66
- ### api-only ###
67
-
68
- @apionly = Rails.application.config.api_only
69
-
70
- ### db:prepare ###
71
-
72
- @dbprep = (Rails::VERSION::MAJOR >= 6) ? 'db:prepare' : 'db:migrate'
73
68
  end
74
69
  end
75
70
  end
@@ -1,6 +1,30 @@
1
1
  class DockerfileGenerator < Rails::Generators::Base
2
2
  include DockerfileRails::Scanner
3
3
 
4
+ class_option :ci, type: :boolean, default: false,
5
+ desc: 'include test gems in bundle'
6
+
7
+ class_option :cache, type: :boolean, default: false,
8
+ desc: 'use build cache to speed up installs'
9
+
10
+ class_option :parallel, type: :boolean, default: false,
11
+ desc: 'use build stages to install gems and node modules in parallel'
12
+
13
+ class_option :compose, type: :boolean, default: false,
14
+ desc: 'generate a docker-compose.yml file'
15
+
16
+ class_option :redit, type: :boolean, default: false,
17
+ desc: 'include redis libraries'
18
+
19
+ class_option :sqlite3, aliases: '--sqlite', type: :boolean, default: false,
20
+ desc: 'include sqlite3 libraries'
21
+
22
+ class_option :postgresql, aliases: '--postgres', type: :boolean, default: false,
23
+ desc: 'include postgresql libraries'
24
+
25
+ class_option :mysql, type: :boolean, default: false,
26
+ desc: 'include mysql libraries'
27
+
4
28
  def generate_app
5
29
  source_paths.push File.expand_path('./templates', __dir__)
6
30
 
@@ -13,12 +37,23 @@ class DockerfileGenerator < Rails::Generators::Base
13
37
 
14
38
  template 'docker-entrypoint.erb', 'bin/docker-entrypoint'
15
39
  chmod "bin/docker-entrypoint", 0755 & ~File.umask, verbose: false
40
+
41
+ template 'docker-compose.yml.erb', 'docker-compose.yml'
16
42
  end
17
43
 
18
44
  private
19
45
 
20
46
  def using_node?
21
- File.exist? 'package.json'
47
+ return @using_node if @using_node != nil
48
+ @using_node = File.exist? 'package.json'
49
+ end
50
+
51
+ def using_redis?
52
+ options.redis? or @redis
53
+ end
54
+
55
+ def parallel?
56
+ using_node? && options.parallel
22
57
  end
23
58
 
24
59
  def keeps?
@@ -31,17 +66,22 @@ private
31
66
  packages = %w(build-essential)
32
67
 
33
68
  # add databases: sqlite3, postgres, mysql
34
- packages += %w(pkg-config libpq-dev default-libmysqlclient-dev)
69
+ packages << 'pkg-config' if options.sqlite3? or @sqlite3
70
+ packages << 'libpq-dev' if options.postgresql? or @postgresql
71
+ packages << 'default-libmysqlclient-dev' if options.mysql or @mysql
72
+
73
+ # add git if needed to install gems
74
+ packages << 'git' if @git
35
75
 
36
76
  # add redis in case Action Cable, caching, or sidekiq are added later
37
- packages << "redis"
77
+ packages << "redis" if using_redis?
38
78
 
39
79
  # ActiveStorage preview support
40
80
  packages << "libvips" if @gemfile.include? 'ruby-vips'
41
81
 
42
82
  # node support, including support for building native modules
43
83
  if using_node?
44
- packages += %w(curl node-gyp) # pkg-config already listed above
84
+ packages += %w(curl node-gyp pkg-config)
45
85
 
46
86
  # module build process depends on Python, and debian changed
47
87
  # how python is installed with the bullseye release. Below
@@ -63,15 +103,19 @@ private
63
103
  end
64
104
  end
65
105
 
66
- packages.sort
106
+ packages.sort.uniq
67
107
  end
68
108
 
69
109
  def deploy_packages
110
+ packages = []
111
+
70
112
  # start with databases: sqlite3, postgres, mysql
71
- packages = %w(libsqlite3-0 postgresql-client default-mysql-client)
113
+ packages << 'libsqlite3-0' if options.sqlite3? or @sqlite3
114
+ packages << 'postgresql-client' if options.postgresql? or @postgresql
115
+ packages << 'default-mysql-client' if options.mysql or @mysql
72
116
 
73
117
  # add redis in case Action Cable, caching, or sidekiq are added later
74
- packages << "redis"
118
+ packages << "redis" if using_redis?
75
119
 
76
120
  # ActiveStorage preview support
77
121
  packages << "libvips" if @gemfile.include? 'ruby-vips'
@@ -108,6 +152,16 @@ private
108
152
  binfixups
109
153
  end
110
154
 
155
+ def deploy_database
156
+ if options.postgresql? or @postgresql
157
+ 'postgresql'
158
+ elsif options.mysql or @mysql
159
+ 'mysql'
160
+ else
161
+ 'sqlite3'
162
+ end
163
+ end
164
+
111
165
  def node_version
112
166
  using_node? and `node --version`[/\d+\.\d+\.\d+/]
113
167
  rescue
@@ -127,4 +181,12 @@ private
127
181
  def api_only?
128
182
  Rails.application.config.api_only
129
183
  end
184
+
185
+ def dbprep_command
186
+ if Rails::VERSION::MAJOR >= 6
187
+ 'db:prepare'
188
+ else
189
+ 'db:migrate'
190
+ end
191
+ end
130
192
  end
@@ -10,16 +10,31 @@ WORKDIR /rails
10
10
  # Set production environment
11
11
  ENV RAILS_ENV="production" \
12
12
  BUNDLE_PATH="vendor/bundle" \
13
- BUNDLE_WITHOUT="development:test"
13
+ BUNDLE_WITHOUT="<%= options.ci? ? 'test' : 'development:test' %>"
14
14
 
15
+ ARG BUNDLER_VERSION=<%= Bundler::VERSION %>
16
+ RUN gem update --system --no-document && \
17
+ gem install -N bundler -v ${BUNDLER_VERSION}
15
18
 
16
- # Throw-away build stage to reduce size of final image
17
- FROM base as build
19
+
20
+ # Throw-away build stage<%= parallel? ? 's' : '' %> to reduce size of final image
21
+ FROM base as <%= parallel? ? 'pre' : '' %>build
18
22
 
19
23
  # Install packages need to build gems<%= using_node? ? " and node modules" : "" %>
24
+ <% if options.cache? %>
25
+ RUN --mount=type=cache,id=dev-apt-cache,sharing=locked,target=/var/cache/apt \
26
+ --mount=type=cache,id=dev-apt-lib,sharing=locked,target=/var/lib/apt \
27
+ apt-get update -qq && \
28
+ <% else -%>
20
29
  RUN apt-get update -qq && \
30
+ <% end -%>
21
31
  apt-get install -y <%= build_packages.join(" ") %>
22
32
 
33
+ <% if parallel? -%>
34
+
35
+ FROM prebuild as node
36
+
37
+ <% end -%>
23
38
  <% if using_node? -%>
24
39
  # Install JavaScript dependencies
25
40
  ARG NODE_VERSION=<%= node_version %>
@@ -28,15 +43,47 @@ ENV VOLTA_HOME="/usr/local"
28
43
  RUN curl https://get.volta.sh | bash && \
29
44
  volta install node@$NODE_VERSION yarn@$YARN_VERSION
30
45
 
46
+ <% end -%>
47
+ <% if parallel? -%>
48
+ # Install node modules
49
+ COPY package.json yarn.lock ./
50
+ <% if options.cache? -%>
51
+ RUN --mount=type=cache,id=bld-yarn-cache,target=/root/.yarn \
52
+ YARN_CACHE_FOLDER=/root/.yarn yarn install
53
+ <% else -%>
54
+ RUN yarn install
55
+ <% end -%>
56
+
57
+
58
+ FROM prebuild as build
59
+
31
60
  <% end -%>
32
61
  # Install application gems
33
62
  COPY Gemfile Gemfile.lock ./
34
- RUN bundle install
63
+ <% if options.cache? -%>
64
+ RUN --mount=type=cache,id=bld-gem-cache,sharing=locked,target=/srv/vendor \
65
+ bundle config set app_config .bundle && \
66
+ bundle config set path /srv/vendor && \
67
+ bundle _${BUNDLER_VERSION}_ install && \
68
+ bundle clean && \
69
+ mkdir -p vendor && \
70
+ bundle config set path vendor && \
71
+ cp -ar /srv/vendor .
72
+ <% else -%>
73
+ RUN bundle _${BUNDLER_VERSION}_ install
74
+ <% end -%>
35
75
 
36
- <% if using_node? -%>
76
+ <% if parallel? -%>
77
+ asdf
78
+ <% elsif using_node? -%>
37
79
  # Install node modules
38
80
  COPY package.json yarn.lock ./
81
+ <% if options.cache? -%>
82
+ RUN --mount=type=cache,id=bld-yarn-cache,target=/root/.yarn \
83
+ YARN_CACHE_FOLDER=/root/.yarn yarn install
84
+ <% else -%>
39
85
  RUN yarn install
86
+ <% end -%>
40
87
 
41
88
  <% end -%>
42
89
  # Copy application code
@@ -54,19 +101,31 @@ RUN bundle exec bootsnap precompile --gemfile app/ lib/
54
101
  <% end -%>
55
102
  <% unless api_only? -%>
56
103
  # Precompiling assets for production without requiring secret RAILS_MASTER_KEY
57
- RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
104
+ RUN SECRET_KEY_BASE<%= Rails::VERSION::MAJOR<7 || Rails::VERSION::STRING.start_with?('7.0') ? '=DUMMY' : '_DUMMY=1' %> ./bin/rails assets:precompile
58
105
 
59
106
  <% end -%>
60
107
 
61
108
  # Final stage for app image
62
109
  FROM base
110
+ <% unless deploy_packages.empty? -%>
63
111
 
64
112
  # Install packages need for deployment
113
+ <% if options.cache? -%>
114
+ RUN --mount=type=cache,id=dev-apt-cache,sharing=locked,target=/var/cache/apt \
115
+ --mount=type=cache,id=dev-apt-lib,sharing=locked,target=/var/lib/apt \
116
+ apt-get update -qq && \
117
+ apt-get install --no-install-recommends -y <%= deploy_packages.join(" ") %>
118
+ <% else -%>
65
119
  RUN apt-get update -qq && \
66
120
  apt-get install --no-install-recommends -y <%= deploy_packages.join(" ") %> && \
67
121
  rm -rf /var/lib/apt/lists /var/cache/apt/archives
122
+ <% end -%>
123
+ <% end -%>
68
124
 
69
125
  # Copy built application from second stage
126
+ <% if options.ci? -%>
127
+ COPY --from=build /usr/local/bundle /usr/local/bundle
128
+ <% end -%>
70
129
  COPY --from=build /rails /rails
71
130
 
72
131
  # Deployment options
@@ -0,0 +1,71 @@
1
+ version: "3.8"
2
+ services:
3
+ web:
4
+ build: .
5
+ ports:
6
+ - "3000:3000"
7
+ environment:
8
+ - RAILS_MASTER_KEY=$RAILS_MASTER_KEY
9
+ <% if using_redis? -%>
10
+ - REDIS_URL=redis://redis-db:6379
11
+ <% end -%>
12
+ <% if deploy_database == 'postgresql' -%>
13
+ - DATABASE_URL=postgres://root:password@postgres-db/
14
+ <% elsif deploy_database == 'mysql' -%>
15
+ - DATABASE_URL=mysql2://root:password@mysql-db/
16
+ <% end -%>
17
+ <% if deploy_database == 'sqlite3' -%>
18
+ volumes:
19
+ - ./db:/rails/db
20
+ <% end -%>
21
+ <% if using_redis? or deploy_database != 'sqlite3' -%>
22
+ depends_on:
23
+ <% if using_redis? -%>
24
+ redis-db:
25
+ condition: service_started
26
+ <% end -%>
27
+ <% if deploy_database == 'postgresql' -%>
28
+ postgres-db:
29
+ condition: service_healthy
30
+ <% elsif deploy_database == 'mysql' -%>
31
+ mysql-db:
32
+ condition: service_healthy
33
+ <% end -%>
34
+ <% if deploy_database == 'postgresql' -%>
35
+
36
+ postgres-db:
37
+ image: postgres
38
+ environment:
39
+ POSTGRES_USER: root
40
+ POSTGRES_PASSWORD: password
41
+ volumes:
42
+ - ./tmp/db:/var/lib/postgresql/data
43
+ ports:
44
+ - "5432:5432"
45
+ healthcheck:
46
+ test: pg_isready
47
+ interval: 2s
48
+ timeout: 5s
49
+ retries: 30
50
+ <% elsif deploy_database == 'mysql' -%>
51
+
52
+ mysql-db:
53
+ image: mysql
54
+ command:
55
+ - --default-authentication-plugin=mysql_native_password
56
+ environment:
57
+ MYSQL_ROOT_PASSWORD: password
58
+ volumes:
59
+ - ./tmp/db:/var/lib/mysql
60
+ healthcheck:
61
+ test: mysqladmin ping -h 127.0.0.1 -u root --password=password
62
+ interval: 2s
63
+ timeout: 5s
64
+ retries: 30
65
+ <% end -%>
66
+ <% end -%>
67
+ <% if using_redis? -%>
68
+
69
+ redis-db:
70
+ image: redis
71
+ <% end -%>
@@ -2,7 +2,7 @@
2
2
 
3
3
  # If running the rails server then create or migrate existing database
4
4
  if [ "${*}" == "./bin/rails server" ]; then
5
- ./bin/rails db:prepare
5
+ ./bin/rails <%= dbprep_command %>
6
6
  fi
7
7
 
8
8
  exec "${@}"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dockerfile-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Ruby
@@ -37,6 +37,7 @@ files:
37
37
  - lib/dockerfile-rails/scanner.rb
38
38
  - lib/generators/dockerfile_generator.rb
39
39
  - lib/generators/templates/Dockerfile.erb
40
+ - lib/generators/templates/docker-compose.yml.erb
40
41
  - lib/generators/templates/docker-entrypoint.erb
41
42
  - lib/generators/templates/dockerignore.erb
42
43
  - lib/generators/templates/node-version.erb