OCIコンテナインスタンスをコマンド操作

# 概要
Oracle Cloud Infrastructure(OCI)の[コンテナインスタンス(CI)](https://docs.oracle.com/ja-jp/iaas/Content/container-instances/overview-of-container-instances.htm)を利用した例です。

コンテナインスタンスは比較的簡単にコンテナを起動できるサービスでメリット・デメリットは以下かと思います。
- メリット
	- OCI内のコンテナレジストリ以外に外部コンテナレジストリからイメージをPullして実行可能
	- Kubermetesのコマンドを覚える必要がない
	- OSやDocker/Podmanの管理が不要
	- 簡単に起動や削除が可能
	- Functionsのように連続実行時間を気にしなくていい
- デメリット
	- 永続ディスクがないので外部保管の仕組みを考える必要がある
	- 最低1コア(=1OCPU)でも月3,000円くらいかかるので使わない時間は停止や削除が必要

今回は検証用のコンテナを準備してOCI CLI機能で起動から削除まで行いました
# 構成
sshアクセスして確認するためのコンテナイメージを作成しCIで稼働します
- コンテナイメージはコンテナレジストリにPush
- portは2222をexpose
- emptydirを設定
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/d7a15f80-3268-4abe-4dd8-2052fa0b7061.png">

# 準備
コンテナはsshアクセスして確認するためコンテナイメージにubuntu 24.04を使用してsshログインできるようにしました。
Dockerfileは以下のとおりです。sshを可能にする以外にもネットワーク関連の便利なコマンドもinstallしています。

```Dockerfile
FROM ubuntu:24.04

RUN apt-get update && apt-get install -y openssh-server && apt-get install -y iputils-ping net-tools
RUN apt-get install -y telnet
RUN mkdir /var/run/sshd
RUN echo 'root:【パスワード】' | chpasswd
RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN sed -i 's/#PasswordAuthentication/PasswordAuthentication/' /etc/ssh/sshd_config
RUN sed -i 's/#Port 22/Port 2222/' /etc/ssh/sshd_config
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd

EXPOSE 2222
CMD ["/usr/sbin/sshd", "-D"]
```
コンテナイメージをOCIのコンテナレジストリにPushしておきます。


# OCI CLIによるコンテナインスタンスの操作
[コンテナ・インスタンスの作成](https://docs.oracle.com/ja-jp/iaas/Content/container-instances/creating-a-container-instance.htm)等を参考にコマンドを作成・実行します

## CI作成

- パラメータファイルを作成
```ci002.json
{
  "availabilityDomain": "TGjA:AP-TOKYO-1-AD-1",
  "compartmentId": "【コンパートメントOCID】",
  "containerRestartPolicy": "ALWAYS",
  "display-name": "ci002",
  "containers": [
    {
      "imageUrl": "nrt.ocir.io/【コンテナレジストリ】",
      "display-name": "ubuntussh24",
      "volumeMounts": [
        {
          "mountPath": "/volume01",
          "volumeName": "volume01"
        }
      ]
    }
  ],
  "shape": "CI.Standard.E4.Flex",
  "shapeConfig": {
    "memoryInGBs": 1.0,
    "ocpus": 1.0
  },
  "vnics": [
    {
      "nsgIds": [
        "【Network Security Group OCID】"
      ],
      "privateIp": "10.105.2.73",
      "subnetId": "【サブネット OCID】"
    }
  ],
  "volumes": [
    {
      "name": "volume01",
      "volumeType": "EMPTYDIR"
    }
  ]
}
```

- コンテナインスタンス作成コマンドを実行
```
[user@linux]$ oci container-instances container-instance create --from-json file://ci002.json
```

- 起動したらログインしてemptyDirにアクセスできることを確認します
```
[user@linux]$ ssh root@10.105.2.73 -p 2222
root@10.105.2.73's password:
root@localhost:/# echo test > /volume01/test.txt
root@localhost:/# cat /volume01/test.txt
test
root@localhost:/#
```

## CIステータス確認
- ステータス確認のShellを作成

```CIGetState.sh
#! /bin/bash
CINAME="$1"
CIOCID=`oci container-instances container-instance list --compartment-id 【コンパートメントOCID】 | jq '.data.items[] | select(."display-name" == "'"$CINAME"'" and ."lifecycle-state" == "ACTIVE")' | jq -r .id`

if [ -z "$CIOCID" ]; then
  CIOCID=`oci container-instances container-instance list --compartment-id 【コンパートメントOCID】 | jq '.data.items[] | select(."display-name" == "'"$CINAME"'" and ."lifecycle-state" == "INACTIVE")' | jq -r .id`
  if [ -z "$CIOCID" ]; then
    echo "Neither Active nor Inactive"
    exit 0
  fi
fi

CISTATE=`oci container-instances container-instance get --container-instance-id $CIOCID | jq -r '.data."lifecycle-state"'`
echo $CISTATE
```
- 実行結果
```
[user@linux]$ /bin/bash CIGetState.sh ci002
ACTIVE
```

## CI停止
CI停止することにより課金は停止するので停止を実施します。
ただしCIを停止すると、15GBのエフェメラル・ストレージ上のデータは失われます。
[コンテナ・インスタンスの停止](https://docs.oracle.com/ja-jp/iaas/Content/container-instances/stopping-a-container-instance.htm)

- ステータス確認のShellを作成します

```CIStop.sh
#! /bin/bash
CINAME="$1"
CIOCID=`oci container-instances container-instance list --compartment-id 【コンパートメントOCID】 | jq '.data.items[] | select(."display-name" == "'"$CINAME"'" and ."lifecycle-state" == "ACTIVE")' | jq -r .id`
oci container-instances container-instance stop --container-instance-id $CIOCID
```

- 実行結果
```
[user@linux]$ /bin/bash CIStop.sh ci002
{
  "opc-work-request-id": "ocid1.computecontainerworkrequest.oc1.*****"
}

[user@linux]$ /bin/bash CIGetState.sh ci002
INACTIVE
```

## CI再スタート
停止したCIを再スタートします

```CIRestart.sh
#! /bin/bash
CINAME="$1"
CIOCID=`oci container-instances container-instance list --compartment-id 【コンパートメントOCID】 | jq '.data.items[] | select(."display-name" == "'"$CINAME"'" and ."lifecycle-state" == "INACTIVE")' | jq -r .id`
oci container-instances container-instance restart --container-instance-id $CIOCID
```
- 実行結果
```
[user@linux]$ /bin/bash CIRestart.sh ci002
{
  "opc-work-request-id": "ocid1.computecontainerworkrequest.oc1.*****"
}

[user@linux]$ /bin/bash CIGetState.sh ci002
ACTIVE
```


## CI削除
不要になったCIを削除します

```CIDelete.sh
#! /bin/bash
CINAME="$1"
CIOCID=`oci container-instances container-instance list --compartment-id 【コンパートメントOCID】 | jq '.data.items[] | select(."display-name" == "'"$CINAME"'" and ."lifecycle-state" == "ACTIVE")' | jq -r .id`
oci container-instances container-instance delete --force --container-instance-id $CIOCID
```
- 実行結果
```
[user@linux]$ /bin/bash CIDelete.sh ci002
{
  "opc-work-request-id": "ocid1.computecontainerworkrequest.oc1.*****"
}

[user@linux]$ /bin/bash CIGetState.sh ci002
Neither Active nor Inactive
```