概要
Oracle Cloud Infrastructure(OCI)のContainer Instanceは継続的デプロイの機能がありません。そのためコンテンツ更新をトリガーにContainer Instanceを再起動して再Pullすることにより継続的デプロイを行う仕組みを考えました
構成
GitHubにPushするとGithub actionsに定義したstepを実行します
- Build the docker image
- Tag image as latest
- Push container image
タグはバージョン(例0.0.1)とlatestの2つ - Set up Python
- Install OCI SDK
- Configure OCI credentials
- Run Python script
Container Instanceにrestartを実施
Container Instanceは再起動時にcontainer imageのタグlatestをpull
前提
- 既存のGithub環境がある
- Container InstancesおよびContainer Registryを使用したことがある
(必要なPolicyを保有)
作成手順
OCI Container Registry repository作成
OCIコンソールやCLI等作成方法は複数ありますが今回はCLIを使用しています
## Replace << >> with the appropriate value
oci artifacts container repository create --display-name ciapp/nginx_helloworld --compartment-id <<ocid1.compartment.oc1....>>
Github Registry作成
- Github Registryはcicd-ciの名前で作成
- リポジトリ作成時に表示されたコマンドをローカルリポジトリを作成するPCで実行
echo "# cicd-ci" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin https://github.com/<<user>>/cicd-ci.git
git push -u origin main
secrets登録
GitHub Repository secretsに以下を登録します
- 対象RepositoryからSettings >> Actions secrets and variables >> Secrets
OCI_CLI_USER: OCI UserのOCID
OCI_CLI_TENANCY: OCIテナンシーのOCID
OCI_CLI_FINGERPRINT: OCI Userで追加したAPIキーFingerprintのOCID
OCI_CLI_KEY_CONTENT: OCI Userで追加したAPIキーの秘密キー
OCI_CLI_REGION: リージョン(例:ap-tokyo-1)
OKE_CLUSTER_OCID: OKEクラスターのOCID
OCI_AUTH_TOKEN: OCI Userで追加した認証トークン
ローカルリポジトリ作業
以下のファイルを作成します
~/work/github/cicd-ci
|--.git
+--.github
+--workflows
|--Build_Push.yml
|--README.md
|--Dockerfile
|--version.txt
+--conf
| +--NGINX構成ファイル
| default.conf
+--src
+--コンテンツ
index.html
FROM nginx:latest
COPY ./conf/default.conf /etc/nginx/conf.d/default.conf
COPY ./src/index.html /var/www/index.html
コンテナイメージのタグの定義
0.0.1
server {
listen 8080 default_server;
server_name localhost;
location / {
root /var/www;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
}
}
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Hello Docker</title>
</head>
<body>
<h1>Hello World ver 0.0.1</h1>
</body>
</html>
workflowはBuildとOCI Container RegistryへのPushまで行います
## Replace << >> with the appropriate value
# This is a basic workflow to help you get started with Actions
name: Build_Push
# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events but only for the "main" branch
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
env:
OCI_CLI_USER: ${{ secrets.OCI_CLI_USER }}
OCI_CLI_TENANCY: ${{ secrets.OCI_CLI_TENANCY }}
OCI_CLI_FINGERPRINT: ${{ secrets.OCI_CLI_FINGERPRINT }}
OCI_CLI_KEY_CONTENT: ${{ secrets.OCI_CLI_KEY_CONTENT }}
OCI_CLI_REGION: ${{ secrets.OCI_CLI_REGION }}
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions/checkout@v3
- name: Read image tag from file
id: read_tag
run: echo "IMAGE_TAG=$(cat version.txt)" >> $GITHUB_ENV
- name: Build the docker image
id: build-docker-image
run: docker build . --file Dockerfile --tag <<region>>.ocir.io/<<namespace>>/ciapp/nginx_helloworld:${{ env.IMAGE_TAG }}
- name: Tag image as latest
id: tag-image-as-latest
run: docker tag <<region>>.ocir.io/<<namespace>>/ciapp/nginx_helloworld:${{ env.IMAGE_TAG }} <<region>>.ocir.io/<<namespace>>/ciapp/nginx_helloworld:latest
- name: Log into OCIR
uses: oracle-actions/login-ocir@v1.2.1
id: login-into-ocir
with:
auth_token: ${{ secrets.OCI_AUTH_TOKEN }}
- name: Push a container image
id: push-container-image
run: docker push <<region>>.ocir.io/<<namespace>>/ciapp/nginx_helloworld:${{ env.IMAGE_TAG }}
- name: Push a container image as tag latest
id: push-container-image-as-tag-latest
run: docker push <<region>>.ocir.io/<<namespace>>/ciapp/nginx_helloworld:latest
作成が完了したらcommitとpushを行います
git add .
git commit -m "ver0.0.1"
git push -u origin main
OCI Container Registry repository反映確認
OCIコンソールやCLI等作成方法は複数ありますが今回はCLIを使用しています
以下のように0.0.1とlatestが作成されています
## Replace << >> with the appropriate value
$ oci artifacts container image list --compartment-id <<ocid1.compartment.oc1....>> --repository-name ciapp/nginx_helloworld | jq -r '.data.items[]."display-name"'
ciapp/nginx_helloworld:0.0.1
ciapp/nginx_helloworld:latest
##Container Instance作成
OCIコンソールやCLI等作成方法は複数ありますが今回はCLIを使用しています
必要なパラメータjsonを作成して実行します
## Replace << >> with the appropriate value
{
"availabilityDomain": "<<AD (Example:TGjA:AP-TOKYO-1-AD-1)>>",
"compartmentId": "<<ocid1.compartment.oc1....>>",
"containerRestartPolicy": "ALWAYS",
"display-name": "ci_nginx_helloworld",
"containers": [
{
"imageUrl": "<<region>>.ocir.io/<<namespace>>/ciapp/nginx_helloworld:latest",
"display-name": "nginx_helloworld",
"volumeMounts": [
{
"mountPath": "/volume01",
"volumeName": "volume01"
}
]
}
],
"shape": "CI.Standard.E4.Flex",
"shapeConfig": {
"memoryInGBs": 1.0,
"ocpus": 1.0
},
"vnics": [
{
"privateIp": "<<private IP>>",
"subnetId": "<<ocid1.subnet.oc1....>>"
}
],
"volumes": [
{
"name": "volume01",
"volumeType": "EMPTYDIR"
}
]
}
oci container-instances container-instance create --from-json file://ci_nginx_helloworld.json
作成が成功したら以下のように動作確認します
$ curl http://<<private IP>>:8080
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Hello Docker</title>
</head>
<body>
<h1>Hello World ver 0.0.1</h1>
</body>
</html>
Container Instance restart追加
コンテンツが更新されたらContainer Instanceに反映されるようrestartの仕組みを追加します
~/work/github/cicd-ci
|--.git
+--.github
+--workflows
|--Build_Push.yml <--変更
|--README.md
|--Dockerfile
|--restart_ci.py <--追加
|--version.txt <--変更
+--conf
| +--NGINX構成ファイル
| default.conf
+--src
+--コンテンツ
index.html <--変更
Giuhub actionsでContainer Instanceを再起動するためのコードです
container_instance_idはcontainer instance作成時の出力jsonに含まれるidの情報です。コンソールからも確認できます。
## Replace << >> with the appropriate value
import oci
container_instance_id = "<<ocid1.computecontainerinstance.oc1...>>"
try:
config = oci.config.from_file()
container_instances_client = oci.container_instances.ContainerInstanceClient(config)
restart_container_instance_response = container_instances_client.restart_container_instance(
container_instance_id = container_instance_id
)
print(restart_container_instance_response.headers)
except Exception as e:
print('ERROR: bad Event!')
コンテンツに更新を行ったことがわかるよう ver 0.0.2に更新しています
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Hello Docker</title>
</head>
<body>
<h1>Hello World ver 0.0.2</h1>
</body>
</html>
Container imageのタグ
0.0.2
Github actionsのstepに以下を追加します
## 既存ファイルに以下を追加
- name: Set up Python
id: set-up-python
uses: actions/setup-python@v4
with:
python-version: '3.12'
- name: Install OCI SDK
id: install-oci-sdk
run: pip install oci
- name: Configure OCI credentials
id: configure-oci-credentials
run: |
mkdir -p ~/.oci
echo "[DEFAULT]" > ~/.oci/config
echo "user=${{ secrets.OCI_CLI_USER }}" >> ~/.oci/config
echo "fingerprint=${{ secrets.OCI_CLI_FINGERPRINT }}" >> ~/.oci/config
echo "tenancy=${{ secrets.OCI_CLI_TENANCY }}" >> ~/.oci/config
echo "region=${{ secrets.OCI_CLI_REGION }}" >> ~/.oci/config
echo "key_file=~/.oci/oci_api_key.pem" >> ~/.oci/config
echo "${{ secrets.OCI_CLI_KEY_CONTENT }}" > ~/.oci/oci_api_key.pem
chmod 600 ~/.oci/oci_api_key.pem
- name: Run Python script
id: run-rython-script
run: python restart_ci.py
作成が完了したらcommitとpushを行います
git add .
git commit -m "ver0.0.2"
git push -u origin main
処理が正常に完了するとOCI Container Registryに0.0.2が追加され、latestが置き換えられました
## Replace << >> with the appropriate value
$ oci artifacts container image list --compartment-id <<ocid1.compartment.oc1....>> --repository-name ciapp/nginx_helloworld | jq -r '.data.items[] | [.["display-name"], .digest] | @csv'
"ciapp/nginx_helloworld:0.0.1","sha256:6383a3469455cd6f10fb39b4be0082f20e923bc56bac14fc4e391f817dc*****"
"ciapp/nginx_helloworld:0.0.2","sha256:33a8775b2c6494ce5a4dc3db0362c826407a214220973a2c5f0bcae0c41*****"
"ciapp/nginx_helloworld:latest","sha256:33a8775b2c6494ce5a4dc3db0362c826407a214220973a2c5f0bcae0c41*****"
ver 0.0.1からver 0.0.2に更新されています
$ curl http://<<private IP>>:8080
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Hello Docker</title>
</head>
<body>
<h1>Hello World ver 0.0.2</h1>
</body>
</html>