lib/generators/dockerfile_generator.rb in dockerfile-rails-1.5.14 vs lib/generators/dockerfile_generator.rb in dockerfile-rails-1.6.0

- old
+ new

@@ -6,10 +6,11 @@ class DockerfileGenerator < Rails::Generators::Base include DockerfileRails::Scanner BASE_DEFAULTS = { + "alpine" => false, "bin-cd" => false, "cache" => false, "ci" => false, "compose" => false, "fullstaq" => false, @@ -37,11 +38,11 @@ "sqlite3" => false, "sqlserver" => false, "sentry" => false, "sudo" => false, "swap" => nil, - "variant" => "slim", + "variant" => nil, "windows" => false, "yjit" => false, }.yield_self { |hash| Struct.new(*hash.keys.map(&:to_sym)).new(*hash.values) } OPTION_DEFAULTS = BASE_DEFAULTS.dup @@ -50,10 +51,29 @@ @@packages = { "base" => [], "build" => [], "deploy" => [] } @@vars = { "base" => {}, "build" => {}, "deploy" => {} } @@args = { "base" => {}, "build" => {}, "deploy" => {} } @@instructions = { "base" => nil, "build" => nil, "deploy" => nil } + ALPINE_MAPPINGS = { + "build-essential" => "build-base", + "chromium-sandbox" => "chromium-chromedriver", + "default-libmysqlclient-dev" => "mysql-client", + "default-mysqlclient" => "mysql-client", + "freedts-bin" => "freedts", + "libicu-dev" => "icu-dev", + "libjemalloc" => "jemalloc-dev", + "libjpeg-dev" => "jpeg-dev", + "libmagickwand-dev" => "imagemagick-libs", + "libsqlite3-0" => "sqlite-dev", + "libtiff-dev" => "tiff-dev", + "libvips" => "vips-dev", + "node-gyp" => "gyp", + "pkg-config" => "pkgconfig", + "python" => "python3", + "python-is-python3" => "python3" + } + # load defaults from config file if File.exist? "config/dockerfile.yml" options = YAML.safe_load(IO.read("config/dockerfile.yml"), symbolize_names: true)[:options] if options @@ -144,10 +164,13 @@ desc: "image platform (example: linux/arm64)" class_option :registry, type: :string, default: OPTION_DEFAULTS.registry, desc: "docker registry to use (example: registry.docker.com/library/)" + class_option :alpine, type: :boolean, default: OPTION_DEFAULTS.alpine, + descr: "use alpine image" + class_option :variant, type: :string, default: OPTION_DEFAULTS.variant, desc: "dockerhub image variant (example: slim-bullseye)" class_option :jemalloc, type: :boolean, default: OPTION_DEFAULTS.jemalloc, desc: "use jemalloc alternative malloc implementation" @@ -372,10 +395,14 @@ else "" end end + def variant + options.variant || (options.alpine ? "alpine" : "slim") + end + def run_as_root? options.root? end def using_litefs? @@ -514,10 +541,14 @@ end gems.sort end + def alpinize(packages) + packages.map { |package| ALPINE_MAPPINGS[package] || package }.sort.uniq + end + def base_packages packages = [] packages += @@packages["base"] if @@packages["base"] if using_execjs? @@ -542,11 +573,17 @@ end # Passenger packages << "passenger" if using_passenger? - packages.sort.uniq + if options.alpine? + packages << "tzdata" + + alpinize(packages) + else + packages.sort.uniq + end end def base_requirements requirements = [] requirements << "nodejs" if using_execjs? @@ -608,11 +645,15 @@ else packages << "python" end end - packages.sort.uniq + if options.alpine? + alpinize(packages) + else + packages.sort.uniq + end end def deploy_packages packages = %w(curl) # work with the default healthcheck strategy in MRSK packages += @@packages["deploy"] if @@packages["deploy"] @@ -657,13 +698,52 @@ if !options.procfile.blank? || (procfile.size > 1) packages << "ruby-foreman" end - packages.sort + if options.alpine? + packages << "sqlite-libs" if @gemfile.include? "sqlite3" + packages << "libpq" if @gemfile.include? "pg" + + alpinize(packages) + else + packages.sort.uniq + end end + def pkg_update + if options.alpine? + "apk update" + else + "apt-get update -qq" + end + end + + def pkg_install + if options.alpine? + "apk add" + else + "apt-get install --no-install-recommends -y" + end + end + + def pkg_cache + if options.alpine? + { "dev-apk-cache" => "/var/cache/apk" } + else + { "dev-apt-cache" => "/var/cache/apt", "dev-apt-lib" => "/var/lib/apt" } + end + end + + def pkg_cleanup + if options.alpine? + "/var/cache/apk/*" + else + "/var/lib/apt/lists /var/cache/apt/archives" + end + end + def base_repos repos = [] packages = [] if using_passenger? @@ -678,12 +758,12 @@ if repos.empty? "" else packages.sort!.uniq! unless packages.empty? - repos.unshift "apt-get update -qq &&", - "apt-get install --no-install-recommends -y #{packages.join(" ")} &&" + repos.unshift "#{pkg_update} &&", + "#{pkg_install} #{packages.join(" ")} &&" end repos.join(" \\\n ") + " && \\\n " end end @@ -704,21 +784,22 @@ if repos.empty? "" else packages.sort!.uniq! unless packages.empty? - repos.unshift "apt-get update -qq &&", - "apt-get install --no-install-recommends -y #{packages.join(" ")} &&" + repos.unshift "#{pkg_update} &&", + "#{pkg_install} --no-install-recommends -y #{packages.join(" ")} &&" end repos.join(" \\\n ") + " && \\\n " end end def base_env env = { "RAILS_ENV" => "production", + "BUNDLE_PATH" => "/usr/local/bundle", "BUNDLE_WITHOUT" => options.ci? ? "development" : "development:test" } if options.lock? env["BUNDLE_DEPLOYMENT"] = "1" @@ -732,10 +813,10 @@ env.merge! @@args["base"].to_h { |key, value| [key, "$#{key}"] } end env.merge! @@vars["base"] if @@vars["base"] - env.map { |key, value| "#{key}=#{value.inspect}" } + env.map { |key, value| "#{key}=#{value.inspect}" }.sort end def build_env env = {}