"protoc: not found" 基于 Alpine 的 Docker 容器 运行 Protocol Buffers
"protoc: not found" on an Alpine-based Docker container running Protocol Buffers
我正在尝试构建一个简单的容器,它从发布页面下载 Protocol Buffers 二进制文件(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,我尝试了以下 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
问题是如果我使用
构建它
docker build --tag docker-protoc .
和 运行 其中有一个 shell,我得到一个 protoc: not found
错误,即使二进制文件在 /usr/local/bin
中,也就是 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 #
我还想到我可能下载了一个 protoc
的版本,它在 Alpine Linux 上 运行 不可用,但 linux-x86_64
后缀似乎匹配容器的架构:
/go # uname -m
x86_64
知道为什么 protoc
不能在此容器中执行吗?
正如 KamilCuk 所指出的,Alpine 使用 musl 作为其 C 标准库,而二进制文件是针对 glibc 编译的。我的解决方案是使用 golang
基本图像(基于 Buster Linux)而不是 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
现在你可能只需要:
FROM golang:1.17-alpine
RUN apk update && apk add --no-cache make protobuf-dev=3.18.1-r1
您实际上可以根据 documentation. I am using the docker image, which is an alpine-based image 从其源代码构建协议,并且没有它的 Buster 基础映像。这是我的 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
然后构建镜像:
docker build . -t protoc:0.0.1
构建完成后你可以这样测试它:
docker run --rm -it --entrypoint bash protoc:0.0.1
bash-5.1# protoc --version
libprotoc 3.19.4
我正在尝试构建一个简单的容器,它从发布页面下载 Protocol Buffers 二进制文件(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,我尝试了以下 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
问题是如果我使用
构建它docker build --tag docker-protoc .
和 运行 其中有一个 shell,我得到一个 protoc: not found
错误,即使二进制文件在 /usr/local/bin
中,也就是 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 #
我还想到我可能下载了一个 protoc
的版本,它在 Alpine Linux 上 运行 不可用,但 linux-x86_64
后缀似乎匹配容器的架构:
/go # uname -m
x86_64
知道为什么 protoc
不能在此容器中执行吗?
正如 KamilCuk 所指出的,Alpine 使用 musl 作为其 C 标准库,而二进制文件是针对 glibc 编译的。我的解决方案是使用 golang
基本图像(基于 Buster Linux)而不是 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
现在你可能只需要:
FROM golang:1.17-alpine
RUN apk update && apk add --no-cache make protobuf-dev=3.18.1-r1
您实际上可以根据 documentation. I am using the docker image, which is an alpine-based image 从其源代码构建协议,并且没有它的 Buster 基础映像。这是我的 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
然后构建镜像:
docker build . -t protoc:0.0.1
构建完成后你可以这样测试它:
docker run --rm -it --entrypoint bash protoc:0.0.1
bash-5.1# protoc --version
libprotoc 3.19.4