🐳

Dockerを利用して FlatBuffers コンパイラを使用する

2024/02/21に公開

こんにちは、 Kenos, Inc.Ke の部分、 @key3 こと佐藤です。

Kenos では通信に含めるバイナリデータのシリアライザとして FlatBuffers を採用しています。外部にスキーマを持つタイプのシリアライザで、スキーマに従った形で任意の型の値をバイナリデータに置き換えることが出来ます。もちろんシリアライズされたバイナリから元のデータを取り出すことも出来ます。

プロジェクト内で使用する FlatBuffers コンパイラを一貫して管理したいという要求を元に、 FlatBuffers 純正のコンパイラ flatc と、 C 言語向けコンパイラの flatcc の2つを Docker コンテナ上で利用する方法をまとめました。

必要なもの

  • Docker
    • docker-compose をサポートしているバージョン以降

手順

Dockerfile の準備

Docker tooling for FlatbuffersDockerfile を取得して保存します。Docker Hub にイメージが登録されているが、バージョンが古いため自前でコンパイルします。2024/02/16時点の内容は以下。

Dockerfile
Dockerfile
# Flatbuffers Dockerfile
# https://github.com/neomantra/docker-flatbuffers

###############################################################################
# FlatBuffer Build
###############################################################################

ARG FLATBUFFERS_IMAGE_BASE="debian"
ARG FLATBUFFERS_IMAGE_TAG="bullseye-slim"

FROM ${FLATBUFFERS_IMAGE_BASE}:${FLATBUFFERS_IMAGE_TAG} as flatbuffer_build

ARG FLATBUFFERS_IMAGE_BASE="debian"
ARG FLATBUFFERS_IMAGE_TAG="bullseye-slim"

ARG FLATBUFFERS_ARCHIVE_BASE_URL="https://api.github.com/repos/google/flatbuffers/tarball"
ARG FLATBUFFERS_ARCHIVE_TAG="master"
ARG FLATBUFFERS_BUILD_TYPE="Release"

# Set to exactly "true" to use clang
ARG FLATBUFFERS_USE_CLANG="false"


RUN DEBIAN_FRONTEND=noninteractive apt-get update \
    && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
        ca-certificates \
        cmake \
        curl \
        make \
        $( if [ "${FLATBUFFERS_USE_CLANG}" = "true" ] ; then echo "clang" ; else echo "g++" ; fi)


RUN curl -fSL "${FLATBUFFERS_ARCHIVE_BASE_URL}/${FLATBUFFERS_ARCHIVE_TAG}" -o flatbuffers.tar.gz \
    && tar xzf flatbuffers.tar.gz \
    && mv google-flatbuffers-* flatbuffers \
    && cd flatbuffers \
    && env $( if [ "${FLATBUFFERS_USE_CLANG}" = "true" ] ; then echo "CC=/usr/bin/clang CXX=/usr/bin/clang++ " ; fi) \
           cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=${FLATBUFFERS_BUILD_TYPE} \
    && make \
    && make test \
    && make install \
    && cp src/idl_parser.cpp src/idl_gen_text.cpp /usr/local/include/flatbuffers


# Build artifacts:
# -- Install configuration: "Release"
# -- Installing: /usr/local/include/flatbuffers
# -- Installing: /usr/local/include/flatbuffers/idl.h
# -- Installing: /usr/local/include/flatbuffers/registry.h
# -- Installing: /usr/local/include/flatbuffers/reflection.h
# -- Installing: /usr/local/include/flatbuffers/flexbuffers.h
# -- Installing: /usr/local/include/flatbuffers/flatc.h
# -- Installing: /usr/local/include/flatbuffers/minireflect.h
# -- Installing: /usr/local/include/flatbuffers/base.h
# -- Installing: /usr/local/include/flatbuffers/grpc.h
# -- Installing: /usr/local/include/flatbuffers/flatbuffers.h
# -- Installing: /usr/local/include/flatbuffers/reflection_generated.h
# -- Installing: /usr/local/include/flatbuffers/hash.h
# -- Installing: /usr/local/include/flatbuffers/stl_emulation.h
# -- Installing: /usr/local/include/flatbuffers/util.h
# -- Installing: /usr/local/include/flatbuffers/code_generators.h
# -- Installing: /usr/local/lib/cmake/flatbuffers/FlatbuffersConfig.cmake
# -- Installing: /usr/local/lib/cmake/flatbuffers/FlatbuffersConfigVersion.cmake
# -- Installing: /usr/local/lib/libflatbuffers.a
# -- Installing: /usr/local/lib/cmake/flatbuffers/FlatbuffersTargets.cmake
# -- Installing: /usr/local/lib/cmake/flatbuffers/FlatbuffersTargets-release.cmake
# -- Installing: /usr/local/bin/flatc
# -- Installing: /usr/local/lib/cmake/flatbuffers/FlatcTargets.cmake
# -- Installing: /usr/local/lib/cmake/flatbuffers/FlatcTargets-release.cmake
#
# Also want:
# src/idl_parser.cpp
# src/idl_gen_text.cpp
#


###############################################################################
# flatcc Build
###############################################################################

# Same build environment as FlatBuffer

ARG FLATCC_ARCHIVE_BASE_URL="https://api.github.com/repos/dvidelabs/flatcc/tarball"
ARG FLATCC_ARCHIVE_TAG="master"

RUN curl -fSL "${FLATCC_ARCHIVE_BASE_URL}/${FLATCC_ARCHIVE_TAG}" -o flatcc.tar.gz \
    && tar xzf flatcc.tar.gz \
    && mv dvidelabs-flatcc-* flatcc \
    && cd flatcc \
    && env $( if [ "${FLATBUFFERS_USE_CLANG}" = "true" ] ; then echo "CC=/usr/bin/clang CXX=/usr/bin/clang++ " ; fi) \
        ./scripts/initbuild.sh make \
    && env $( if [ "${FLATBUFFERS_USE_CLANG}" = "true" ] ; then echo "CC=/usr/bin/clang CXX=/usr/bin/clang++ " ; fi) \
       ./scripts/build.sh


# Build artifacts:
# Compiler:
#   bin/flatcc                 (command line interface to schema compiler)
#   lib/libflatcc.a            (optional, for linking with schema compiler)
#   include/flatcc/flatcc.h    (optional, header and doc for libflatcc.a)
# Runtime:
#   include/flatcc/**          (runtime header files)
#   include/flatcc/reflection  (optional)
#   include/flatcc/support     (optional, only used for test and samples)
#   lib/libflatccrt.a          (runtime library)


###############################################################################
# Final Image Composition
###############################################################################

FROM ${FLATBUFFERS_IMAGE_BASE}:${FLATBUFFERS_IMAGE_TAG}

ARG FLATBUFFERS_IMAGE_BASE="debian"
ARG FLATBUFFERS_IMAGE_TAG="bullseye-slim"

COPY --from=flatbuffer_build /usr/local/bin/flatc /usr/local/bin/flatc
COPY --from=flatbuffer_build /usr/local/include/flatbuffers /usr/local/include/flatbuffers
COPY --from=flatbuffer_build /usr/local/lib/libflatbuffers.a /usr/local/lib/libflatbuffers.a
COPY --from=flatbuffer_build /usr/local/lib/cmake/flatbuffers /usr/local/lib/cmake/flatbuffers

COPY --from=flatbuffer_build /flatcc/bin/flatcc /usr/local/bin/flatcc
COPY --from=flatbuffer_build /flatcc/include/flatcc /usr/local/include/flatcc
COPY --from=flatbuffer_build /flatcc/lib/*.a /usr/local/lib/

ARG FLATBUFFERS_USE_CLANG="false"
ARG FLATBUFFERS_ARCHIVE_BASE_URL="https://api.github.com/repos/google/flatbuffers/tarball"
ARG FLATBUFFERS_ARCHIVE_TAG="master"
ARG FLATBUFFERS_BUILD_TYPE="Release"
ARG FLATCC_ARCHIVE_BASE_URL="https://api.github.com/repos/dvidelabs/flatcc/tarball"
ARG FLATCC_ARCHIVE_TAG="master"

LABEL maintainer="Evan Wies <evan@neomantra.net>"
LABEL FLATBUFFERS_IMAGE_BASE="${FLATBUFFERS_IMAGE_BASE}"
LABEL FLATBUFFERS_IMAGE_TAG="${FLATBUFFERS_IMAGE_TAG}"
LABEL FLATBUFFERS_USE_CLANG="${FLATBUFFERS_USE_CLANG}"
LABEL FLATBUFFERS_ARCHIVE_BASE_URL="${FLATBUFFERS_ARCHIVE_BASE_URL}"
LABEL FLATBUFFERS_ARCHIVE_TAG="${FLATBUFFERS_ARCHIVE_TAG}"
LABEL FLATBUFFERS_BUILD_TYPE="${FLATBUFFERS_BUILD_TYPE}"
LABEL FLATCC_ARCHIVE_BASE_URL="${FLATCC_ARCHIVE_BASE_URL}"
LABEL FLATCC_ARCHIVE_TAG="${FLATCC_ARCHIVE_TAG}"

compose.yaml の作成

docker-compose を使ってコンテナに必要なオプションをまとめてしまいましょう。

次の内容で compose.yaml を作成します。 FLATBUFFERS_ARCHIVE_TAG および FLATCC_ARCHIVE_TAG は利用したい FlatBuffers コンパイラおよび flatcc の任意のバージョンを指定してください。

FLATBUFFERS_IMAGE_TAG は Debian イメージの任意のタグを指定しますが、2023年以降の Flatbuffers は bullseye-slim タグのイメージではコンパイルすることが出来なかったため、以下の例ではビルド引数を指定して上書きしています。

version: "3.8"

services:
  flatbuffers:
    container_name: flatbuffers
    build:
      context: .
      dockerfile: Dockerfile
      args:
        - FLATBUFFERS_IMAGE_TAG=bookworm-slim
        - FLATBUFFERS_USE_CLANG=true
        - FLATBUFFERS_ARCHIVE_TAG=v23.5.26
        - FLATCC_ARCHIVE_TAG=v0.6.1
    volumes:
      - .:/app
    working_dir: /app

イメージのビルド

Docker イメージをビルドする。

docker compose build flatbuffers

スキーマのコンパイル

Docker コンテナ内で flatc コマンドと flatcc コマンドの両方が使用できます。

前述の compose.yaml を使用するとカレントディレクトリ以下が /app ディレクトリに展開されるので、その作業ディレクトリ内でコンパイルを実施することが出来ます。

# Go 向けにスキーマをコンパイルする
docker compose run flatbuffers \
    flatc --go -o . common.fbs

C 言語向けに flatcc コマンドを使用することも出来ます。

# C 向けにスキーマをコンパイルする
docker compose run flatbuffers \
    flatcc --common --reader --builder -o . common.fbs

Discussion