今回初めてテックブログに投稿します ビデオリサーチの佐藤です。
普段は協力会社さんの開発管理をしつつ、必要に応じて随所でプログラミングしたり、インフラ構築のレビューをしたりという日々を送っています。
今回は、PoCで利用するプロトタイプ作成時に、Dockerファイルを書いていて気づいたハマりポイントをご紹介します。 内容としてはコンテナ実行時にコンテナ内で実行するpythonに引数を渡す方法になります
やりたい事と結論
やりたい事
Dockerで実行するpythonに任意の引数を与えて実行したい
結論
コンテナ実行時、環境変数に引数を渡す
- Dockerfile
FROM python:3 # 中略... CMD python main_file.py ${HOGE}
docker build ./ -t fuga:piyo
docker run -e HOGE="hoge" fuga:piyo
- 変数は
${}
で囲んで渡す($
だけでも良い。表記揺れしないようどちらかに合わせる) - CMDはexec形式でshを使うか、シェル形式を使う。上記例示はシェル形式。最終的にはexec形式のサンプルをご紹介します。
ポイント1:環境変数を利用する
コンテナ実行時に環境変数で引数を渡す。
docker run -e HOGE="hoge" fuga:piyo
公式ドキュメント:
docs.docker.jp
Dockerの変数といえばARGを思い浮かべますが、ARGはbuild時に利用するものなので、コンテナ実行時に変数を渡すには環境変数に持たせる必要があります。
ポイント2:Dockerfile内での変数展開の記述方法にハマらない
Dockerfile内で変数定義した場合、利用するときは
${HOGE}
or
$HOGE
処理に入れ込むときは可読性を考えて${HOGE}
のほうが好ましい。
シンプルに書ける場合は$HOGE
でも問題ない。
公式ドキュメント:
docs.docker.jp
ハマるポイントではないのですが、 後述するCMDで変数が上手く利用できていないと、変数の使い方が間違っている? CMDに値を渡す際に変数の前に$をつけるだけではだめなんだっけ?ダブルクオートで囲むんだっけ? などと試行錯誤していると、どんどん時間が吸い込まれていきます。 基本的な部分で不安を感じないようにポイントとして挙げています。
ポイント3:CMDでの変数展開
誤った実装
CMD [ "python", "${HOGE}" ]
exec形式ではシェルを呼び出さず、$HOGE の変数展開を行わないので、この実装だと${HOGE}の中身が展開されません
正しい実装
CMD ["sh", "-c", "python main_file.py ${HOGE}"]
or
CMD python main_file.py ${HOGE}
exec形式を使うか、シェル形式を使う。(公式の推奨は前者)
公式ドキュメント:
docs.docker.jp
Sample Code
以上を踏まえてサンプルコードを書いて見ます!
やりたい事と結論ではDockerfileのCMDをシェル形式で書いていますが
サンプルコードでは公式推奨のexec形式で記載しています
- Dockerfile
FROM python:3 WORKDIR /app COPY ./src/main_file.py /app/main_file.py ENV SUB="" CMD ["sh", "-c", "python main_file.py ${SUB}"]
- main_file.py
import argparse def main(): parser = argparse.ArgumentParser() parser.add_argument("--sub", default="", type = str) args = parser.parse_args() print("https://" + args.sub + "videor.co.jp") if __name__ == "__main__": main()
サンプルコードを動かします。
まずはbuild
docker build ./ -t hoge:fuga
docker runコマンド
docker run hoge:fuga
出力結果
https://videor.co.jp
環境変数から引数を付与してのdocker runコマンド
docker run -e SUB="--sub tech." hoge:fuga
出力結果
https://tech.videor.co.jp
弊社のコーポレートサイトのURLとテックブログのURLを適宜出し分けるプログラムを注入したコンテナができました!
さいごに
いつもCMDではシェル形式で書いているのですが、Dockerの推奨だった気がするし、たまにはexec形式で書いてみるかと思って実装したところ、exec形式だと変数が展開できないことを忘れていて調べ直すに至りました。 RUNコマンドでもexec形式は使えますが、同様に変数は展開できません。 既に知ってる実装を手癖で書いていることが多いので、疑問がでた際は公式のドキュメントに立ち返って調べ直すと新しい気付きが多く得られると改めて実感しました。
ビデオリサーチでは、現在一緒にサービス開発を推進してくれる仲間を大募集しています! もしビデオリサーチに興味を持っていただいた方は、以下よりお気軽にご応募ください。