前までの記事で、Ubuntu に build-essential をインストールするDockerfile を書き、コンパイルをuser権限で行うようにした。コンテナ内の bash から操作することで C++ をコンパイルを行う。
前回 timtoronto634.hatenablog.com
今日は
- コンテナ起動時に引数としてcppファイルとコンパイル先までのpathを与えたらコンパイルだけコンテナでやってくれる
- docker-compose を使うのをやめてどこからでもコンパイルできるようにする
のを実装する。気ままにdockerの復習しながら進んでいく感じ。
最終的にはdocker-entrypoint.shを書いて、そこでいろいろ処理を加えたかったが(コンパイル対象のファイル名を受け取ってコンパイル後の実行ファイル名を決めるなど)、それはいったん放置。
復習
いったんコンテナ起動時に引数を与えるときの挙動を確認する。
dockerfile 内で指定した ENTRYPOINT は必ず実行し、CMD に引数を書いておくとそれがデフォルトの引数として機能する
試しに以下のdockerfileを書く
FROM ubuntu:18.04 RUN apt-get update && \ apt-get install -y build-essential ARG UID=1000 RUN useradd -m -u ${UID} docker # switch to the added user USER ${UID} ENTRYPOINT ["ls"] CMD [ "-a" ]
ビルドして引数を何も与えずに実行すると以下*1
$ docker-compose run --rm eachfile . ABC129 ABC135 ABC149 ABC156 ABC163 .. ABC130 ABC136 ABC151 ABC157 ABC165 .dockerignore #以下略
ls -a
の実行結果が得られる。ここで引数として-lを与えてみる
$ docker-compose run --rm eachfile -l total 124 drwxr-xr-x 3 docker docker 4096 Aug 11 03:50 ABC126 drwxr-xr-x 3 docker docker 4096 Aug 11 03:50 ABC129 # 以下略
ここでは`ls -l'の実行結果が得られる。
余談だが、ここでCMDを与えないでおいても、引数としてオプションを書くとしっかり実行された。また、ENTRYPOINTもCMDもDockerfile中に一つしか書けないため、複数実行したければdocker-entrypoint.sh等を書いてそれをENTRYPOINTに渡す。
コンテナ起動時に引数としてcppファイルとコンパイル先までのpathを与える
以上を踏まえて、Dockerfileには
ENTRYPOINT ["g++", "-o"] CMD ["hello_world/hello", "hello_world/hello.cpp"]
を書いておけば、docker-compose run --rm eachfile 実行ファイル名 元ファイル名.cpp
とできる。
もうわざわざbashでなかに入ってコマンドを打つ必要はない。g++
を書く代わりになる。
docker-compose を使うのをやめてどこからでもコンパイルできるようにする
ここまではdocker-compose を使って書いてきた。ボリュームのマウントの設定書くために使っていたのだが、ほんとにマウントの設定以外に利点がない。むしろ、docker-compose.ymlのファイルがあるディレクトリでしかコマンドを実行できないのがとってもめんどくさい。
そこで、マウントの部分はエイリアスを書いてあげて、どこのディレクトリからでもコンパイル用のイメージからコンテナを作成できるようにした。
$ vim ~/.bashrc
から alias g++o='docker run -v $(pwd):/codes/ --rm eachfile'
を追加。ちなみに、シングルクォーテーションでかくことに注意
参考
*1:eachfileはイメージ