Merge pull request #51063 from anonychun/speedup-docker-build-time
Speedup Docker Build Time
This commit is contained in:
commit
f8ffd46ccc
@ -561,6 +561,22 @@ def dockerfile_binfile_fixups
|
||||
binfixups
|
||||
end
|
||||
|
||||
def dockerfile_base_packages
|
||||
# Add curl to work with the default healthcheck strategy in Kamal
|
||||
packages = ["curl"]
|
||||
|
||||
# ActiveRecord databases
|
||||
packages << base_package_for_database unless skip_active_record?
|
||||
|
||||
# ActiveStorage preview support
|
||||
packages << "libvips" unless skip_active_storage?
|
||||
|
||||
# jemalloc for memory optimization
|
||||
packages << "libjemalloc2"
|
||||
|
||||
packages.compact.sort
|
||||
end
|
||||
|
||||
def dockerfile_build_packages
|
||||
# start with the essentials
|
||||
packages = %w(build-essential git pkg-config)
|
||||
@ -568,11 +584,6 @@ def dockerfile_build_packages
|
||||
# add database support
|
||||
packages << build_package_for_database unless skip_active_record?
|
||||
|
||||
# ActiveStorage preview support
|
||||
packages << "libvips" unless skip_active_storage?
|
||||
|
||||
packages << "curl" if using_js_runtime?
|
||||
|
||||
packages << "unzip" if using_bun?
|
||||
|
||||
# node support, including support for building native modules
|
||||
@ -585,22 +596,6 @@ def dockerfile_build_packages
|
||||
packages.compact.sort
|
||||
end
|
||||
|
||||
def dockerfile_deploy_packages
|
||||
# Add curl to work with the default healthcheck strategy in Kamal
|
||||
packages = ["curl"]
|
||||
|
||||
# ActiveRecord databases
|
||||
packages << deploy_package_for_database unless skip_active_record?
|
||||
|
||||
# ActiveStorage preview support
|
||||
packages << "libvips" unless skip_active_storage?
|
||||
|
||||
# jemalloc for memory optimization
|
||||
packages << "libjemalloc2"
|
||||
|
||||
packages.compact.sort
|
||||
end
|
||||
|
||||
def css_gemfile_entry
|
||||
return if options[:api]
|
||||
return unless options[:css]
|
||||
|
@ -27,6 +27,16 @@ def gem_for_database(database = options[:database])
|
||||
end
|
||||
end
|
||||
|
||||
def docker_for_database_base(database = options[:database])
|
||||
case database
|
||||
when "mysql" then "curl default-mysql-client libvips"
|
||||
when "trilogy" then "curl libvips"
|
||||
when "postgresql" then "curl libvips postgresql-client"
|
||||
when "sqlite3" then "curl libsqlite3-0 libvips"
|
||||
else nil
|
||||
end
|
||||
end
|
||||
|
||||
def docker_for_database_build(database = options[:database])
|
||||
case database
|
||||
when "mysql" then "build-essential default-libmysqlclient-dev git"
|
||||
@ -37,16 +47,6 @@ def docker_for_database_build(database = options[:database])
|
||||
end
|
||||
end
|
||||
|
||||
def docker_for_database_deploy(database = options[:database])
|
||||
case database
|
||||
when "mysql" then "curl default-mysql-client libvips"
|
||||
when "trilogy" then "curl libvips"
|
||||
when "postgresql" then "curl libvips postgresql-client"
|
||||
when "sqlite3" then "curl libsqlite3-0 libvips"
|
||||
else nil
|
||||
end
|
||||
end
|
||||
|
||||
def convert_database_option_for_jruby
|
||||
if defined?(JRUBY_VERSION)
|
||||
opt = options.dup
|
||||
@ -59,15 +59,7 @@ def convert_database_option_for_jruby
|
||||
end
|
||||
end
|
||||
|
||||
def build_package_for_database(database = options[:database])
|
||||
case database
|
||||
when "mysql" then "default-libmysqlclient-dev"
|
||||
when "postgresql" then "libpq-dev"
|
||||
else nil
|
||||
end
|
||||
end
|
||||
|
||||
def deploy_package_for_database(database = options[:database])
|
||||
def base_package_for_database(database = options[:database])
|
||||
case database
|
||||
when "mysql" then "default-mysql-client"
|
||||
when "postgresql" then "postgresql-client"
|
||||
@ -76,6 +68,14 @@ def deploy_package_for_database(database = options[:database])
|
||||
end
|
||||
end
|
||||
|
||||
def build_package_for_database(database = options[:database])
|
||||
case database
|
||||
when "mysql" then "default-libmysqlclient-dev"
|
||||
when "postgresql" then "libpq-dev"
|
||||
else nil
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def mysql_socket
|
||||
@mysql_socket ||= [
|
||||
|
@ -7,19 +7,21 @@ FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base
|
||||
# Rails app lives here
|
||||
WORKDIR /rails
|
||||
|
||||
# Install base packages
|
||||
RUN apt-get update -qq && \
|
||||
apt-get install --no-install-recommends -y <%= dockerfile_base_packages.join(" ") %>
|
||||
|
||||
# Set production environment
|
||||
ENV RAILS_ENV="production" \
|
||||
BUNDLE_DEPLOYMENT="1" \
|
||||
BUNDLE_PATH="/usr/local/bundle" \
|
||||
BUNDLE_WITHOUT="development"
|
||||
|
||||
|
||||
# Throw-away build stage to reduce size of final image
|
||||
FROM base as build
|
||||
|
||||
# Install packages needed to build gems<%= using_node? ? " and node modules" : "" %>
|
||||
RUN apt-get update -qq && \
|
||||
apt-get install --no-install-recommends -y <%= dockerfile_build_packages.join(" ") %>
|
||||
RUN apt-get install --no-install-recommends -y <%= dockerfile_build_packages.join(" ") %>
|
||||
|
||||
<% if using_node? -%>
|
||||
# Install JavaScript dependencies
|
||||
@ -79,13 +81,9 @@ RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
|
||||
# Final stage for app image
|
||||
FROM base
|
||||
|
||||
<% unless dockerfile_deploy_packages.empty? -%>
|
||||
# Install packages needed for deployment
|
||||
RUN apt-get update -qq && \
|
||||
apt-get install --no-install-recommends -y <%= dockerfile_deploy_packages.join(" ") %> && \
|
||||
rm -rf /var/lib/apt/lists /var/cache/apt/archives
|
||||
# Clean up installation packages to reduce image size
|
||||
RUN rm -rf /var/lib/apt/lists /var/cache/apt/archives
|
||||
|
||||
<% end -%>
|
||||
# Copy built artifacts: gems, application
|
||||
COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
|
||||
COPY --from=build /rails /rails
|
||||
|
@ -99,7 +99,7 @@ jobs:
|
||||
<%- end -%>
|
||||
steps:
|
||||
- name: Install packages
|
||||
run: sudo apt-get update && sudo apt-get install --no-install-recommends -y google-chrome-stable <%= (dockerfile_deploy_packages + [build_package_for_database]).join(" ") %>
|
||||
run: sudo apt-get update && sudo apt-get install --no-install-recommends -y google-chrome-stable <%= (dockerfile_base_packages + [build_package_for_database]).join(" ") %>
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
@ -44,14 +44,14 @@ def edit_dockerfile
|
||||
dockerfile_path = File.expand_path("Dockerfile", destination_root)
|
||||
return unless File.exist?(dockerfile_path)
|
||||
|
||||
base_name = docker_for_database_base
|
||||
build_name = docker_for_database_build
|
||||
deploy_name = docker_for_database_deploy
|
||||
if base_name
|
||||
gsub_file("Dockerfile", all_docker_bases_regex, base_name)
|
||||
end
|
||||
if build_name
|
||||
gsub_file("Dockerfile", all_docker_builds_regex, build_name)
|
||||
end
|
||||
if deploy_name
|
||||
gsub_file("Dockerfile", all_docker_deploys_regex, deploy_name)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
@ -59,12 +59,12 @@ def all_database_gems
|
||||
DATABASES.map { |database| gem_for_database(database) }
|
||||
end
|
||||
|
||||
def all_docker_builds
|
||||
DATABASES.map { |database| docker_for_database_build(database).nil? ? nil : docker_for_database_build(database) }.compact!
|
||||
def all_docker_bases
|
||||
DATABASES.map { |database| docker_for_database_base(database).nil? ? nil : docker_for_database_base(database) }.compact!
|
||||
end
|
||||
|
||||
def all_docker_deploys
|
||||
DATABASES.map { |database| docker_for_database_deploy(database).nil? ? nil : docker_for_database_deploy(database) }.compact!
|
||||
def all_docker_builds
|
||||
DATABASES.map { |database| docker_for_database_build(database).nil? ? nil : docker_for_database_build(database) }.compact!
|
||||
end
|
||||
|
||||
def all_database_gems_regex
|
||||
@ -72,12 +72,12 @@ def all_database_gems_regex
|
||||
/(\b#{all_database_gem_names.join('\b|\b')}\b)/
|
||||
end
|
||||
|
||||
def all_docker_builds_regex
|
||||
/(\b#{all_docker_builds.join('\b|\b')}\b)/
|
||||
def all_docker_bases_regex
|
||||
/(\b#{all_docker_bases.join('\b|\b')}\b)/
|
||||
end
|
||||
|
||||
def all_docker_deploys_regex
|
||||
/(\b#{all_docker_deploys.join('\b|\b')}\b)/
|
||||
def all_docker_builds_regex
|
||||
/(\b#{all_docker_builds.join('\b|\b')}\b)/
|
||||
end
|
||||
|
||||
def gem_entry_regex_for(gem_name)
|
||||
|
19
railties/test/fixtures/Dockerfile.test
vendored
19
railties/test/fixtures/Dockerfile.test
vendored
@ -7,21 +7,21 @@ FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base
|
||||
# Rails app lives here
|
||||
WORKDIR /rails
|
||||
|
||||
# Install base packages
|
||||
RUN apt-get update -qq && \
|
||||
apt-get install --no-install-recommends -y curl libsqlite3-0 libvips
|
||||
|
||||
# Set production environment
|
||||
ENV RAILS_ENV="production" \
|
||||
BUNDLE_DEPLOYMENT="1" \
|
||||
BUNDLE_PATH="/usr/local/bundle" \
|
||||
BUNDLE_WITHOUT="development"
|
||||
|
||||
|
||||
# Throw-away build stage to reduce size of final image
|
||||
FROM base as build
|
||||
|
||||
# Install packages needed to build gems
|
||||
RUN apt-get update -qq && \
|
||||
apt-get install --no-install-recommends -y build-essential git libvips pkg-config
|
||||
|
||||
|
||||
RUN apt-get install --no-install-recommends -y build-essential git pkg-config
|
||||
|
||||
# Install application gems
|
||||
COPY Gemfile Gemfile.lock ./
|
||||
@ -29,8 +29,6 @@ RUN bundle install && \
|
||||
rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \
|
||||
bundle exec bootsnap precompile --gemfile
|
||||
|
||||
|
||||
|
||||
# Copy application code
|
||||
COPY . .
|
||||
|
||||
@ -40,14 +38,11 @@ RUN bundle exec bootsnap precompile app/ lib/
|
||||
# Precompiling assets for production without requiring secret RAILS_MASTER_KEY
|
||||
RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
|
||||
|
||||
|
||||
# Final stage for app image
|
||||
FROM base
|
||||
|
||||
# Install packages needed for deployment
|
||||
RUN apt-get update -qq && \
|
||||
apt-get install --no-install-recommends -y curl libsqlite3-0 libvips && \
|
||||
rm -rf /var/lib/apt/lists /var/cache/apt/archives
|
||||
# Clean up installation packages to reduce image size
|
||||
RUN rm -rf /var/lib/apt/lists /var/cache/apt/archives
|
||||
|
||||
# Copy built artifacts: gems, application
|
||||
COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
|
||||
|
@ -85,7 +85,7 @@ class ChangeGeneratorTest < Rails::Generators::TestCase
|
||||
end
|
||||
|
||||
assert_file("Dockerfile") do |content|
|
||||
assert_match "build-essential git libvips", content
|
||||
assert_match "build-essential git", content
|
||||
assert_match "curl libsqlite3-0 libvips", content
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user