From 2f10fb7a96e70051b5a2cf1e0dbdc625449fbf98 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Wed, 4 Sep 2024 10:59:57 -0600 Subject: [PATCH] Slim down contracts-bedrock package (#11723) * Slim down contracts-bedrock package The contracts-bedrock package was over 2GB in size, mostly because it contained the Git repository. It also supported multiple platforms, which would lead to costly recompilation steps every time the image was used on a different platform (e.g., OSX). The PR updates the Dockerfile to no longer ship the Git repo. It also updates the Debian base image to a more modern, slimmed down version. The new image is <1G in size. * fix bakefile --- docker-bake.hcl | 3 +- ops/docker/Dockerfile.packages | 57 +++++++++++++------ .../scripts/libraries/Executables.sol | 8 ++- 3 files changed, 49 insertions(+), 19 deletions(-) diff --git a/docker-bake.hcl b/docker-bake.hcl index d57ab76e7e62..47509616416a 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -219,6 +219,7 @@ target "contracts-bedrock" { dockerfile = "./ops/docker/Dockerfile.packages" context = "." target = "contracts-bedrock" - platforms = split(",", PLATFORMS) + # See comment in Dockerfile.packages for why we only build for linux/amd64. + platforms = ["linux/amd64"] tags = [for tag in split(",", IMAGE_TAGS) : "${REGISTRY}/${REPOSITORY}/contracts-bedrock:${tag}"] } diff --git a/ops/docker/Dockerfile.packages b/ops/docker/Dockerfile.packages index 598f40b3e3bb..f4f110244f5f 100644 --- a/ops/docker/Dockerfile.packages +++ b/ops/docker/Dockerfile.packages @@ -1,11 +1,12 @@ +# We need to specify the platforms below, otherwise platforms other than +# linux/amd64 will be forced to rebuild the contracts every time this +# image is used. + # This Dockerfile builds all the dependencies needed by the smart-contracts, excluding Go and Python. -FROM us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest as foundry +FROM --platform=linux/amd64 us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest as foundry -# Historically the contracts-bedrock was on the node image based on Debian 11 (bullseye), -# for Node / PNPM compatibility reasons. -# We no longer use Node JS, but continue to use the same Debian version for compatibility. -FROM debian:bullseye-slim as base +FROM --platform=linux/amd64 debian:bookworm-20240812-slim as base # Base: install deps RUN apt-get update && apt-get install -y \ @@ -17,13 +18,7 @@ RUN apt-get update && apt-get install -y \ bash \ --no-install-recommends -COPY /ops/docker/oplabs.crt /usr/local/share/ca-certificates/oplabs.crt -RUN chmod 644 /usr/local/share/ca-certificates/oplabs.crt \ - && update-ca-certificates - -# Note: "just" is only available on Debian 13. Instead, pull it from the foundry image. COPY --from=foundry /usr/local/bin/just /usr/local/bin/just - COPY --from=foundry /usr/local/bin/forge /usr/local/bin/forge COPY --from=foundry /usr/local/bin/cast /usr/local/bin/cast @@ -31,18 +26,48 @@ WORKDIR /opt/optimism COPY ./versions.json ./versions.json COPY ./packages ./packages - COPY .git/ ./.git COPY .gitmodules ./.gitmodules -RUN git submodule update --init --recursive + +RUN git submodule update --init --recursive \ + && cd packages/contracts-bedrock \ + && just build \ + && echo $(git rev-parse HEAD) > .gitcommit + +FROM --platform=linux/amd64 debian:bookworm-20240812-slim + +RUN apt-get update && apt-get install -y \ + curl \ + jq \ + ca-certificates \ + git \ + make \ + bash \ + --no-install-recommends + +COPY /ops/docker/oplabs.crt /usr/local/share/ca-certificates/oplabs.crt + +RUN chmod 644 /usr/local/share/ca-certificates/oplabs.crt \ + && update-ca-certificates + +COPY --from=foundry /usr/local/bin/just /usr/local/bin/just +COPY --from=foundry /usr/local/bin/forge /usr/local/bin/forge +COPY --from=foundry /usr/local/bin/cast /usr/local/bin/cast +COPY --from=foundry /usr/local/bin/svm /usr/local/bin/svm + +RUN svm install 0.8.25 && \ + svm install 0.8.15 && \ + svm install 0.8.19 && \ + svm install 0.8.26 # Not to be confused with OP, this is a OnePassword CLI tool. COPY --from=1password/op:2 /usr/local/bin/op /usr/local/bin/op -# prebuild the smart-contracts for the convenience of the user -RUN cd packages/contracts-bedrock && just build +RUN mkdir -p /opt/optimism/packages/contracts-bedrock + +COPY --from=base /opt/optimism/packages/contracts-bedrock /opt/optimism/packages/contracts-bedrock +COPY --from=base /opt/optimism/versions.json /opt/optimism/versions.json -FROM base as contracts-bedrock WORKDIR /opt/optimism/packages/contracts-bedrock # Set "just" as entrypoint, so the default args (the Dockerfile CMD) diff --git a/packages/contracts-bedrock/scripts/libraries/Executables.sol b/packages/contracts-bedrock/scripts/libraries/Executables.sol index 31f81da71ee5..0dc91e32072d 100644 --- a/packages/contracts-bedrock/scripts/libraries/Executables.sol +++ b/packages/contracts-bedrock/scripts/libraries/Executables.sol @@ -19,12 +19,16 @@ library Executables { string internal constant ls = "ls"; string internal constant git = "git"; - /// @notice Returns the commit hash of HEAD. + /// @notice Returns the commit hash of HEAD. If no git repository is + /// found, it will return the contents of the .gitcommit file. Otherwise, + /// it will return an error. The .gitcommit file is used to store the + /// git commit of the contracts when they are packaged into docker images + /// in order to avoid the need to have a git repository in the image. function gitCommitHash() internal returns (string memory) { string[] memory commands = new string[](3); commands[0] = bash; commands[1] = "-c"; - commands[2] = "cast abi-encode 'f(string)' $(git rev-parse HEAD)"; + commands[2] = "cast abi-encode 'f(string)' $(git rev-parse HEAD || cat .gitcommit)"; return abi.decode(Process.run(commands), (string)); } }