aws-cli v2: how much smaller can it get? Answer: a lot smaller :)
Tags: aws, cli
Published: 2023-03-19 16:54:26

Pulling the official aws-cli image, I got a huge 374MB image.

```
docker images | grep amazon
amazon/aws-cli                                              latest            abb3d3272080   3 days ago      374MB
```

It's rather big for a CLI and so I thought: "Maybe I can make it smaller".

## Entering Wolfi

Wolfi is a project sponsored by Chainguard. Wolfi is described as:

> [Wolfi](https://github.com/wolfi-dev/) is a stripped-down distro designed for the cloud-native era.

Well, you can think of it like Google's [distroless](https://github.com/GoogleContainerTools/distroless).

The reason I want to select Wolfi is because of a bunch of reasons:

- Better SBOM support. Well, not all the SBOMs are created equally and what's better than building everything from sources and create SBOM from there.
- Multi-arch (amd64, arm64 are must but maybe armv7 as well?)
- Smaller image size.
- Signed and verifiable :)
- Secure. Let's aim for that sweet 0 CVE.

## aws-cli v2

aws-cli v2 is powered by a bunch of C project like [aws-c-http](https://github.com/awslabs/aws-c-http), [aws-c-auth](https://github.com/awslabs/aws-c-auth), etc... and so I need to package those first.

What I don't quite understand is AWS's decision to still use Python as frontend for the CLI. And packaging Python packages is like going down the rabbit hole.

I'm going to use [melange](https://github.com/chainguard-dev/melange) for packaging. I write melange package's manifest in YAML and melange spits out APK file for me.

Here's what a package build file looks like with melange

```yaml
package:
  name: aws-c-http
  version: 0.7.5
  epoch: 0
  description: AWS C99 implementation of the HTTP/1.1 and HTTP/2 specifications
  copyright:
    - license: Apache-2.0
environment:
  contents:
    keyring:
      - https://packages.wolfi.dev/os/wolfi-signing.rsa.pub
    repositories:
      - https://packages.wolfi.dev/os
      - '@local ./packages'
    packages:
      - aws-c-cal-dev@local
      - aws-c-common-dev@local
      - aws-c-compression-dev@local
      - aws-c-io-dev@local
      - build-base
      - busybox
      - ca-certificates-bundle
      - cmake
      - s2n-tls-dev@local
      - samurai
pipeline:
  - uses: fetch
    with:
      expected-sha512: 90bfd0abfce8727bd4ef6e9a016e6183c2c4349c2d6e4cc02b932f5109ceb3476d79b853e74ca4888b768f44eba9ae953ca5e9b900704a2a3370a200c0168c02
      uri: https://github.com/awslabs/aws-c-http/archive/refs/tags/v${{package.version}}.tar.gz
  - runs: |
      if [ "$CBUILD" != "$CHOST" ]; then
        CMAKE_CROSSOPTS="-DCMAKE_SYSTEM_NAME=Linux -DCMAKE_HOST_SYSTEM_NAME=Linux"
      fi
      CFLAGS="$CFLAGS -flto=auto" \
      CXXFLAGS="$CXXFLAGS -flto=auto" \
      cmake -B build -G Ninja \
        -DCMAKE_INSTALL_PREFIX=/usr \
        -DCMAKE_INSTALL_LIBDIR=/usr/lib \
        -DBUILD_SHARED_LIBS=True \
        -DCMAKE_BUILD_TYPE=None \
        -DBUILD_TESTING="$(want_check && echo ON || echo OFF)" \
        $CMAKE_CROSSOPTS
      cmake --build build
  - runs: |
      DESTDIR="${{targets.destdir}}" cmake --install build
  - uses: strip
subpackages:
  - name: aws-c-http-dev
    pipeline:
      - uses: split/dev
      - runs: |
          mkdir -p "${{targets.subpkgdir}}"/usr/lib
          mv "${{targets.destdir}}"/usr/lib/aws-c-http "${{targets.subpkgdir}}"/usr/lib/
    dependencies:
      runtime:
        - aws-c-http
    description: aws-c-http dev

```
I also need to package a bunch of Python libs like `py3-certifi`, `py3-distro`, etc... because they are not available on Wolfi yet.

Once those are done, I just need to build `aws-cli` package, put those APK files in a final image with Chainguard's [apko](https://github.com/chainguard-dev/apko).

## Preliminary result

The early result looks very promising. The final image is much smaller. 50% smaller to be precised. And I mean without any optimizations at all. I haven't even split the docs into their own packages yet.

Let's look at it.

![new aws-cli image size](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qnnb6d3ntoxeh290id5h.png)

186MB vs the original 374MB. A whooping 188MB stripped off from the official aws-cli image. That's 50% size reduction.

Are you sure it's even working :D

## Final

I haven't quite done with it yet but you can try it by pulling `ghcr.io/tuananh/aws-cli`.

For now, it's still very much work-in-progress so expect things may break here and there :)