DockerでC++環境を作った時のメモ
元々はC++でちょっとしたtoolを作っていたのだけれど、Mac上でのclangとboostのversion問題にぶつかってうまく解決出来なかったので、思い立ってDockerで開発環境組もうか、となった。
で、人に教えてもらいながら作ったものが以下。
ということで以下そのときの覚書。
Dockerに関する調べ物
まずもってDockerについてぼんやりとしか知らない。 これを使ったのもかつてboot2dockerでVirtualBoxを用いてVM立ち上げていた頃のこと。 再学習が必要なのでは? ということでしてみた。
現時点で把握していること
Dockerの実行構成の理解が曖昧なので整理。正確にはDockerを使うときにimageとcontainerがあるけれど、これらの関係。 いまのところの理解としてはVirtualBoxなどのVM上でimageとなるOSを起動してそこでContainerを動かしているという理解だけど、今はVirtualBoxいらないよねとか、じゃあそこは何が代替しているんだろうとか、Dockerfileで最初に生成されるのはimageであってContainerではない? とか、そのあたりがぐちゃぐちゃになっている。
ImageとContainerについて
ContainerがOSのresouceをうまくnamespaceみたく分割して利用しているものなのはわかる。
だから任意のOSのContainerを動かしたいという場合は、imageから起動したVMが必要だし、VM上でContainerを立ち上げるしかない。
で、Dockerfileは最初baseとなるimageを落としてからいろいろinstallして、その結果として新しいimageを作っている……のか?
Docker(ドッカー)イメージはコンテナの元だ。例えば、MySQLを運用するコンテナはMySQLイメージで起動する。ドッカーイメージはDockerfile (ドッカーファイル)で定義する。
それでいいらしい。ではDockerfileに関する謎は解けた。
VMについて
次、mac上でいろんなimageを動かしている方法。 昔はboot2ddockerを用いてvirtualboxを利用していたけれど、今はそれは必要ない。 じゃあ何がその代わりをしているんだっけ。結構前にmac標準でそういう機能が入ったと思うんだけど。
ああ文字列には見覚えがある。
Appleがついに公式にサポートした仮想化技術Hypervisor.frameworkを使って、FreeBSDのbhyveをOS Xにポートしたxhyveというものが以前GitHubにされました。
The xhyve hypervisor is a port of bhyve to OS X. It is built on top of Hypervisor.framework in OS X 10.10 Yosemite and higher, runs entirely in userspace, and has no other dependencies. It can run FreeBSD and vanilla Linux distributions and may gain support for other guest operating systems in the future.
うーん? hypervisorってそういえば何だっけ。 ぼんやりとVMの管理のためのツール的なものだと思っていたけどもしかしてVM環境自体も担っている?
ハイパーバイザー型は、サーバーへ直接インストールし仮想マシンを稼働させる方式で、ESXi、Hyper-V、Xen などが分類されます。ホストOSを必要としないためハードウェアを直接制御することができ、仮想マシンの速度低下を最小限に抑えることができます。また、複数の仮想マシンを効率よく稼働させるための様々な仕組みが盛り込まれています。
ハードウェア上でまず別のOSが稼働し(このOSをホストOSと呼ぶ)、その上でハイパーバイザが(ホストOSのアプリケーションとして)稼働し、更にはハイパーバイザの上で更に別のOS(このOSをゲストOSと呼ぶ)を稼働させる方法である。狭義においては、Type 2はハイパーバイザには含まれない。
ああ。そういうこと。
ということで事前知識としてはこんな感じでいいか。
環境構築
少しだけ解説すると、file構成は以下の通り。
Name | Description |
---|---|
/doc | 開発時の覚書をMarkdownで書きためている場所。きっと整理すればManualになったり開発記録になったりする。 |
/etc | containerで利用するconfiguration fileやdocker関連のfileとかが置いてある。 |
/src | 開発するprogramのsource codeは全部ここ。ここだけ取り出せばそれ単体で開発対象が丸ごと持って行けるというイメージ。 |
で、どう説明していこうか
いや使い方を説明するなら
/etc/docker-compose/docker-compose.tpl
を編集して、- 変数の書き換えの定義などをtop directoryのMakefile内の
.docker-compose.yml
あたりのcommandとして用意して、 make dup
すれば.docker-compose.yml
とか生成してcontainer起動するので、make dlogin
とかその他のcommand使って普通にdockerを使えばいい
というものなんだけど。ここで話したいのはそういう話しじゃなくてどうやって作っていったかの七転八倒なので(何故そっちを……)。
よし。
- Dockerfileを作った時の悲喜交々
- .docker-compose.ymlをいじっていった時の苦労
- その他
くらいの感じで話してみようか。
Dockerfileの作成
C++開発用のDockerfileの作成だけど、基本的にはgccとmakeとboostが入っていればいい。
と思ってたけどそういやgdbとかstraceとかvalgrindとかも欲しいな。この時点ではDockerでgdbとか動かせるのか? という疑問もあったけど(daemon作るつもりだったから……。つまり起動してからattacheしないと駄目でしょ? あれ、Dockerってそういうことできたっけ? 単純に一つのapplicationを起動させるだけなら出来るって知ってるけど、的な悩み)、まあそれはあとでDocker-Composeでいじる時に悩むことにする。
baseとしたimageはcentos7。
# RUN yum -y install gcc \ # gcc-c++ \ # automake \ # make \ # libtool \ # cppunit \ # cppunit-devel \ # valgrind \ # gdb \ # strace
最初はこのcomment outされているところだけつくって、docker build -t test_gcc ./etc/docker-compose/images/gcc
とかcommand叩いて無事作れるか試していた。
で、yumだけなので動いて当然として、できればgccも最新のものとか使いたいなあという欲望が出てくる。
そしたらあるわけです。便利なものが。
最近はscl(Red Hat Software Collections )というものがあって、それで簡単に別のgcc環境が作れてしまう。すげーと感動しながら入れる。
RUN yum -y install gcc \ gcc-c++ \ automake \ make \ libtool \ cppunit \ cppunit-devel RUN yum install -y centos-release-scl \ centos-release-scl-rh RUN yum install -y devtoolset-7-gcc \ devtoolset-7-gcc-c++ \ devtool \ devtoolset-7-valgrind \ devtoolset-7-strace devtoolset-7-gdb \ devtoolset-7-gcc-gdb-plugin
yumでとりあえず最低限いりそうなものだけいれておいて、devtoolset-7-gccをいれる。
gccとgcc-c++はいるっけ? libtoolも。まあいれとこう。<最低限とは何だったのか
これ開発環境だからこうだけど本番環境ならそもそもboostくらいしかいらない気がするのでちょっとcontainerの作り方がめんどいかもしれない。まあ今は開発環境のものだけなのでいいか。
あとはboostだけどこれはまあ仕方ないので素直にbuildした。
RUN yum -y install wget ARG boost_version=1.66.0 ARG boost_file=boost_1_66_0 RUN cd /tmp \ && scl enable devtoolset-7 bash \ && wget https://dl.bintray.com/boostorg/release/${boost_version}/source/${boost_file}.tar.gz --no-check-certificate \ && tar xfz ${boost_file}.tar.gz \ && rm ${boost_file}.tar.gz \ && cd ${boost_file} \ && ./bootstrap.sh \ && ./b2 --without-python --prefix=/usr -j 4 link=shared runtime-link=shared install \ && cd .. \ && rm -rf ${boost_file} \ && ldconfig
これで終わり。開発環境となるdocker imageはこれで作れた。
Docker-Composeの設定
で、次はDocker-Compose用に.docker-compose.yml
を作成する。結果はこの通り。
今回作ったcontainerの意味するところは以下の通り。
Name | Description |
---|---|
data | busybox。hostの./src以下をmountするためのContainer。 |
gcc | gccのbuild/実行用のContainer。data containerをvolumeとしてmountする。vmみたくloginしての利用も出来る。gdbなどを使うときのため。 |
build | 上に同じく。ただしこちらはloginすることは想定していない。 |
server | 生成したserver applicationを実行するための設定。本来ならこれは専用にcontainer作るべきな気がする。gccとかvalgrindとかいれてないやつ。 |
ちょっと京菜事をしているのはdataというcontainerをよそがmountしているという処理。
これはどういうことか言えば、複数のcontainerが同じdirectoryをmountしたりしたらとても面倒なことになりそうなので、hostのdirectoryをmountする作業は全部一つのcontainerに任せてしまいましょう、という話。
あとはdocker-composeでsetupすれば通る。
$ docker-compose -f .docker-compose.yml up -d data $ docker-compose -f .docker-compose.yml up -d gcc
あとはよく使うcommandをmakefileにまとめて終わり。
他のserviceも立ち上げたい場合
他のserviceも立ち上げたい場合はこれ、./etc/
以下にconfigとかいれておいて、.docker-compose.yml
に専用のcontainerを定義すればいい。
imageも別途作る必要があるけれど、gccの開発環境のDockerfileを参考に適当に作る感じになる。