コンテナ内でコマンド実行する方法
目的
コンテナ内でコマンド実行する方法について簡単に整理する。
背景
コンテナの使い方
コンテナは仮想マシンと異なり、汎用的なOSを提供するのではなく、特定の仕事(例えばWebサービスの提供)を実行する目的で存在する*1。1コンテナ1プロセスが基本である。
では、コンテナ内で実行するプロセスはどのように指定されるのであろうか。以降でdockerを例に記載する。
コンテナ実行までの流れ
まず、実行するdockerコンテナがどのように作られるかの流れをおさらいする。
まず、Docker Hub等のコンテナレジストリから、イメージを取得する。取得したイメージをそのまま使うケースもあるが、実際にはカスタマイズがしたいので、Dockerfileと呼ばれる指示書のようなもので、そのイメージに対し各種コマンドを実行し、コンテナイメージを作成する。そのイメージをdocker run
コマンドで実行する。
コンテナ内で実行するプロセスの指定
コンテナ内で実行するプロセスは以下のいずれかの方法で指定できる。
- Dockerfile内で命令を書く
- docker run
コマンド実行時のオプションで指定する
実際は上記を組み合わせて使うことで、より柔軟に実行するプロセスを指定できる。
Dockerfileの命令とdocker run
命令のオプション
大雑把には、次のように理解できる。
- ENTRYPOINT
:docker run
実行時に行われるコマンド*2
- CMD
:コマンドのデフォルト引数
が、docker run
コマンド実行時のオプション指定と組合せると上記の表現では理解できない挙動があるのでもう少し書く。ENTRYPOINT
とCMD
の有無で場合わけする。
ここからわかる通り、基本はコマンドは1つしか実行できない。1コンテナ1プロセスという考え方ともマッチする。とはいえ、複数実行したいケースも当然ある。その方法は別記事にて記載する。
RUN
命令について
なお、DockerfileにはRUN
命令もあるが、毛色が違うので分けて考えておくのがよい。これもコンテナ内で実行するコマンドを指定しているという面では似ているが、apt-get
やyum
等、コンテナ実行のために必要なパッケージを準備するものとして使われる。コンテナが担う主のタスクそのものを実行することはできない。つまりdocker run
時には実行されない。
Kubernetesにおけるコンテナの実行
Kubernetesのpodやdeploymentのmanifestにおいて、コンテナについてcontainers:
フィールド内で記述できるが、dockerにおけるENTRYPOINTとCMDに対応するフィールドがある。
ENTRYPOINT
に対応するのがcommand:
で、CMD
に対応するのがargs:
である。CMD
とcommand
が対応するではないので注意(紛らわしい)。Kubernetesでは、コンテナを実行するときは例えばkubectl exec ポッド名/コンテナ名 -it -- 引数(コマンドやオプション)
で行うが、このときの引数部とcommand:
やargs:
の関係はdockerと同じである。
例:podのmanifest
apiVersion: v1 kind: Pod metadata: name: command-demo spec: containers: - name: command-demo-container image: ubuntu command: ["ls", "-l"] args: ["-a", "--color"]
例:実行例(ls -l -f
が実行される)
$ kubectl exec command-demo -it -- -f
参考にしたもの
Kubernetes完全ガイド impress top gearシリーズ | 青山 真也 | 工学 | Kindleストア | Amazon
Udemy - Certified Kubernetes Administrator(CKA)with Practice Tests
Docker入門(第四回)~Dockerfileについて~ | さくらのナレッジ
DockerfileのCMDとENTRYPOINTを改めて解説する - Qiita