概要
C/C++のプログラムをDockerコンテナでビルド、動作させる際の軽量な方法を紹介します。Dockerの実行環境の構築方法としては、Go、Python、Javaなどに関しては情報が多くあるのですが、C/C++に対しての良いDocker環境の構築方法の記事がなかったので共有します。
最近は、Dockerにmulti stage buildという機能があり、2段階でのDockerイメージの作成を行います。主に、Dockerfile内で一段階目で実行ファイルを作成するためのビルド環境を作成し、二段階目で、作成した実行ファイルを実行するためだけの軽量ランタイム環境を最終的なDockerイメージとして保存することが主流になってきています。これらをC/C++プログラムにも適用します。
また、最近ではdistolessイメージという、実行に特化して機能が限定された、軽量でセキュアなDockerイメージをGoogleが公開しております。詳しくは、こちらで詳しく解説している方がいらっしゃいます。この環境を使いたいのですが、C/C++では実行時にライブラリをリンクさせる動的リンクライブラリを使用する場合があり、その場合は、追加でパッケージを入れることが難しいdistoless環境ではプログラムの実行ができません。そのため、ここでは、他に軽量と言われていて、パッケージ追加など基本的な機能があるディストリビューションのAlpine Linuxを使います。Alpine Linuxについて詳しくは、こちらで解説されている方がいらっしゃいます。
もし、より良いDockerの実行環境があればコメント頂ければ幸いです。
Dockerfileと実行方法
まず、Dockerfileとその実行方法を示して、そのあとにDockerfileの意味を一つ一つ説明していきます。以下のDockerfileを作成します。
# ---------------
# Image creation stage
FROM alpine AS dev
# Copy required files
COPY ./simulation.cpp /app/
# Set the working directory
WORKDIR /app
# Install required packages
RUN apk add --quiet --no-cache \
librdkafka-dev \
alpine-sdk \
nlohmann-json
# Build
RUN g++ simulation.cpp -o simulation -lrdkafka++
# ---------------
# Image creation stage
FROM alpine AS prod
# Set the working directory
WORKDIR /app
# Copy required files
COPY --from=dev /app/simulation /app/simulation
# Install required packages
RUN apk add --quiet --no-cache \
librdkafka-dev
# ---------------
# Execution
CMD ["./simulation"]
Dockerイメージのビルドと起動を行います。同じディレクトリにコンパイル、実行したいプログラムsimulation.cpp
を置いておきます。
docker build -t simulation:1.0 .
docker run -it simulation:1.0
作成された実行環境のDockerイメージが以下のsimulation
で、参考として、<none>
がビルド環境、ubuntu
がubuntuイメージです。simulation
が非常に軽量なのがわかります。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
simulation 1.0 3593bd8b0d91 About a minute ago 13.1MB
<none> <none> 64d875c1b27f 11 minutes ago 227MB
ubuntu latest 7e0aa2d69a15 3 weeks ago 72.7MB
#Dockerfileの説明
alpineのイメージを作成し、dev
とタグを付けます。
# Image creation stage
FROM alpine AS dev
ローカルの現在のディレクトリからdevの/app/のディレクトリに対してsimulation.cppをコピーします。
# Copy required files
COPY ./simulation.cpp /app/
作業用ディレクトリを/appに変更します。(cdのようなものです。)
# Set the working directory
WORKDIR /app
ビルドに必要なパッケージをインストールします。私のsimulation.cpp
のビルドに必要なパッケージを記載しているだけなので、パッケージ部分は任意に書き換えて下さい。no-cashe
を指定することで、パッケージをキャッシュしない設定となり、通常イメージサイズ削減のため指定する。quiet
は特にapk add
の出力などが必要ない時に指定する。
# Install required packages
RUN apk add --quiet --no-cache \
librdkafka-dev \
alpine-sdk \
nlohmann-json
Docker内でコンパイルを行う。-lrdkafka++
により動的リンクするライブラリを指定する。
# Build
RUN g++ simulation.cpp -o simulation -lrdkafka++
次に、実行用のDockerイメージを作成する。prod
とタグを付ける。
# Image creation stage
FROM alpine AS prod
作業用ディレクトリをprod
の/appとする。
# Set the working directory
WORKDIR /app
dev
のイメージから実行ファイルをprod
にコピーする。
# Copy required files
COPY --from=dev /app/simulation /app/simulation
動的リンクが必要なライブラリのみをインストールする。
# Install required packages
RUN apk add --quiet --no-cache\
librdkafka-dev
実行ファイルを実行する。
# Execution
CMD ["./simulation"]
以上です。