【OCI】Dockerで作成したイメージをOCIコンテナインスタンスで動かしてみる

# はじめに

今回はOracle Cloud Infrastructure（OCI）が提供している
コンテナインスタンスにNginx + PHPが動作するDockerコンテナを
立てて動かしてみたいと思います。

コンテナであれば、VM(Compute)にDocker環境を作って動かせますが、
わざわざそのためにVMを立てて管理するのもスマートではなく
コンテナインスタンスを使ったら手間もかからず利用できるので
そのあたりの簡単な手順を紹介したいと思います。

■参考
コンテナ・インスタンスの概要
https://docs.oracle.com/ja-jp/iaas/Content/container-instances/overview-of-container-instances.htm

OCI Container Instances概要 / OCI Container Instances
https://speakerdeck.com/oracle4engineer/oci-container-instances

ローカル環境に設定したDockerコンテナでNginx + PHPが動くようにし、
イメージをOCIR（Oracle Cloud Infrastructure Registry）にプッシュします。
そのイメージからコンテナインスタンスを作成して外部URLから
アクセスしてページが表示されるか確認してみます。

■構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/9d6b0f22-ee41-d70a-0063-711c3f140fea.png)

■事前準備
・アカウント
コンテナインスタンス, OCIRが使用できるOCIアカウントを準備

・認証トークン
OCIRにアクセスするための認証トークンを準備

認証トークンの作成方法はこちらを参考にします。
https://oracle-japan.github.io/ocitutorials/cloud-native/functions-for-beginners/
→ 2-1-1. 認証tokenの作成

・ネットワークの設定
VCN、パブリックサブネット、インターネットゲートウェイ、
セキュリティリスト等を作成しておき、インターネットからHTTP(Port 80)で
アクセスできるように準備しておきます。

ネットワークの作成方法についてはこちらを参考にします。
https://oracle-japan.github.io/ocitutorials/beginners/creating-vcn/

・Dockerのセットアップ
予めローカルPC環境にDockerをセットアップしておきます。

Dockerに関する情報はこちらを参考にします。
https://docs.docker.jp/v1.9/docker-hub/index.html

◆目次
1.OCIR（Oracle Cloud Infrastructure Registry）でリポジトリを作成
2.ローカルPC環境でDockerイメージを作成してOCIRにプッシュ
3.コンテナインスタンスの作成
4.PHPサイトへのアクセステスト

## 1.OCIR（Oracle Cloud Infrastructure Registry）でリポジトリを作成
それでは早速、OCIRリポジトリの作成をしていきます。

左上メニュー[Ξ]から開発者サービス → コンテナ・レジストリを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/14f88ce8-0066-74a3-7196-a25f8bb3d4a1.png)

続いてリポジトリの作成を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/c91c1bdd-7abd-9197-5b1c-e8453aa78540.png)

入力欄が表示されるのでアクセスをプライベートに選択し、
任意のリポジトリ名を入力して作成します。
ここでは「oci-my-php-app」とします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/73d593bb-6597-5c85-bc3c-d934f932e7e1.png)

リポジトリが作成されると以下のような画面となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/dec76bef-4e3d-8e6a-593c-2b82b57fbcf2.png)

以上でOCIRリポジトリの作成は終了です。

## 2.ローカルPC環境でDockerイメージを作成してOCIRにプッシュ
ここではローカルPC環境でNginx + PHPが動作するDockerイメージを作成します。
作業用PCはWindows, Linux, Mac、なんでも構いません。
特に構成は問わないのでDockerが動く環境を準備するようにしてください。
※自分はOCI上のOracle Linuxにsshでリモート接続して作業しています。
（コマンド等、細かい設定はご自身の環境に合わせてください）

作業環境にログインしたらディレクトリ、ファイルを作成します。

■ファイル構成／ディレクトリ構造
```
my-php-app/
 |- Dockerfile
 |- custom-nginx.conf
 |- src/
     |- index.php
 |- start.sh
```

■作業の流れ

①ディレクトリの作成
作業用環境にログインしたら任意の場所でディレクトリを２つ作成し、
my-php-appに移動します。
```
mkdir my-php-app
mkdir my-php-app/src
cd my-nginx-app
```
※以降はmy-php-app内で作業を実施

②Dockerfileの作成
Nginx上でPHPが動くようにイメージを落としてきて
起動できるようにDockerfileの内容作成します。
```
vi Dockerfile
```

```
# PHPとNginxを含むベースイメージを使用
FROM php:7.4-fpm

# Nginxをインストール
RUN apt-get update && apt-get install -y nginx

# Nginxの設定ファイルをコンテナにコピー
COPY custom-nginx.conf /etc/nginx/sites-available/default

# PHPファイルをコンテナにコピー
COPY src/ /var/www/html/

# スタートアップスクリプトをコンテナにコピー
COPY start.sh /start.sh

# スタートアップスクリプトに実行権限を与える
RUN chmod +x /start.sh

# コンテナ起動時にスタートアップスクリプトを実行
CMD ["/start.sh"]
```

③custom-nginx.confの作成
PHPが動作するようconfファイルを作成します。
```
vi custom-nginx.conf
```

```
server {
    listen 80;

    root /var/www/html;
    index index.php index.html index.htm;

    server_name localhost;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass 127.0.0.1:9000;
    }
}
```
④start.shの作成
PHPが起動するようにシェルスクリプトを作成します。
```
vi start.sh
```
```
#!/bin/bash

# PHP-FPMをデーモンとして起動
php-fpm -D

# Nginxを起動
nginx -g 'daemon off;'
```

⑤index.phpの作成
PHPが動作しているか確認するためにシンプルにphpinfo()を作成します。
```
vi src/index.php
```

```
<?php
phpinfo();
```

ここまでで必要なファイルの作成は完了となります。

⑥ビルドの実行
必要なファイルが作成できたので、そのままビルドを実行すると
イメージが作成されます。
```
docker build --no-cache -t my-php-app .
```

イメージが作成されているか確認してみます。
確認はdocker imagesでできます。
```
docker images
```
実行するとこんな感じで表示されます。
これで正常にイメージが作成されていることが確認できます。
```
REPOSITORY                              TAG       IMAGE ID       CREATED          SIZE
my-php-app                              latest    70e29d706da8   24 minutes ago   490MB
```

⑦コンテナの作成
80ポートでアクセスできるように次の
コマンドでコンテナを作成します。
```
docker run -d -p 80:80 my-nginx-php-app
```

コンテナが作成されているかの確認もしてみます。
確認はdocker psでできます。
```
docker ps
```

実行するとこんな感じで表示されます。
これで正常にコンテナが作成されていることが確認できます。
```
CONTAINER ID   IMAGE        COMMAND                  CREATED       STATUS       PORTS                                         NAMES
2299cf21c484   my-php-app   "docker-php-entrypoi…"   2 hours ago   Up 2 hours   0.0.0.0:80->80/tcp, :::80->80/tcp, 9000/tcp   sharp_lewin
```

前述のコマンドでイメージとコンテナが正常に作成できましたが、
念のためcurlでPHPが応答する確かめます。

```
curl localhost/index.php
```
※エラーがなくHTMLタグが表示されたらコンテナが正常に作成されています。

⑧OICRにログイン
コマンドで以下を実行することでOCIRにログインできます。
docker login [リージョンキー].ocir.io
※東京リージョンの場合、nrt.ocir.ioとなります。
```
docker login nrt.ocir.io
```

上記を実行するとユーザとパスワードを聞かれるので入力します。
ユーザ: [テナンシー名]/oracleidentitycloudservice/[ユーザ名]
パスワード: ※事前準備で用意しておいた認証トークン
※ユーザはIDCSの場合を想定しています。

例. テナンシー名がABC、ユーザ名がXYZだった場合
```
ユーザ: ABC/oracleidentitycloudservice/XYZ
パスワード: [認証トークン]
```

⑨イメージにタグ付け
イメージタグは以下のように付けます。
docker tag [イメージ名]:latest [リージョンキー].ocir.io/[テナンシー名]/[OCIRリポジトリ名]:latest

```
docker tag my-php-app:latest nrt.ocir.io/[テナンシー名]/oci-my-php-app:latest
```

⑩OCIRにイメージをプッシュ
最後にイメージをプッシュして完了です。
```
docker push nrt.ocir.io/[テナンシー名]/oci-my-php-app:latest
```

以上でDockerイメージをOCIRへのプッシュできました。

## 3.コンテナインスタンスの作成

続いてコンテナインスタンスを作成していきます。
左上メニュー[Ξ]から開発者サービス → コンテナ・インスタンスを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/97be4e00-1b4f-f9f6-afd4-a8b1e2bab591.png)

Create container instanceを実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/3424111a-42c4-887a-114f-4766243c66be.png)

任意のName（コンテナインスタンス名:container-php-app）を入力して、
下にスクロールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/bd9e9dd0-096d-e1d6-0e3d-9fa0264b6b06.png)

必要に応じてコンテナインスタンスのシェイプを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/17d837d1-1822-b1f9-145a-e370ab7a4e59.png)

VCNとサブネット（パブリック）を選択し、外部からアクセスできるように
Assign a public IPv4 addressにして、次へボタンを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/488c85c8-8393-940a-d2d5-7753908af3ac.png)

任意のName（コンテナ名:container-php-app01）を入力して、
Select imageボタンを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/1455e877-64f1-5c37-feca-0a8e8b25f2a4.png)

以下の項目を入力してSelect imageボタンを押します。
Repository: リポジトリ名 [oci-my-php-app]
Image in repository: タグ [latest]
（＊Provide credentials manuallyにチェックを入れます）
Registry username: [ユーザ名] (例. [テナンシー名]/oracleidentitycloudservice/[ユーザ名])
Registry password: [認証トークン]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/7e765fd4-72db-8cf3-d51c-c43b73e59b5a.png)

リポジトリ、認証情報の入力が完了したら次へボタンを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/730dae67-7435-5c84-6a94-2760567131c4.png)

最後に登録情報を確認して、Createをボタンを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/711fd1d1-5f76-1576-17e3-785301731988.png)

しばらく待つとコンテナインスタンスが作成されるので
パブリックIPを保存しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/90cefbd6-acf0-6bea-b923-061a2962a57d.png)

以上でコンテナインスタンスの作成は終了です。

## 4.PHPサイトへのアクセステスト
コンテナインスタンスのPHPが外部から正常に表示できるか確認するために
ブラウザから以下の通りアクセスします。
http://[グローバルIP]

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/9b9c7458-5071-810b-ae7b-e4c0b4b25070.png)

表示されればこれで終了です。

## おわり
以上、OCIに立てたコンテナインスタンスを簡単に使うことができました。