C++ アプリケーションに対してのマルチステージビルドの生成

前提条件

  • git クライアント を持っていること。 本節における例では、コマンドラインベースの Git クライアントを用いることにします。 クライアントはどのようなものでも利用可能です。

概要

この節では C++ アプリケーション用のマルチステージ Docker ビルドの生成について説明しています。 マルチステージビルドは、ビルド過程でのさまざまなステージにおいて、さまざまなベースイメージを使用できるようにする Docker 機能です。 これにより最終イメージのサイズを最適化し、ビルド時の依存関係を実行時の依存関係から分離できます。

C++ などのようなコンパイル言語における標準的な方法として、コードをコンパイルするためのビルドステージと、コンパイル済みバイナリを実行するためのランタイムステージの 2 つを用意します。 こうするのは、実行時にはビルド時の依存パッケージが必要ないからです。

サンプルアプリケーションの入手

端末に Hello, World! を出力する単純な C++ アプリケーションを用いていきます。 これ行うために、本ガイドで利用するサンプルリポジトリをクローンします。

$ git clone https://github.com/dockersamples/c-plus-plus-docker.git

ここに示す例は、リポジトリ内の hello ディレクトリ配下にあります。 そのディレクトリに入って、ファイルを見てみます。

$ cd c-plus-plus-docker/hello
$ ls

以下のようなファイルが表示されます。

Dockerfile  hello.cpp

Dockerfile の確認

IDE またはテキストエディターを使って Dockerfile を開きます。 Dockerfile には Docker イメージをビルドする命令が含まれています。

# ステージ 1: ビルドステージ
FROM ubuntu:latest AS build

# C++ コードコンパイルのための build-essential インストール
RUN apt-get update && apt-get install -y build-essential

# ワーキングディレクトリの設定
WORKDIR /app

# コンテナーへのソースコードコピー
COPY hello.cpp .

# C++ コードをスタティックコンパイルし、ランタイムライブラリへの依存をなくす
RUN g++ -o hello hello.cpp -static

# ステージ 2: ランタイムステージ
FROM scratch

# ビルドステージからのスタティックバイナリのコピー
COPY --from=build /app/hello /hello

# バイナリを実行するコマンド
CMD ["/hello"]

Dockerfile にはステージが 2 つあります。

  1. ビルドステージ: このステージはイメージとして ubuntu:latest を利用し、C++ コードをコンパイルしてスタティックバイナリを生成します。
  2. ランタイムステージ: このステージは scratch イメージを利用しますが、これは空のイメージです。 ビルドステージからスタティックバイナリをコピーしてそれを実行します。

Docker イメージのビルド

Docker イメージをビルドするため、hello ディレクトリに入って以下のコマンドを実行します。

$ docker build -t hello .

-t フラグはこのイメージに対して hello という名前をつけるものです。

Docker コンテナーの実行

Docker コンテナーを起動するため、以下のコマンドを実行します。

$ docker run hello

端末に Hello, World! が出力されます。

まとめ

本節では C++ アプリケーション向けにマルチステージビルドの生成方法について学びました。 マルチステージビルドは最終イメージのサイズを最適化し、ランタイムの依存パッケージからビルド時の依存パッケージを切り離します。 本例における最終イメージにはスタティックイメージしか含まれず、ビルド時の依存パッケージは含まれていません。

イメージとして空のイメージをベースとしたため、普通にあるような OS ツールが含まれていません。 したがってコンテナー内では、たとえば ls といった単純なコマンドすら実行することはできません。

$ docker run hello ls

こうしてイメージを軽量にそしてセキュアに作り出します。