Skip to content

Commit 520d073

Browse files
authored
optimize docker image layers (#4271)
## Description [Adding/fixing caching of Gradle wrapper](#4270) to our build image increased it's size beyond 2GB. We started seeing issues with dry run release and download artifact [silently failing](actions/download-artifact#396). This PR attempts to optimize the image layers to reduce it's overall size and hopefully work past these issues. ### Key Optimizations Multi-stage consolidation: • Combined all cargo tool installations into a single `cargo_tools` stage instead of separate stages per tool • Created dedicated `gradle_wrapper` stage that reuses install_rust base to avoid duplicating Java installation Layer reduction: • Combined RUN commands with cleanup operations (yum clean all && rm -rf /var/cache/yum) • Added cargo cache cleanup (rm -rf /opt/cargo/registry/src && rm -rf /opt/cargo/git/db) after installations • Consolidated AWS CLI installation and cleanup in single layer Gradle wrapper optimization: • Removed checkout_smithy_rs_tools conditional logic - now always fetches gradle wrapper • Uses sparse checkout to fetch only required files (gradlew, gradle/wrapper, gradle.properties) Before and after: ``` > finch images REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE smithy-rs-build-image latest 449b886b6045 2 days ago linux/arm64 6.663GB 2.223GB smithy-rs-base-image local 2c1a924209b3 2 days ago linux/arm64 6.663GB 2.223GB smithy-rs-base-image ci-d4053cbdd4e82adff099eb2f4e6cbaae2139d577 2c1a924209b3 2 days ago linux/arm64 6.663GB 2.223GB ghcr.io/github/github-mcp-server latest 9cd2504664e1 2 months ago linux/arm64 46.25MB 13.08MB todaaron at 842f577d1917 in ~/sandbox/rs/smithy-rs on aajtodd/optimize-dockerfile ✗ [91e76ab] 10:22 > finch images REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE smithy-rs-base-image local 811268820b1a 48 seconds ago linux/arm64 4.57GB 1.564GB smithy-rs-base-image ci-ea6828b430e9f84941104db55cb6d58d201ad145 811268820b1a 59 seconds ago linux/arm64 4.57GB 1.564GB smithy-rs-build-image latest b66608bb54c3 3 days ago linux/arm64 4.571GB 1.564GB smithy-rs-base-image ci-d4053cbdd4e82adff099eb2f4e6cbaae2139d577 2c1a924209b3 3 days ago linux/arm64 6.663GB 2.223GB ghcr.io/github/github-mcp-server latest 9cd2504664e1 2 months ago linux/arm64 46.25MB 13.08MB ``` ---- _By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice._
1 parent 91e76ab commit 520d073

File tree

2 files changed

+93
-84
lines changed

2 files changed

+93
-84
lines changed

aws/rust-runtime/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tools/ci-build/Dockerfile

Lines changed: 92 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@ ARG rust_stable_version=1.86.0
1010
ARG rust_nightly_version=nightly-2025-05-04
1111

1212
FROM ${base_image} AS bare_base_image
13-
RUN yum -y updateinfo
13+
RUN yum -y updateinfo && yum clean all && rm -rf /var/cache/yum
1414

1515
FROM bare_base_image as musl_toolchain
16-
RUN yum -y install --allowerasing tar gzip gcc make
17-
RUN curl https://musl.libc.org/releases/musl-1.2.5.tar.gz -o musl-1.2.5.tar.gz \
18-
&& ls \
19-
&& tar xvzf musl-1.2.5.tar.gz \
20-
&& (cd musl-1.2.5 && ./configure && make install)
16+
RUN yum -y install --allowerasing tar gzip gcc make && \
17+
curl https://musl.libc.org/releases/musl-1.2.5.tar.gz -o musl-1.2.5.tar.gz && \
18+
tar xzf musl-1.2.5.tar.gz && \
19+
(cd musl-1.2.5 && ./configure && make install) && \
20+
rm -rf musl-1.2.5* && \
21+
yum clean all && rm -rf /var/cache/yum
2122

2223
#
2324
# Rust & Tools Installation Stage
@@ -66,8 +67,8 @@ RUN yum -y install --allowerasing \
6667
pkgconfig \
6768
tar \
6869
xz && \
69-
yum clean all
70-
RUN set -eux; \
70+
yum clean all && rm -rf /var/cache/yum && \
71+
set -eux; \
7172
if [[ "$(uname -m)" == "aarch64" || "$(uname -m)" == "arm64" ]]; then \
7273
curl https://static.rust-lang.org/rustup/archive/1.24.3/aarch64-unknown-linux-gnu/rustup-init --output rustup-init; \
7374
echo "32a1532f7cef072a667bac53f1a5542c99666c4071af0c9549795bbdb2069ec1 rustup-init" | sha256sum --check; \
@@ -88,64 +89,67 @@ RUN set -eux; \
8889
cargo --version; \
8990
cargo +${rust_nightly_version} --version;
9091

91-
FROM install_rust AS local_tools
92-
ARG rust_nightly_version
93-
ENV GRADLE_USER_HOME=/home/build/.gradle
94-
COPY . tools/ci-build
95-
# when `checkout_smithy_rs_tools` is set to true, this commit will be checked out
92+
FROM install_rust AS gradle_wrapper
93+
# Commit/branch to checkout for gradle wrapper
9694
ARG smithy_rs_commit_hash=main
97-
# If the `checkout_smithy_rs_tools` arg is set to true, then the Dockerfile will acquire the tools
98-
# source code by checking out smithy-lang/smithy-rs/main rather than copying them from the local directory.
99-
# If it is false we still clone the smithy-rs repo beecause we need the gradle wrapper to install the gradle
100-
# binary. But in this case we delete the repo before installing the tools and use the local versions from
101-
# the build context.
102-
ARG checkout_smithy_rs_tools=false
95+
ENV GRADLE_USER_HOME=/opt/gradle
96+
WORKDIR /opt/gradle
10397
RUN set -eux; \
104-
git clone https://github.com/smithy-lang/smithy-rs.git --depth 1; \
105-
cd smithy-rs; \
106-
if [[ "${checkout_smithy_rs_tools}" == "true" ]]; then \
107-
git checkout ${smithy_rs_commit_hash}; \
108-
else \
109-
# Run the gradle wrapper with no args to download the gradle binary and cache it in the image
110-
./gradlew; \
111-
cd ..; \
112-
rm -rf smithy-rs; \
113-
fi; \
114-
cargo install --locked --path tools/ci-build/changelogger; \
115-
cargo install --locked --path tools/ci-build/crate-hasher; \
116-
cargo install --locked --path tools/ci-build/difftags; \
117-
cargo install --locked --path tools/ci-build/publisher; \
118-
cargo install --locked --path tools/ci-build/runtime-versioner; \
119-
cargo install --locked --path tools/ci-build/sdk-lints; \
120-
cargo install --locked --path tools/ci-build/sdk-lockfiles; \
121-
cargo install --locked --path tools/ci-build/sdk-versioner; \
122-
chmod g+rw -R /opt/cargo/registry
98+
source /etc/profile.d/java_home.sh; \
99+
git init smithy-rs && cd smithy-rs; \
100+
git remote add origin https://github.com/smithy-lang/smithy-rs.git; \
101+
git sparse-checkout init --cone; \
102+
git sparse-checkout set gradlew gradle/wrapper gradle.properties; \
103+
git fetch --depth=1 origin ${smithy_rs_commit_hash}; \
104+
git checkout FETCH_HEAD; \
105+
# Run the gradle wrapper with no args to download the gradle binary and cache it in the image
106+
./gradlew; \
107+
cd ..; \
108+
rm -rf smithy-rs
123109

124-
ARG cargo_deny_version=0.16.4 \
125-
cargo_udeps_version=0.1.56 \
126-
cargo_hack_version=0.6.27 \
127-
cargo_minimal_versions_version=0.1.27 \
128-
cargo_check_external_types_version=0.2.0 \
129-
maturin_version=1.5.1 \
130-
wasm_pack_version=0.13.1 \
131-
cargo_wasmtime_version=34.0.1 \
132-
cargo_component_version=0.20.0 \
133-
cargo_semver_checks_version=0.41.0 \
134-
cargo_mdbook_version=0.4.37 \
135-
cargo_mdbook_mermaid_version=0.13.0
110+
FROM install_rust AS local_tools
111+
ARG rust_nightly_version
112+
COPY . tools/ci-build
113+
RUN cargo install --locked --path tools/ci-build/changelogger && \
114+
cargo install --locked --path tools/ci-build/crate-hasher && \
115+
cargo install --locked --path tools/ci-build/difftags && \
116+
cargo install --locked --path tools/ci-build/publisher && \
117+
cargo install --locked --path tools/ci-build/runtime-versioner && \
118+
cargo install --locked --path tools/ci-build/sdk-lints && \
119+
cargo install --locked --path tools/ci-build/sdk-lockfiles && \
120+
cargo install --locked --path tools/ci-build/sdk-versioner && \
121+
chmod g+rw -R /opt/cargo/registry && \
122+
rm -rf /opt/cargo/registry/src && \
123+
rm -rf /opt/cargo/git/db
136124

137-
RUN cargo install cargo-deny --locked --version ${cargo_deny_version} \
138-
&& cargo +${rust_nightly_version} install cargo-udeps --locked --version ${cargo_udeps_version} \
139-
&& cargo install cargo-hack --locked --version ${cargo_hack_version} \
140-
&& cargo install cargo-minimal-versions --locked --version ${cargo_minimal_versions_version} \
141-
&& cargo install cargo-check-external-types --locked --version ${cargo_check_external_types_version} \
142-
&& cargo install maturin --locked --version ${maturin_version} \
143-
&& cargo install wasm-pack --locked --version ${wasm_pack_version} \
144-
&& cargo install wasmtime-cli --features="component-model" --locked --version ${cargo_wasmtime_version} \
145-
&& cargo +${rust_nightly_version} install cargo-component --locked --version ${cargo_component_version} \
146-
&& cargo install cargo-semver-checks --locked --version ${cargo_semver_checks_version} \
147-
&& cargo install mdbook --locked --version ${cargo_mdbook_version} \
148-
&& cargo install mdbook-mermaid --locked --version ${cargo_mdbook_mermaid_version}
125+
FROM install_rust AS cargo_tools
126+
ARG cargo_deny_version=0.16.4
127+
ARG cargo_udeps_version=0.1.56
128+
ARG cargo_hack_version=0.6.27
129+
ARG cargo_minimal_versions_version=0.1.27
130+
ARG cargo_check_external_types_version=0.2.0
131+
ARG maturin_version=1.5.1
132+
ARG wasm_pack_version=0.13.1
133+
ARG cargo_wasmtime_version=34.0.1
134+
ARG cargo_component_version=0.20.0
135+
ARG cargo_semver_checks_version=0.41.0
136+
ARG cargo_mdbook_version=0.4.37
137+
ARG cargo_mdbook_mermaid_version=0.13.0
138+
ARG rust_nightly_version
139+
RUN cargo install cargo-deny --locked --version ${cargo_deny_version} && \
140+
cargo +${rust_nightly_version} install cargo-udeps --locked --version ${cargo_udeps_version} && \
141+
cargo install cargo-hack --locked --version ${cargo_hack_version} && \
142+
cargo install cargo-minimal-versions --locked --version ${cargo_minimal_versions_version} && \
143+
cargo install cargo-check-external-types --locked --version ${cargo_check_external_types_version} && \
144+
cargo install maturin --locked --version ${maturin_version} && \
145+
cargo install wasm-pack --locked --version ${wasm_pack_version} && \
146+
cargo install wasmtime-cli --features="component-model" --locked --version ${cargo_wasmtime_version} && \
147+
cargo +${rust_nightly_version} install cargo-component --locked --version ${cargo_component_version} && \
148+
cargo install cargo-semver-checks --locked --version ${cargo_semver_checks_version} && \
149+
cargo install mdbook --locked --version ${cargo_mdbook_version} && \
150+
cargo install mdbook-mermaid --locked --version ${cargo_mdbook_mermaid_version} && \
151+
rm -rf /opt/cargo/registry/src && \
152+
rm -rf /opt/cargo/git/db
149153

150154
# nodejs needed by internal release process
151155
FROM install_rust AS nodejs
@@ -207,30 +211,36 @@ RUN set -eux; \
207211
shadow-utils \
208212
cmake \
209213
tar \
210-
unzip; \
211-
yum clean all; \
212-
rm -rf /var/cache/yum; \
213-
groupadd build; \
214-
useradd -m -g build build; \
215-
chmod 775 /home/build;
216-
RUN set -eux; cd /tmp; curl 'https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip' -o awscliv2.zip && unzip awscliv2.zip && ./aws/install
214+
unzip && \
215+
yum clean all && \
216+
rm -rf /var/cache/yum && \
217+
groupadd build && \
218+
useradd -m -g build build && \
219+
chmod 775 /home/build && \
220+
cd /tmp && \
221+
curl 'https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip' -o awscliv2.zip && \
222+
unzip awscliv2.zip && \
223+
./aws/install && \
224+
rm -rf awscliv2.zip aws && \
225+
pip3 install --no-cache-dir mypy==0.991
226+
217227
COPY --chown=build:build --from=local_tools /opt/cargo /opt/cargo
218-
COPY --chown=build:build --from=local_tools /opt/cargo/bin/cargo-deny /opt/cargo/bin/cargo-deny
219-
COPY --chown=build:build --from=local_tools /opt/cargo/bin/cargo-udeps /opt/cargo/bin/cargo-udeps
220-
COPY --chown=build:build --from=local_tools /opt/cargo/bin/cargo-hack /opt/cargo/bin/cargo-hack
221-
COPY --chown=build:build --from=local_tools /opt/cargo/bin/cargo-minimal-versions /opt/cargo/bin/cargo-minimal-versions
222-
COPY --chown=build:build --from=local_tools /opt/cargo/bin/cargo-check-external-types /opt/cargo/bin/cargo-check-external-types
223-
COPY --chown=build:build --from=local_tools /opt/cargo/bin/maturin /opt/cargo/bin/maturin
224-
COPY --chown=build:build --from=local_tools /opt/cargo/bin/wasm-pack /opt/cargo/bin/wasm-pack
225-
COPY --chown=build:build --from=local_tools /opt/cargo/bin/wasmtime /opt/cargo/bin/wasmtime
226-
COPY --chown=build:build --from=local_tools /opt/cargo/bin/cargo-component /opt/cargo/bin/cargo-component
228+
COPY --chown=build:build --from=gradle_wrapper /opt/gradle /home/build/.gradle
229+
COPY --chown=build:build --from=cargo_tools /opt/cargo/bin/cargo-deny /opt/cargo/bin/cargo-deny
230+
COPY --chown=build:build --from=cargo_tools /opt/cargo/bin/cargo-udeps /opt/cargo/bin/cargo-udeps
231+
COPY --chown=build:build --from=cargo_tools /opt/cargo/bin/cargo-hack /opt/cargo/bin/cargo-hack
232+
COPY --chown=build:build --from=cargo_tools /opt/cargo/bin/cargo-minimal-versions /opt/cargo/bin/cargo-minimal-versions
233+
COPY --chown=build:build --from=cargo_tools /opt/cargo/bin/cargo-check-external-types /opt/cargo/bin/cargo-check-external-types
234+
COPY --chown=build:build --from=cargo_tools /opt/cargo/bin/maturin /opt/cargo/bin/maturin
235+
COPY --chown=build:build --from=cargo_tools /opt/cargo/bin/wasm-pack /opt/cargo/bin/wasm-pack
236+
COPY --chown=build:build --from=cargo_tools /opt/cargo/bin/wasmtime /opt/cargo/bin/wasmtime
237+
COPY --chown=build:build --from=cargo_tools /opt/cargo/bin/cargo-component /opt/cargo/bin/cargo-component
227238
COPY --chown=build:build --from=install_rust /opt/rustup /opt/rustup
228-
COPY --chown=build:build --from=local_tools /opt/cargo/bin/cargo-semver-checks /opt/cargo/bin/cargo-semver-checks
229-
COPY --chown=build:build --from=local_tools /opt/cargo/bin/mdbook /opt/cargo/bin/mdbook
230-
COPY --chown=build:build --from=local_tools /opt/cargo/bin/mdbook-mermaid /opt/cargo/bin/mdbook-mermaid
239+
COPY --chown=build:build --from=cargo_tools /opt/cargo/bin/cargo-semver-checks /opt/cargo/bin/cargo-semver-checks
240+
COPY --chown=build:build --from=cargo_tools /opt/cargo/bin/mdbook /opt/cargo/bin/mdbook
241+
COPY --chown=build:build --from=cargo_tools /opt/cargo/bin/mdbook-mermaid /opt/cargo/bin/mdbook-mermaid
231242
COPY --chown=build:build --from=nodejs /opt/nodejs /opt/nodejs
232243
COPY --chown=build:build --from=musl_toolchain /usr/local/musl/ /usr/local/musl/
233-
COPY --chown=build:build --from=local_tools /home/build/.gradle /home/build/.gradle
234244
ENV PATH=/opt/nodejs/bin:/opt/cargo/bin:$PATH:/usr/local/musl/bin/ \
235245
NODE_HOME=/opt/nodejs \
236246
CARGO_HOME=/opt/cargo \
@@ -245,7 +255,6 @@ ENV PATH=/opt/nodejs/bin:/opt/cargo/bin:$PATH:/usr/local/musl/bin/ \
245255
# This is used primarily by the `build.gradle.kts` files in choosing how to execute build tools. If inside the image,
246256
# they will assume the tools are on the PATH, but if outside of the image, they will `cargo run` the tools.
247257
ENV SMITHY_RS_DOCKER_BUILD_IMAGE=1
248-
RUN pip3 install --no-cache-dir mypy==0.991
249258
WORKDIR /home/build
250259
# RUSTUP_TOOLCHAIN takes precedence over everything except `+<toolchain>` args. This will allow us to ignore the toolchain
251260
# file during CI, avoiding issues during Rust version upgrades.

0 commit comments

Comments
 (0)