dockerfile-rails 0.0.1 → 0.1.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: 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