awscli version 2 on alpine linux
Asked Answered
D

8

81

I was trying to put awscli_v2 into an alpine-based docker container and see that it fails with the following error message:

/aws/install: line 78: /aws/dist/aws: not found

Considering that the file itself is there and can be listed with ls, I would guess that some libraries that the executable ./aws/dist/aws relies upon are not present on alpine. Does someone know which libraries that might be?

Derain answered 19/2, 2020 at 10:49 Comment(3)
I don't know what's missing, but I had the same problem. It works for me when I use ubuntu as the base image. TBF, the AWS documentation does list CentOS, Fedora, Ubuntu, Amazon Linux 1, and Amazon Linux 2 as the only supported OSes, but I agree it would be nice to be able to build an alpine image.Signorina
There is an issue for this in the project GitHub github.com/aws/aws-cli/issues/4685Ashling
For anybody who wants to just use the aws-cli without any hassle you can now install aws-cli v1 from the alpine package using. If you intended using aws-cli in a container without any specific reason to use v2, use apk add --no-cache aws-cli. It will save you a lot of time.Niela
C
149

Actually with a bit a effort it is possible to run AWS CLI v2 on Alpine:

ARG ALPINE_VERSION=3.17

FROM alpine:${ALPINE_VERSION}

ARG GLIBC_VERSION=2.35-r0
ARG AWSCLI_VERSION=2.11.11

# install glibc compatibility for alpine
RUN apk --no-cache add \
        binutils \
        curl \
    && curl -sL https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub -o /etc/apk/keys/sgerrand.rsa.pub \
    && curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-${GLIBC_VERSION}.apk \
    && curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-bin-${GLIBC_VERSION}.apk \
    && curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-i18n-${GLIBC_VERSION}.apk \
    && apk add --no-cache --force-overwrite \
        glibc-${GLIBC_VERSION}.apk \
        glibc-bin-${GLIBC_VERSION}.apk \
        glibc-i18n-${GLIBC_VERSION}.apk \
    && /usr/glibc-compat/bin/localedef -i en_US -f UTF-8 en_US.UTF-8 \
    && ln -sf /usr/glibc-compat/lib/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2 \
    && curl -sL https://awscli.amazonaws.com/awscli-exe-linux-x86_64-${AWSCLI_VERSION}.zip -o awscliv2.zip \
    && unzip awscliv2.zip \
    && aws/install \
    && rm -rf \
        awscliv2.zip \
        aws \
        /usr/local/aws-cli/v2/current/dist/aws_completer \
        /usr/local/aws-cli/v2/current/dist/awscli/data/ac.index \
        /usr/local/aws-cli/v2/current/dist/awscli/examples \
        glibc-*.apk \
    && find /usr/local/aws-cli/v2/current/dist/awscli/botocore/data -name examples-1.json -delete \
    && apk --no-cache del \
        binutils \
        curl \
    && rm -rf /var/cache/apk/*

The above Dockerfile will install the 'glibc' package for Alpine, so that the AWS CLI will be able to find the required shared libraries. The Dockerfile also removes some stuff we probably don't need, such as auto-complete and examples. If you need some other specific packages you can of course add them to the Dockerfile.

Updated 2023-12-12

AWS has improved the build process, so now it's also possible to build from git with MUSL glibc (kudos to @Julian Bueno):

The following will build v2.15.0 of AWS CLI, which is the latest at the time of this edit (2023-12-12)

ARG ALPINE_VERSION=3.19
FROM python:3.11-alpine${ALPINE_VERSION} as builder

ARG AWS_CLI_VERSION=2.15.0
RUN apk add --no-cache git unzip groff build-base libffi-dev cmake
RUN git clone --single-branch --depth 1 -b ${AWS_CLI_VERSION} https://github.com/aws/aws-cli.git

WORKDIR aws-cli
RUN ./configure --with-install-type=portable-exe --with-download-deps
RUN make
RUN make install

# reduce image size: remove autocomplete and examples
RUN rm -rf \
    /usr/local/lib/aws-cli/aws_completer \
    /usr/local/lib/aws-cli/awscli/data/ac.index \
    /usr/local/lib/aws-cli/awscli/examples
RUN find /usr/local/lib/aws-cli/awscli/data -name completions-1*.json -delete
RUN find /usr/local/lib/aws-cli/awscli/botocore/data -name examples-1.json -delete
RUN (cd /usr/local/lib/aws-cli; for a in *.so*; do test -f /lib/$a && rm $a; done)

# build the final image
FROM alpine:${ALPINE_VERSION}
COPY --from=builder /usr/local/lib/aws-cli/ /usr/local/lib/aws-cli/
RUN ln -s /usr/local/lib/aws-cli/aws /usr/local/bin/aws

The above reduces the image size even more (from 175MB to 95MB), since we no longer need the glibc-compat hack. Hopefully AWS will also distribute the Alpine binaries, so we do not have to build it ourselves.

Update 2023-07-01

Alpine 3.18 includes aws-cli v2 as a 'main' package, so all you need to do is just run apk add aws-cli. One remark on this: The maintainers decided to use the 'dynamically linked' executable, which means it pulls in a ton of Python3 runtime dependencies (179Mb). If you want your images to be as tiny as possible, you can continue to use option #2.

Clipping answered 17/4, 2020 at 9:45 Comment(26)
Working as expected!Automate
Great answer. I've been looking for an easy implementation of the gclib problem for a few hours and stumbled across this. It has really helped, thanks.Palindrome
This made my day. Thank you!Vincenz
This works indeed, thanks for the suggestion. I thought that this C issue might be the reason, because it is widely discussed in other topics connected to python on alpine.Derain
You get a nasty warning out of the glibc package however it does indeed work.Climacteric
I'm getting 'ascii' codec can't encode character in position error when running some awscli commands, I think this is due to unicode stuff. Something I don't get when run awscli on Debian based image.Filigree
If you need unicode support, you can try adding this: curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VER}/glibc-i18n-${GLIBC_VER}.apk && apk add glibc-i18n-${GLIBC_VER}.apk && /usr/glibc-compat/bin/localedef -i en_US -f UTF-8 en_US.UTF-8Clipping
Oh yeah, forgot to update it here ... You would need to generate your locale by installing the glibc-i18n package as well, as it is indicated in the main documentation of alpine-pkg-glibc hereFiligree
@Clipping Oh you're the author! You should know already :)Filigree
What is the final image size using this method? The official AWSCLI2 images come in around 120Mb despite not using Alpine.Jillion
Nevermind, it looks like it's around 60Mb, so roughly half the size of the official containersJillion
Just wanted to add that GCLIB v2.35-r0 currently has issues with AWS CLI v2 install. It results in symbolic link issues. Fallback to v2.34-r0 as suggested in the answer to avoid this issue. I hope the maintainer of the project will address this issue.Cleanup
@Cleanup I've updated the Dockerfile to support 2.35-r0 with this line: ln -sf /usr/glibc-compat/lib/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2Clipping
Great job, saves lots of time. Hope AWS will provide at some point musl binaries.Injector
This strategiy is fully compatible to build a multi-architecture image via docker buildx. I was able to build for both --platform linux/amd64,linux/arm64Catcall
Works, just tried it with registry.gitlab.com/gitlab-org/terraform-images/releases/1.3:v0.47.0 instead of blank alpine image 🎉Insatiable
Thanks for the answer. It worked as a charm.Oatis
Thanks! It added around 95MB to my image.Warison
Looks like native support is now in testing gitlab.alpinelinux.org/alpine/aports/-/commit/…. Here is the upstream issue gitlab.alpinelinux.org/alpine/aports/-/issues/14379.Cholesterol
I have tried to submit an updated APKBUILD file for aws-cli-v2, but the maintainers refused it. See gist.github.com/blagerweij/3ed4c39a0e0a14547d2a6b76c20b3054 IMHO that build-file is a bit 'cleaner' than the referenced commit....Clipping
it indeed "takes a bit of effort"Antic
Doesn't seem to work anymore with current alpine and aws cli when building on gitlab.com with docker 19. Here are the needed adjustments, to make it work: https://mcmap.net/q/258232/-awscli-version-2-on-alpine-linux.Skedaddle
This solution has worked for me in the past but now both solutions are not working. With the GLIBC build method I'm getting exit code 1 error "ERROR: failed to solve: process "/bin/sh -c curl -sLO github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-${GLIBC_VERSION}.apk...". When I try the MUSL glibc method, it gets stuck running setup.py. Any ideas?Cleanup
I just tried both approaches again (and have updated version numbers to the latest versions), and it works for me. There was one conflict with nsswitch.conf with newer version of Alpine, which was resolved with --force-overwrite flag.Clipping
The latter approach stopped working for me with the error File "PyInstaller/loader/pyiboot01_bootstrap.py", line 17, in <module> ModuleNotFoundError: No module named 'pyimod02_importers'. I'm trying versions 2.11.5 of AWSCLI and 3.11-alpine3.17 of Python.Babbling
@AlexanderPravdin I've just tried with v2.11.5, v2.12.1 and v2.11.27, all of them worked for me.... Perhaps you could try Python 3.10 or a newer version of aws-cli?Clipping
S
39

AWS CLI version 2 is compiled against glibc, the GNU Project's implementation of the C standard library. Most common Linux distributions use glibc, but Alpine Linux is instead based on musl libc.

Because binaries compiled against glibc aren't compatible with musl, AWS CLI version 2 doesn't run on Alpine Linux.

The best way to run AWS CLI version 2 on Alpine Linux would be for Amazon to provide one of the following:

  • Binaries compiled against musl
  • A source distribution, which can be compiled on Alpine Linux
  • An official AWS CLI Docker image based on Alpine Linux

Update

AWS now provides an example Dockerfile to build AWS CLI on Alpine Linux: https://docs.aws.amazon.com/cli/latest/userguide/getting-started-source-install.html#source-getting-started-install-workflows-alpine

Dockerfile:

FROM python:3.8-alpine AS builder

ENV AWSCLI_VERSION=2.2.1

RUN apk add --no-cache \
    curl \
    make \
    cmake \
    gcc \
    g++ \
    libc-dev \
    libffi-dev \
    openssl-dev \
    && curl https://awscli.amazonaws.com/awscli-${AWSCLI_VERSION}.tar.gz | tar -xz \
    && cd awscli-${AWSCLI_VERSION} \
    && ./configure --prefix=/opt/aws-cli/ --with-download-deps \
    && make \
    && make install

FROM python:3.8-alpine

RUN apk --no-cache add groff

COPY --from=builder /opt/aws-cli/ /opt/aws-cli/

ENTRYPOINT ["/opt/aws-cli/bin/aws"]

Build and run:

$ docker build --tag awscli-alpine .
$ docker run --rm -it awscli-alpine --version
aws-cli/2.2.1 Python/3.8.11 Linux/5.10.25-linuxkit source-sandbox/x86_64.alpine.3 prompt/off

Update 2

Alpine Linux 3.18 provides AWS CLI in the aws-cli package. To install it, run:

$ apk update
$ apk add aws-cli
Sherly answered 19/3, 2020 at 18:22 Comment(2)
musl binaries is probably what most people wantInjector
Thank you for update 2. We're using Alpine and I was not aware that this was available. This is a much simpler approach if you don't want to include the CLI in the base image.Koh
G
11

Can also use https://git.adelielinux.org/adelie/gcompat

apk add gcompat

source: https://wiki.alpinelinux.org/wiki/Running_glibc_programs

Edit sample:

ENV AWS_CLI_VER=2.0.30

RUN apk update && apk add --no-cache curl gcompat zip &&  \
    curl -s https://awscli.amazonaws.com/awscli-exe-linux-x86_64-${AWS_CLI_VER}.zip -o awscliv2.zip && \
    unzip awscliv2.zip && ./aws/install
Gastineau answered 24/8, 2021 at 21:43 Comment(8)
Could you add more details on your answer? A complete script to setup and run AWS CLI with this package? Because I tried and got the ImportError: Error relocating /usr/local/aws-cli/v2/dist/_awscrt.cpython-38-x86_64-linux-gnu.so: pthread_attr_setaffinity_np: symbol not found error.Babbling
If I was to guess, you try to install awscliv2 via pip? If so, try using curl to get the zip binary directly. It worked for me when the latest version of alpine.Gastineau
I've downloaded awscli v2 linux binaries and tried running them as is with the gcompat installed. Could you extend your answer with clear reproducible steps to repeat your success?Babbling
No bueno: ` (3/3) Installing gcompat (1.0.0-r2) $ ldd ./aws/dist/aws Error relocating ./aws/dist/aws: __strcat_chk: symbol not found Error relocating ./aws/dist/aws: __snprintf_chk: symbol not found Error relocating ./aws/dist/aws: __vfprintf_chk: symbol not found Error relocating ./aws/dist/aws: __realpath_chk: symbol not found Error relocating ./aws/dist/aws: __memcpy_chk: symbol not found Error relocating ./aws/dist/aws: __vsnprintf_chk: symbol not found `Bucktooth
I'd really like for this answer to work, as Alpine suggests it as the official way to run glibc programs, and it avoids sourcing something from a random GitHub repository. Unfortunately it doesn't seem to work - I'm getting the same symbol not found errors.Mayday
I think that's an error u'd get if you download arm version of awscli and try to run it on a non-arm architecture (e.g. aws.amazon.com/blogs/developer/…) You probably wanted non-arm linux version.Gastineau
As of this writing, AWS_CLI_VERSION=2.1.39 worked with gcompat that I installed and NOT the latest AWS CLI which as this writing is 2.2.43Filmore
Can confirm the comment from @skim, 2.1.39 w/ gcompat works for me too (unlike newer versions).Chincapin
F
4

From this comment and this . I have create an updated version at the time of writing. This version does not need gcompat and takes 6 minutes to build

FROM python:3.10.5-alpine3.16 as builder

ENV AWS_CLI_VERSION=2.7.15

RUN set -ex; \
apk add --no-cache \
git unzip groff build-base libffi-dev cmake

RUN set -eux; \
git clone --single-branch --depth 1 -b ${AWS_CLI_VERSION} https://github.com/aws/aws-cli.git; \
cd /aws-cli; \
sed -i'' 's/PyInstaller.*/PyInstaller==5.2/g' requirements-build.txt; \
python -m venv venv; \
. venv/bin/activate; \
./scripts/installers/make-exe

RUN set -ex; \
unzip /aws-cli/dist/awscli-exe.zip; \
./aws/install --bin-dir /aws-cli-bin; \
/aws-cli-bin/aws --version

FROM python:3.10.5-alpine3.16

COPY --from=builder /usr/local/aws-cli/ /usr/local/aws-cli/
COPY --from=builder /aws-cli-bin/ /usr/local/bin/  

#Check version
RUN  aws --version 

ENTRYPOINT ["/bin/ash", "-c"]
Felspar answered 14/7, 2022 at 14:7 Comment(3)
Not working for me. I get it hanging with this step ... => => # + export VIRTUAL_ENV_PROMPT => => # + '[' -n -o -n ] => => # + ./scripts/installers/make-exe => => # /aws-cli/./scripts/installers/make-exe:12: DeprecationWarning: The distutils package is deprecated and slated for removal in Python 3.12. Use setuptools or check => => # PEP 632 for potential alternatives => => # from distutils.dir_util import copy_tree ...Jijib
Works perfectly for me! I've made some improvements to reduce the image size even more, check my updated answer above: https://mcmap.net/q/258232/-awscli-version-2-on-alpine-linuxClipping
has anyone had any look with 2.9.23 plus as the awscli version?Crashing
S
1

To make it work on gitlab.com with docker 19.x with current aws cli version 2.11.4 and current alpine 3.17.2 I had to make a few adjustments to the accepted answer from blagerweij.

# install awscli v2 and other basic utilities that are needed by all docker images
# see: https://mcmap.net/q/258232/-awscli-version-2-on-alpine-linux
ARG ALPINE_VERSION=3.17.2

FROM alpine:${ALPINE_VERSION}

ARG GLIBC_VERSION=2.33-r0
ARG AWSCLI_VERSION=2.11.4

# install glibc compatibility for alpine
RUN apk --no-cache add \
        binutils \
        curl \
    && curl -sL https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub -o /etc/apk/keys/sgerrand.rsa.pub \
    && curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-${GLIBC_VERSION}.apk \
    && curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-bin-${GLIBC_VERSION}.apk \
    && curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-i18n-${GLIBC_VERSION}.apk \
    && apk add --no-cache \
        --force-overwrite \
        glibc-${GLIBC_VERSION}.apk \
        glibc-bin-${GLIBC_VERSION}.apk \
        glibc-i18n-${GLIBC_VERSION}.apk \
    && /usr/glibc-compat/bin/localedef -i en_US -f UTF-8 en_US.UTF-8 \
    && ln -sf /usr/glibc-compat/lib/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2 \
    && curl -sL https://awscli.amazonaws.com/awscli-exe-linux-x86_64-${AWSCLI_VERSION}.zip -o awscliv2.zip \
    && unzip awscliv2.zip \
    && aws/install \
    && rm -rf \
        awscliv2.zip \
        aws \
        /usr/local/aws-cli/v2/current/dist/aws_completer \
        /usr/local/aws-cli/v2/current/dist/awscli/data/ac.index \
        /usr/local/aws-cli/v2/current/dist/awscli/examples \
        glibc-*.apk \
    && find /usr/local/aws-cli/v2/current/dist/awscli/botocore/data -name examples-1.json -delete \
    && apk --no-cache del \
        binutils \
        curl \
    && rm -rf /var/cache/apk/*

ENV LANG='C.UTF-8'
```
Skedaddle answered 19/3, 2023 at 9:29 Comment(3)
Thanks for this, I'm struggling to make it work with the "builder image" paradigm though, i.e. I'm doing FROM alpine:${ALPINE_VERSION} COPY --from=builder /usr/local/aws-cli/ /usr/local/aws-cli/ RUN /usr/local/aws-cli/v2/2.11.11/dist/aws --version but I get /bin/sh: /usr/local/aws-cli/v2/2.11.11/dist/aws: not found Any idea what I'm missing? (sorry for crappy formatting, I don't think multi-line code fragments are supported in comments)Okwu
@Okwu you sure your using aws cli version 2.11.11 and the path is correct?Skedaddle
Yep, I can ls that path within the image no problem: -rwxr-xr-x 1 root root 6655640 Apr 19 12:23 /usr/local/aws-cli/v2/2.11.4/dist/awsOkwu
P
0

awscli-v2 might be coming to alpine as a package.

Someone might be working on it in the community repository: https://pkgs.alpinelinux.org/packages?name=aws-cli&branch=edge&repo=community

Currently seems to be broken but if you want to try it out you can install with: apk add aws-cli --repository=https://dl-cdn.alpinelinux.org/alpine/edge/community

Pau answered 13/2, 2023 at 22:51 Comment(2)
The package was now moved to a community repository: pkgs.alpinelinux.org/… although it still (currently - Feb 22, 2023) doesn't seem to work due a bug in the Python symlink (links to 3.11 rather than 3.10).Polluted
Yeah looks like the maintainer might have dropped it.Pau
L
0

Rather than trying to fix the MUSL/LIBC gaps in Apline or to go the hard path with Python, I have found this image rather good and up to date. It's got the compiled version of AWS cli.

It is about 105 MB in size after some cleanup (you don t need docs, do you?)

In case you really want to start from Alpine (with no other party involved), then you can check in the Alpine package management that edge tag/branch supports AWS cli v2 v2.11.0-r0 as of 2023-03-05 (Python-interpreted version).

So, you Dockerfile can be as simple as:

FROM alpine:edge
RUN apk add --no-cache aws-cli
RUN rm -fr \
  /usr/bin/aws_completer \
  /usr/lib/python*/site-packages/awscli/data/ac.index \
  /usr/lib/python*/site-packages/awscli/examples
RUN find /usr/lib/python* -name completions-1*.json -delete

to get a 183MB image. Of course your mileage may vary with other versions.

Leonor answered 5/3, 2023 at 16:35 Comment(0)
T
0

Wanted to add this as a comment to the answer about the community repo, but I guess I don't have enough rep. I was able to get aws-cli v2 running on alpine just using apk repositories. These commands in your dockerfile should work to get the correct versions of Python, Pip, Aws-Cli and python dependencies.

RUN apk update --repository=https://dl-cdn.alpinelinux.org/alpine/edge/main/
RUN apk add python3 --repository=https://dl-cdn.alpinelinux.org/alpine/edge/main/
RUN apk update --repository=https://dl-cdn.alpinelinux.org/alpine/edge/community/
RUN apk add aws-cli py3-pip --repository=https://dl-cdn.alpinelinux.org/alpine/edge/community/
RUN pip install --ignore-installed wcwidth docutils cryptography urllib3 six
Tracheitis answered 25/4, 2023 at 18:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.