Docker

Dockerコンテナ上のファイルをローカルにコピーする

コンテナのビルド時に、コンテナ上のサーバにファイルを配備するには Dockerfile を利用すると楽です。

RUN でコマンドを定義できますし、ENV で環境変数の設定もできます。

今回はコンテナ上の C 言語で書かれたプログラムを gcc でコンパイルして、そのコンパイルされたファイルをローカルにコピーする方法を紹介します。

ローカルにファイルをコピーする目的

コンテナ上で作成した成果物をローカルにコピーする機会はあまりないと思いますが、今回は以下のような用途で利用しました。

コンパイルしたいCのプログラムがある
コンパイルしたものをPHPから利用したい
今後はコンパイル済のものをそのまま配備したい

コンテナ構築時に C のプログラムをコンテナ側にコピーして gcc コマンドで毎回コンパイルしてもいいのですが、PHP が動作するコンテナの Docker 管理下では C のプログラムを管理したくなかったのでこのようにしてみました。

ただし、最初の 1 回は同じ OS 上でビルドする必要があるので最初だけコンテナ上で gcc をします。

利用するコンテナパッケージ

本当は Nginx と PHP の組み合わせが好きなのですが、それぞれ別のコンテナで立ち上げてリバースプロキシで接続するのも嫌だったので、以下のパッケージを DockerHub から利用することにしました。

このパッケージの OS は AlpineLinux6.4 なので、そこに最初から組み込まれている gcc でビルドします。

Java や Kotlin などで SpringBoot のフレームワークを使って動かしている場合は、Linux なら so(シェアードオブジェクト)、Mac なら dylib(ダイナミックライブラリ)を作って JNA や JNI のインタフェースを利用して使用します。

PHP なら exec() や system() でサクっと呼べるので、out ファイルの生成だけでライブラリ化する必要はありません。

コンテナからローカルへのコピー

では、コンテナのシェルにログインしてみます。

コンテナ側の Linux で早速コンパイルをします。

コンパイル結果の rilakkuma.out をローカルにコピーするため、コンテナからログアウトします。

ローカルからは以下の cp オプションが使えます。

まずは、コピー元のコンテナの「コンテナID」を取得します。

「コンテナID」をメモったらコピーします。

ちなみに、コピー元とコピー先の順番を逆にすれば、ローカルからコンテナへファイルコピーもできます。

これで、rilakkuma.out を PHP 側の Dockerfile ビルド時にコンテナ上に配備するようにすれば OK です。