3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OCI Container Instanceにexec機能を作る

3
Last updated at Posted at 2026-08-09

概要

Oracle Cloud Infrastructure(OCI)のコンテナサービス Container Instance(CI)には、AWS ECS Exec のような標準の対話型コマンド実行機能がありません。そのため、通常は確認したい情報を標準出力や標準エラー出力へ出力して確認する必要があります。しかし、特に構築・検証フェーズでは、Shellを使ってコンテナ内の状態やファイルを確認したい場面が多くあります。
そこで本記事では、FSS 上の command.txt を定期的に監視する軽量なエージェントをコンテナ内で動作させ、指定したコマンドを実行して結果を出力する「Run command」の仕組みを検証した内容を紹介します

構成

File Storage Service (FSS)を作成して、Mount TargetをContainer Instance(CI)と操作VMそれぞれ配置します
FSS上にciagent ディレクトリを作成し、管理ファイルを配置します。

ファイルのそれぞれの役割は次のとおりです。

  • runcmdagent.sh
    • Run commandエージェント
      command.txtに記載されたコマンドを60秒毎に読み込み、state.txtのハッシュ値と比較して前回と変更があった場合はコマンドを実行、結果をoutput.txtに保存
  • command.txt
    • 実行したいコマンドを記述するファイル
  • output.txt
    • Run commandエージェントの実行結果
  • state.txt
    • 最後に実行したcommand.txtのSHA-256ハッシュ値
  • runcmdagent.log
    • runcmdagent.sh 自身の動作ログ

事前準備

File Storage

File StorageおよびFile Storage Mount Targetを作成します

Run commandエージェント作成

コマンドを実行するエージェントを作成しFSSのディレクトリciagentに配置します

runcmdagent.sh
#!/bin/sh
# エラー発生時にスクリプトを即時終了
set -eu

# 各種ファイルパスとログの最大行数の定義
BASE="/mnt/fss/ciagent"
CMD_FILE="$BASE/command.txt"
OUT_FILE="$BASE/output.txt"
STATE_FILE="$BASE/state.txt"
LOG_FILE="$BASE/runcmdagent.log"
MAX_LINES=100

# エージェントの起動ログを記録
echo "===== $(date -Iseconds) =====" >> "$LOG_FILE"
echo "agent started pid=$$" >> "$LOG_FILE"

# 外部からのコマンド実行指示を監視する無限ループ
while true; do
  # command.txtが存在する場合のみ処理を実行
  if [ -f "$CMD_FILE" ]; then
    # 現在のcommand.txtのハッシュ値(SHA-256)を取得
    current_hash="$(sha256sum "$CMD_FILE" | awk '{print $1}')"
    # 前回実行時のハッシュ値を読み込む(ファイルがない場合は空)
    last_hash="$(cat "$STATE_FILE" 2>/dev/null || true)"

    echo "poll $(date -Iseconds) current=$current_hash last=$last_hash" >> "$LOG_FILE"

    # ハッシュ値が異なれば(=コマンドが新しく更新されていれば)実行
    if [ "$current_hash" != "$last_hash" ]; then
      # 実行するコマンドの中身を読み込む
      cmd="$(cat "$CMD_FILE")"

      # 出力ファイルに実行日時とコマンドを記録
      {
        echo "===== $(date -Iseconds) ====="
        echo "\$ $cmd"
      } >> "$OUT_FILE"

      # コマンドの失敗でエージェント自体が落ちないよう一時的にset +eにする
      set +e
      sh -lc "$cmd" >> "$OUT_FILE" 2>&1
      rc=$? # コマンドの終了コードを保持
      set -e

      # 終了コードを出力ファイルに追記
      {
        echo "[exit=$rc]"
        echo
      } >> "$OUT_FILE"

      # 今回実行したハッシュ値を状態ファイルに保存して完了とする
      printf '%s\n' "$current_hash" > "$STATE_FILE"
      sync
    fi
  fi

# runcmdagent.log rotation
if [ -f "$LOG_FILE" ]; then
  lines=$(wc -l < "$LOG_FILE")
  if [ "$lines" -gt "$MAX_LINES" ]; then
    KEEP_LINES=$((MAX_LINES / 2))
    tail -n "$KEEP_LINES" "$LOG_FILE" > "$LOG_FILE.tmp"
    mv "$LOG_FILE.tmp" "$LOG_FILE"
  fi
fi

# Polling
  sleep 60
done

実行コマンド作成

実行したいコマンドを記述するファイルを作成しFSSのディレクトリciagentに配置します
例えば以下のように設定します

#01
ps aux

Container Instancesの作成

Container Instancesの定義ファイルを作成します
起動コマンドにsh /mnt/fss/ciagent/runcmdagent.shを追加することによりエージェントを起動します

ci_nginx-ciagent.json

## Replace << >> with the appropriate value
{
  "compartmentId": "<<ocid1.compartment.oc1..*******>>",
  "displayName": "nginx-ciagent",
  "availabilityDomain": "<<availabilityDomain>>",
  "shape": "CI.Standard.E4.Flex",
  "shapeConfig": {
    "ocpus": 1.0,
    "memoryInGBs": 1.0
  },
  "vnics": [
    {
      "subnetId": "<<ocid1.subnet.oc1.*******>>",
      "privateIp": "<<Private IP>>",
      "isPublicIpAssigned": false
    }
  ],
  "containers": [
    {
      "displayName": "nginx",
      "imageUrl": "docker.io/library/nginx:stable-alpine",
      "command": ["/bin/sh", "-c"],
      "arguments": ["sh /mnt/fss/ciagent/runcmdagent.sh & exec nginx -g 'daemon off;'"],
      "volumeMounts": [
        {
          "volumeName": "shared-fss",
          "mountPath": "/mnt/fss",
          "isReadOnly": false
        }
      ]
    }
  ],
  "volumes": [
    {
      "name": "shared-fss",
      "volumeType": "OCI_FSS_FILE_SYSTEM",
      "mountTarget": {
        "ociFssMountTargetType": "OCID",
        "id": "<<ocid1.mounttarget.oc1.*******>>"
      },
      "export": {
        "ociFssExportType": "OCID",
        "id": "<<ocid1.export.oc1.*******>>"
      },
      "security": {
        "auth": "SYS",
        "isEncryptedInTransit": true
      },
      "mountCommand": {
        "mountOptions": [
          { "option": "hard" },
          { "option": "noac" },
          { "option": "retrans", "value": "11" }
        ]
      },
      "subnetId": "<<ocid1.subnet.oc1.*******>>"
    }
  ]
}

OCI CLIコマンドでCI作成実行します

$ oci container-instances container-instance create --from-json file://ci_nginx-ciagent.json --debug

動作確認

  • FSS確認
    コマンドが正常に実行されていればoutput.txt,state.txtおよびruncmdagent.logが作成されます
$ ls -lart /mnt/fss/ciagent
total 73
drwxrwxrwx 3 root root    12 Aug  5 18:36 ..
-rw-r--r-- 1 root root  1211 Aug  9 04:10 runcmdagent.sh
-rw-rw-r-- 1 root root    25 Aug  9 15:19 command.txt
-rw-r--r-- 1 root root 24832 Aug  9 15:20 output.txt
-rw-r--r-- 1 root root    65 Aug  9 15:20 state.txt
drwxr-xr-x 2 root root     5 Aug  9 23:23 .
-rw-r--r-- 1 root root 12528 Aug  9 23:45 runcmdagent.log

実行したいコマンドはcommand.txtに設定しています

#01
ps aux

コマンド実行結果がoutput.txtに出力されています

$ tail /mnt/fss/ciagent/output.txt
$ #01
ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 nginx: master process nginx -g daemon off;
    7 root      0:00 sh /mnt/fss/ciagent/runcmdagent.sh
    8 nginx     0:00 nginx: worker process
    9 nginx     0:00 nginx: worker process
   19 root      0:00 ps aux
[exit=0]

コマンド内容を変更すれば実行してoutput.txtに追記出力します

まとめ

この方法により、構築・検証フェーズで必要な確認作業を、コンテナへログインせずに実施できます。実行結果、状態管理、エージェントの動作ログを分けて保存することで、確認しやすく運用しやすい構成にできました
OCIでは標準機能だけでECS Exec相当の機能は得られませんが、FSSとShellスクリプトを組み合わせることで、実用的な代替手段を作れることが分かりました
本構成は検証をスムーズに進めるための手軽な代替手段として非常に有効ですが、FSSへの書き込み権限がそのままコンテナ内の任意コード実行につながるため、FSSへのアクセス制限やファイルの権限設定等利用する環境や権限管理には十分にご注意ください

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?