如何将 gRPC Python 插件与 Docker 和 Google 云构建一起使用?

How to use the gRPC Python Plugin with Docker and Google Cloud Builds?

TL,DR;

详情

I 运行 a Python gRPC service and ESP in Docker containers running on Google Compute Engine. About gRPC > API management 显示了我的应用程序架构图:

我的高级构建步骤:


1) 使用 protoc protocol buffers 编译器创建 描述符文件api_descriptor.pb

python -m grpc_tools.protoc \
    --include_imports \
    --include_source_info \
    --proto_path=. \
    --descriptor_set_out=api_descriptor.pb \
    --python_out=generated_pb2 \
    --grpc_python_out=generated_pb2 \
    bookstore.proto

2) Deploy the proto descriptor文件(api_descriptor.pb)和使用gcloud命令行工具的配置文件:

gcloud endpoints services deploy api_descriptor.pb api_config.yaml

3) Generate gRPC code 使用 Python 插件:

python -m grpc_tools.protoc -I../../protos --python_out=. --grpc_python_out=. ../../protos/helloworld.proto

4) 构建最终 Docker 映像以部署到 Google Compute Engine。生成的 Docker 图像应包括:


步骤 4) 使用以下 Docker 文件构建 'gRPC Server'(附图中最右边的蓝色框):

FROM gcr.io/google_appengine/python:latest

WORKDIR .
EXPOSE 8081
ENTRYPOINT ["python", "server.py"]

ADD requirements.txt .
ADD protos ./protos

RUN mkdir out

RUN apt-get update && \
    apt-get install -y python2.7 python-pip && \
    pip install -r requirements.txt


RUN python \
    -m grpc_tools.protoc \
    --python_out=out \
    --grpc_python_out=out \
    --proto_path=. \
    bookstore.proto

我正在将这些构建步骤迁移到 Google 的 Cloud Build

AFAICT 我的高级构建步骤应该映射到 Cloud Builder official builder images

1) ???

2) 使用cloud-builders/gcloud/到运行gcloud命令。

3) ???

4) 使用cloud-builders/docker构建'gRPC Server'Docker镜像。

步骤 2) 和 3) 已有可用的云构建器(参见 GoogleCloudPlatform/cloud-builders)。

但是,我不确定如何将步骤 1)3) 迁移到 Cloud Build。这两个步骤都需要 运行 一个 Python 插件,该插件在基础 Linux Docker 图像中不可用。

AFAICT 步骤 1) 应该为 api_descriptor.pb 生成 Cloud Build artifact 并保存到 Cloud Storage Bucket。

我几个月前就开始工作了。我不知道我是不是按照 "right" 的方式做的。自己判断 :p

TL,DR; 如果您只想将 protoc 与 Google Cloud Build 一起使用,我已经提交了一个 protoc 构建器到cloud builders community GitHub repository which has been accepted. See cloud-builders-community/protoc.

详细信息; 我的解决方案依赖于创建 protoc Custom Build Step。这会创建一个 Docker 容器镜像,Cloud Build worker 在需要 运行 protoc.

时拉取和 运行s

您只需要两个文件即可创建 Custom Build Stepprotoc:

  1. cloudbuild.yaml - 告诉 Google Cloud Builder 如何构建 Docker 图像。
  2. Dockerfile - 告诉 Docker 如何构建包含 protoc 二进制文件的环境。

这实际上是我实现步骤 1 的本地目录结构:

.
├── cloudbuild.yaml
└── Dockerfile

Docker 文件是安装 protoc 命令的地方,是两个文件中较复杂的一个:

FROM ubuntu

ARG PROTOC_VERSION=3.6.1
ARG PROTOC_TARGET=linux-x86_64
ARG ASSET_NAME=protoc-${PROTOC_VERSION}-${PROTOC_TARGET}.zip

RUN apt-get -qy update && apt-get -qy install python wget unzip && rm -rf /var/lib/apt/lists/*

RUN echo "${PROTOC_VERSION}/${ASSET_NAME}"

RUN wget https://github.com/google/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-${PROTOC_TARGET}.zip && \
unzip ${ASSET_NAME} -d protoc && rm ${ASSET_NAME}

ENV PATH=$PATH:/protoc/bin/
ENTRYPOINT ["protoc"]
CMD ["--help]

分解:

  1. 定义我们想要结束的最终 "protoc" 图像的第一个只读层。我选择 Ubuntu 因为它是我在本地 运行 的内容。任何最小 Linux "base image" 都可以,但必须安装以下二进制文件:apt-getwgetunziprm

FROM ubuntu

  1. 设置一些变量,用户可以在构建时使用 docker 使用 --build-arg <varname>=<value> 标志的构建命令将这些变量传递给构建器:

ARG PROTOC_VERSION=3.6.1

ARG PROTOC_TARGET=linux-x86_64

ARG ASSET_NAME=protoc-${PROTOC_VERSION}-${PROTOC_TARGET}.zip

  1. 运行 apt-get -qy update 到 "resynchronize the package index files from their sources"。 q 省略进度指示器,y 假定对遇到的任何提示的回答是“是”:

RUN apt-get -qy update

  1. 安装PythonWget(从网络服务器检索内容),然后解压缩.

RUN apt-get -qy install python wget unzip

  1. 删除作为前面步骤的一部分创建的所有文件(不再需要):

RUN rm -rf /var/lib/apt/lists/*

前面三个RUN指令可以合并为一个:

RUN apt-get -qy update && apt-get -qy install python wget unzip && rm -rf /var/lib/apt/lists/*

  1. 使用 ENV 指令更新 PATH 环境以在最终环境(图像)中包含 protoc 二进制文件的位置。

ENV PATH=$PATH:/protoc/bin/

设置映像的 ENTRYPOINT,使映像 运行 成为 protoc 可执行文件。不是,由于上一步将protoc添加到$PATH,我们只需要将二进制指定为运行(不是完整路径):

ENTRYPOINT ["protoc"]

  1. 使用CMD指令,这样如果运行宁protoc图像时没有提供选项,protoc --help将运行:

CMD ["--help]

这就是定义可执行文件 protoc Docker 映像所需的全部内容。但是,它还不是可以在 Google 的 Cloud Build 环境中使用的 Custom Build Step。我们必须使用 cloudbuild.yaml:

定义自定义构建步骤
steps:
  - name: 'gcr.io/cloud-builders/docker'
    args:
      [
        'build',
        '--tag',
        'gcr.io/$PROJECT_ID/protoc',
        '--cache-from',
        'gcr.io/$PROJECT_ID/protoc',
        '.',
      ]
images: ['gcr.io/$PROJECT_ID/protoc']

此文件将生成一个人工制品 gcr.io/my-cloud-project-id/protoc,可用于 Google Cloud Build 中的 运行 protoc。此自定义构建步骤的示例用法:

steps:
  - name: 'gcr.io/$PROJECT_ID/protoc'
    args:
      [
        '--include_imports',
        '--include_source_info',
        '--proto_path',
        '.',
        '--descriptor_set_out',
        'api_descriptor.pb',
        'v1/my-api-proto.proto',
      ]

Cloud Build 会自动将 $PROJECT_ID 替换为您的项目 ID,因此名称将引用工件:gcr.io/my-cloud-project-id/protoc。由于这是一个可执行的 Docker 映像(用 ENTRYPOINT ["protoc"] 定义),它等同于 运行ning 在本地:

protoc --include_imports --include_source_info --proto_path . --descriptor_set_out api_descriptor.pb v1/my-api-proto.proto

因此,在回答我的问题时,1) 和 3) 都可以使用 protoc 自定义构建步骤到 Google Cloud Build 中的 运行。