tanke25616429のアウトプット

IT技術の基本を勉強したことをアウトプットします。Linux、Kubernetes、クラウド中心です。百番煎じくらいだけど誰かの役に立てばそれはそれでうれしい。

コンテナ内でコマンド実行する方法

目的

コンテナ内でコマンド実行する方法について簡単に整理する。

背景

コンテナの使い方

コンテナは仮想マシンと異なり、汎用的なOSを提供するのではなく、特定の仕事(例えばWebサービスの提供)を実行する目的で存在する*1。1コンテナ1プロセスが基本である。

では、コンテナ内で実行するプロセスはどのように指定されるのであろうか。以降でdockerを例に記載する。

コンテナ実行までの流れ

まず、実行するdockerコンテナがどのように作られるかの流れをおさらいする。

まず、Docker Hub等のコンテナレジストリから、イメージを取得する。取得したイメージをそのまま使うケースもあるが、実際にはカスタマイズがしたいので、Dockerfileと呼ばれる指示書のようなもので、そのイメージに対し各種コマンドを実行し、コンテナイメージを作成する。そのイメージをdocker runコマンドで実行する。

f:id:tanke25616429:20200731101542p:plain
コンテナ実行までの流れ(「さくらのナレッジ Docker入門(第四回)」https://knowledge.sakura.ad.jp/15253/より引用)

コンテナ内で実行するプロセスの指定

コンテナ内で実行するプロセスは以下のいずれかの方法で指定できる。 - Dockerfile内で命令を書く - docker runコマンド実行時のオプションで指定する

実際は上記を組み合わせて使うことで、より柔軟に実行するプロセスを指定できる。

Dockerfileの命令とdocker run命令のオプション

大雑把には、次のように理解できる。 - ENTRYPOINTdocker run 実行時に行われるコマンド*2 - CMD:コマンドのデフォルト引数

が、docker runコマンド実行時のオプション指定と組合せると上記の表現では理解できない挙動があるのでもう少し書く。ENTRYPOINTCMDの有無で場合わけする。

f:id:tanke25616429:20200731111524p:plain
ENTRYPOINTなし CMDなし

f:id:tanke25616429:20200731111702p:plain
ENTRYPOINTあり CMDなし

f:id:tanke25616429:20200731111902p:plain
ENTRYPOINTなし CMDあり

f:id:tanke25616429:20200731112027p:plain
ENTRYPOINTあり CMDあり

ここからわかる通り、基本はコマンドは1つしか実行できない。1コンテナ1プロセスという考え方ともマッチする。とはいえ、複数実行したいケースも当然ある。その方法は別記事にて記載する。

RUN命令について

なお、DockerfileにはRUN命令もあるが、毛色が違うので分けて考えておくのがよい。これもコンテナ内で実行するコマンドを指定しているという面では似ているが、apt-getyum等、コンテナ実行のために必要なパッケージを準備するものとして使われる。コンテナが担う主のタスクそのものを実行することはできない。つまりdocker run時には実行されない。

Kubernetesにおけるコンテナの実行

Kubernetesのpodやdeploymentのmanifestにおいて、コンテナについてcontainers:フィールド内で記述できるが、dockerにおけるENTRYPOINTとCMDに対応するフィールドがある。 ENTRYPOINTに対応するのがcommand:で、CMDに対応するのがargs:である。CMDcommandが対応するではないので注意(紛らわしい)。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

shinkufencer.hateblo.jp

Docker入門(第四回)~Dockerfileについて~ | さくらのナレッジ

DockerfileのCMDとENTRYPOINTを改めて解説する - Qiita

Docker お勉強 03 Dockerfile - sioaji2012のブログ

Dockerfileを改善するためのBest Practice 2019年版

*1:なので、マイクロサービスアーキテクチャの議論とコンテナの議論がセットで出てくるという面があると思われる。

*2:docker run時にENTRYPOINTを上書きしたい場合は、--entrypointというオプションで指定することができる。