76

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?

Konstl
  • 793
  • 1
  • 5
  • 8
  • 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](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2-linux.html) 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. – digitalronin Mar 16 '20 at 11:04
  • 1
    There is an issue for this in the project GitHub https://github.com/aws/aws-cli/issues/4685 – Evgeny Sep 13 '20 at 10:35
  • 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. – Missaka Iddamalgoda Aug 24 '22 at 14:44

8 Answers8

141

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.

Update 2022-08-01

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

ARG ALPINE_VERSION=3.17
FROM python:3.10-alpine${ALPINE_VERSION} as builder

ARG AWS_CLI_VERSION=2.11.11
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.

blagerweij
  • 3,154
  • 1
  • 15
  • 20
  • 5
    Working as expected! – Syerad Apr 22 '20 at 20:02
  • 1
    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. – Software Engineer May 09 '20 at 09:14
  • This made my day. Thank you! – Justinas Lelys Jun 03 '20 at 10:16
  • 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. – Konstl Jun 17 '20 at 13:02
  • You get a nasty warning out of the glibc package however it does indeed work. – krystan honour Jan 27 '21 at 02:26
  • 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. – bormansquirrel Feb 25 '21 at 12:56
  • 1
    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-8` – blagerweij Feb 25 '21 at 16:58
  • 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` [here](https://github.com/sgerrand/alpine-pkg-glibc#locales) – bormansquirrel Feb 26 '21 at 11:28
  • @blagerweij Oh you're the author! You should know already :) – bormansquirrel Feb 26 '21 at 11:29
  • What is the final image size using this method? The official AWSCLI2 images come in around 120Mb despite not using Alpine. – Lee Harrison Feb 28 '21 at 01:19
  • 3
    Nevermind, it looks like it's around 60Mb, so roughly half the size of the official containers – Lee Harrison Feb 28 '21 at 01:32
  • 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. – Alex Jul 25 '22 at 15:07
  • @Alex 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.2` – blagerweij Jul 27 '22 at 09:59
  • Great job, saves lots of time. Hope AWS will provide at some point musl binaries. – zenbeni Aug 09 '22 at 09:30
  • 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/arm64` – laconbass Sep 28 '22 at 22:58
  • Works, just tried it with registry.gitlab.com/gitlab-org/terraform-images/releases/1.3:v0.47.0 instead of blank alpine image – Benjamin Nov 23 '22 at 10:39
  • Thanks for the answer. It worked as a charm. – Carl Tsai Dec 29 '22 at 05:48
  • Thanks! It added around 95MB to my image. – RicHincapie Jan 17 '23 at 18:31
  • Looks like native support is now in testing https://gitlab.alpinelinux.org/alpine/aports/-/commit/aa039cf358500ac471ba9f82529dba0c0fdc2887. Here is the upstream issue https://gitlab.alpinelinux.org/alpine/aports/-/issues/14379. – SomeGuyOnAComputer Feb 08 '23 at 17:32
  • I have tried to submit an updated APKBUILD file for aws-cli-v2, but the maintainers refused it. See https://gist.github.com/blagerweij/3ed4c39a0e0a14547d2a6b76c20b3054 IMHO that build-file is a bit 'cleaner' than the referenced commit.... – blagerweij Feb 08 '23 at 23:00
  • it indeed "takes a bit of effort" – Cyril Duchon-Doris Feb 17 '23 at 15:35
  • 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://stackoverflow.com/a/75781104/1245992. – Gellweiler Mar 19 '23 at 09:42
  • 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 https://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? – Alex Apr 06 '23 at 03:35
  • 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. – blagerweij Apr 12 '23 at 10:52
  • The latter approach stopped working for me with the error `File "PyInstaller/loader/pyiboot01_bootstrap.py", line 17, in ModuleNotFoundError: No module named 'pyimod02_importers'`. I'm trying versions `2.11.5` of AWSCLI and `3.11-alpine3.17` of Python. – Alexander Pravdin Jun 16 '23 at 03:52
  • @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? – blagerweij Jun 19 '23 at 08:54
35

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
Max Smolens
  • 3,461
  • 26
  • 34
  • musl binaries is probably what most people want – zenbeni Aug 08 '22 at 12:27
  • 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. – display name Aug 27 '23 at 14:44
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
AnthonyC
  • 1,880
  • 2
  • 20
  • 27
  • 4
    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. – Alexander Pravdin Aug 25 '21 at 01:21
  • 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. – AnthonyC Aug 25 '21 at 16:58
  • 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? – Alexander Pravdin Aug 26 '21 at 03:25
  • 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 ` – Alexander Aug 26 '21 at 08:59
  • 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. – DrTeeth Sep 24 '21 at 13:12
  • 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. https://aws.amazon.com/blogs/developer/aws-cli-v2-now-available-for-linux-arm/) You probably wanted non-arm linux version. – AnthonyC Sep 28 '21 at 22:57
  • 7
    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.43 – skim Oct 05 '21 at 17:55
  • 2
    Can confirm the comment from @skim, 2.1.39 w/ gcompat works for me too (unlike newer versions). – Karim Temple Nov 15 '21 at 22:56
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"]
  • 1
    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 ... – azec-pdx Jul 16 '22 at 00:26
  • 1
    Works perfectly for me! I've made some improvements to reduce the image size even more, check my updated answer above: https://stackoverflow.com/a/61268529/1704634 – blagerweij Aug 01 '22 at 20:38
  • has anyone had any look with 2.9.23 plus as the awscli version? – Ric_Harvey Feb 13 '23 at 13:22
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://stackoverflow.com/a/75781104/1245992
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'
```
Gellweiler
  • 751
  • 1
  • 12
  • 25
  • 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) – Constantinos Apr 14 '23 at 17:27
  • @Constantinos you sure your using aws cli version 2.11.11 and the path is correct? – Gellweiler Apr 18 '23 at 11:16
  • 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/aws` – Constantinos Apr 19 '23 at 12:26
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

WesAtWork
  • 65
  • 7
  • 1
    The package was now moved to a community repository: https://pkgs.alpinelinux.org/packages?name=aws-cli&branch=edge&repo=community 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). – Pavel Pichrt Feb 22 '23 at 16:37
  • Yeah looks like the maintainer might have dropped it. – WesAtWork Feb 23 '23 at 10:17
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.

EnzoR
  • 3,107
  • 2
  • 22
  • 25
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
EdChung
  • 1
  • 2