8

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?

kubanczyk
  • 5,184
  • 1
  • 41
  • 52
Kurt Peek
  • 52,165
  • 91
  • 301
  • 526
  • 4
    `Any idea` because alpine uses musl, and the binary was compiled against glibc – KamilCuk Oct 20 '20 at 14:53
  • 1
    As @KamilCuk mentioned it is missing `glibc`, which could be solved by installing `apk add gcompat` https://wiki.alpinelinux.org/wiki/Running_glibc_programs – maxcnunes Mar 07 '22 at 23:03

3 Answers3

8

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
Kurt Peek
  • 52,165
  • 91
  • 301
  • 526
  • 3
    Alpine also has protoc in apk `apk add protoc`, although the version isn't quite the latest. – Frug Jan 28 '21 at 16:38
  • 2
    Although installing this `protoc` alpine dep, it won't come with the `descriptor.proto` file, it will be installing only the compiler. I needed `apk add protobuf-dev` to actually locate the `descriptor.proto` file inside `/usr/include/google/protobuf`, and finally build my protos schemas. – Marcosaurios Nov 19 '21 at 10:57
3

Nowadays you will be fine with just a standard package:

FROM golang:alpine

RUN apk update && apk add --no-cache make protobuf-dev
kubanczyk
  • 5,184
  • 1
  • 41
  • 52
0

You can actually build protoc from its source according to the documentation. I am using the docker image, which is an alpine-based image and there is no Buster base image of it. Here is my Dockerfile:

FROM docker:20.10.12

RUN apk update && apk add curl bash unzip build-base autoconf automake libtool make g++
ENV PROTOBUF_VERSION 3.19.4
ENV PROTOBUF_URL https://github.com/google/protobuf/releases/download/v"$PROTOBUF_VERSION"/protobuf-cpp-"$PROTOBUF_VERSION".zip
RUN curl --silent -L -o protobuf.zip "$PROTOBUF_URL" && \
    unzip protobuf.zip && \
    cd protobuf-"$PROTOBUF_VERSION" && \
    ./configure && \
    make -j$(nproc) && \
    make install && \
    cd .. && rm protobuf.zip

And then build the image:

docker build . -t protoc:0.0.1

After the build is over you can test it like this:

docker run --rm -it --entrypoint bash protoc:0.0.1
bash-5.1# protoc --version
libprotoc 3.19.4
Ramin Gharib
  • 45
  • 10