I’m trying to build a simple container which downloads a Protocol Buffers binary from the release page (https://github.com/protocolbuffers/protobuf/releases/tag/v3.13.0) and adds it to the path. Following the Linux instructions at http://google.github.io/proto-lens/installing-protoc.html, I’ve attempted the following Dockerfile
:
FROM golang:alpine # Install protoc (cf. http://google.github.io/proto-lens/installing-protoc.html) RUN apk add curl ENV PROTOC_ZIP=protoc-3.13.0-linux-x86_64.zip RUN curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v3.13.0/$PROTOC_ZIP && unzip -o $PROTOC_ZIP -d /usr/local bin/protoc && unzip -o $PROTOC_ZIP -d /usr/local 'include/*' && rm -f $PROTOC_ZIP
The problem is that if I build it using
docker build --tag docker-protoc .
and run a shell in it, I get a protoc: not found
error, even though the binary is in /usr/local/bin
which is in the PATH
:
> docker run -it docker-protoc /bin/ash /go # protoc /bin/ash: protoc: not found /go # ls /usr/local/bin protoc /go # echo $PATH /go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin /go #
It also occurred to me that I might have downloaded a version of protoc
that is not runnable on Alpine Linux, but the linux-x86_64
suffix seems to match the architecture of the container:
/go # uname -m x86_64
Any idea why protoc
can’t be executed in this container?
Advertisement
Answer
As pointed out by KamilCuk, Alpine uses musl as its C standard library whereas the binary was compiled against glibc. My solution was to use the golang
base image (which is based on Buster Linux) rather than golang:alpine
:
FROM golang # Install protoc (cf. http://google.github.io/proto-lens/installing-protoc.html) ENV PROTOC_ZIP=protoc-3.13.0-linux-x86_64.zip RUN apt-get update && apt-get install -y unzip RUN curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v3.13.0/$PROTOC_ZIP && unzip -o $PROTOC_ZIP -d /usr/local bin/protoc && unzip -o $PROTOC_ZIP -d /usr/local 'include/*' && rm -f $PROTOC_ZIP