Azure Container Apps (ACA) に C 言語の CGI プログラム カスタムコンテナイメージをデプロイする
こんにちは、@studio_meowtoon です。今回は、Azure Container Apps 環境で、C 言語の CGI プログラムをコンテナとして起動する方法を紹介します。
目的
Windows 11 の Linux でクラウド開発します。
こちらから記事の一覧がご覧いただけます。
実現すること
Microsoft Azure Container Apps (ACA) に C 言語の CGI プログラム カスタムコンテナイメージをデプロイします。
この記事は学習目的であり、実際にはセキュリティリスクを伴う可能性があるため、実際のプロダクション環境では使用しないことを強くお勧めいたします。
CGI プログラムをコンテナとして起動
要素 | 概要 |
---|---|
web-browser | Web ブラウザ |
Azure | クラウド環境 |
Azure Container Apps | コンテナ実行環境 |
app-hello-c-cgi | カスタムコンテナ |
app | CGI プログラム |
apache | Web サーバー |
この記事では、Docker Hub に公開するパブリックアクセス可能なカスタムコンテナイメージを使用しています。実際のシステム開発では、どのレジストリからコンテナイメージを取得するかは異なる場合がありますので、適宜ご確認ください。
技術背景
CGI とは?
こちらを展開してご覧いただけます。
CGI (シージーアイ) [Common Gateway Interface] は、ウェブサーバーと外部プログラムとの間でデータの受け渡しと相互作用を可能にする仕組みです。
キーワード | 内容 |
---|---|
動的なウェブページ生成 | CGI を使用することで、動的なウェブページを生成し、ユーザーに対話的なコンテンツを提供できます。 |
プログラム言語の選択肢 | C 言語は CGI プログラムを書くための一般的なプログラミング言語の1つであり、高性能で効率的なプログラムを開発できます。 |
ウェブサーバーとの連携 | CGI プログラムは、ウェブサーバーからの HTTP リクエストを受け取り、クライアントに対するHTTPレスポンスを生成することができます。 |
外部データベースとの統合 | C言語を使用した CGI プログラムは、外部データベースと連携してデータの取得や更新を行うことができます。 |
古典的なウェブ開発 | CGI は古典的なウェブ開発のアプローチであり、現代のウェブアプリケーション開発では他の技術やアーキテクチャが一般的に使用されますが、歴史的な重要性があります。 |
CGI と C 言語の組み合わせは、ウェブサーバーとプログラムとの間でデータをやり取りし、動的なウェブコンテンツを生成するために使用される古典的なテクノロジーです。
Microsoft Azure Container Apps (ACA) とは?
こちらを展開してご覧いただけます。
Microsoft Azure Container Apps (ACA)
Azure 上で実行されるコンテナアプリケーションのプラットフォームです。
ACA は、Docker コンテナと Kubernetes クラスタの環境をサポートしており、開発者はコンテナイメージを作成して、Kubernetes リソースとしてデプロイすることができます。また、カスタムドメイン名をサポートしているため、自社のブランドを維持することができます。
メリット | 説明 |
---|---|
簡単なセットアップとデプロイ | ACA は、簡単なユーザーインターフェイスを備えており、数回のクリックでコンテナアプリケーションをセットアップしてデプロイすることができます。 |
スケーラビリティ | ACA は、自動的にスケーリングを行うことができます。アプリケーションに必要なリソースが増加した場合、ACA は自動的に必要なリソースを追加して処理を分散します。 |
セキュリティ | ACA は、コンテナアプリケーションを実行する際に必要なセキュリティ機能を提供しています。例えば Azure Active Directory との統合や、コンテナレベルでのアクセス制御などがあります。 |
コスト効率 | ACA は、必要なときに必要なリソースを追加するため、無駄なリソースの使用を最小限に抑えることができます。また、必要なリソースに対してのみ支払いを行うため、コスト効率的に利用することができます。 |
開発環境
- Windows 11 Home 22H2 を使用しています。
WSL の Ubuntu を操作していきますので macOS の方も参考にして頂けます。
WSL (Microsoft Store アプリ版) ※ こちらの関連記事からインストール方法をご確認いただけます
> wsl --version
WSL バージョン: 1.0.3.0
カーネル バージョン: 5.15.79.1
WSLg バージョン: 1.0.47
Ubuntu ※ こちらの関連記事からインストール方法をご確認いただけます
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04.1 LTS
Release: 22.04
Docker ※ こちらの関連記事からインストール方法をご確認いただけます
$ docker --version
Docker version 23.0.1, build a5ee5b1
Azure CLI ※ こちらの関連記事からインストール方法をご確認いただけます
$ az --version
azure-cli 2.45.0
core 2.45.0
telemetry 1.0.8
この記事では基本的に Ubuntu のターミナルで操作を行います。Vim を使用してコピペする方法を初めて学ぶ人のために、以下の記事で手順を紹介しています。ぜひ挑戦してみてください。
作成する Web サイトの仕様
Web ブラウザに Hello World! と表示します。
"Hello World" を表示する手順
プロジェクトフォルダを作成
プロジェクトフォルダを作成して移動します。
※ ~/tmp/hello-c-cgi をプロジェクトフォルダとします。
$ mkdir -p ~/tmp/hello-c-cgi
$ cd ~/tmp/hello-c-cgi
C コンパイラのインストール
gcc をインストールします。
$ sudo apt update
$ sudo apt install gcc
確認します。
$ gcc --version
gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
C プログラムの作成
hello_world.c を作成します。
$ vim hello_world.c
ファイルの内容
#include <stdio.h>
int main() {
printf("Content-Type: text/html\n\n");
printf("<html><head><title>Hello CGI</title></head><body>");
printf("<h1>Hello World!</h1>");
printf("</body></html>");
return 0;
}
ビルド(コンパイル)します。
$ gcc -o app hello_world.c -O2
説明を開きます。
要素 | 説明 |
---|---|
gcc | GCC (GNU Compiler Collection) の C コンパイラを呼び出すコマンドです。C 言語のソースコードをコンパイルして実行可能なプログラムに変換します。 |
-o app | -o オプションは、コンパイルされた実行可能ファイルの名前を指定するためのオプションです。ここでは、出力ファイルの名前を "app" に指定しています。 |
hello_world.c | コンパイル対象の C 言語ソースコードファイルの名前です。このコマンドでは、"hello_world.c" というファイルをコンパイルします。 |
-O2 | -O2 オプションは、コンパイラに最適化のレベルを指示します。具体的には、プログラムの実行速度を向上させるための最適化を有効にします。-O2 は、一般的な最適化レベルの一つで、プログラムの実行速度を向上させつつも、コンパイルにはある程度の時間がかかります。コードを最適化することで、プログラムの効率性が向上し、実行速度が向上することがあります。 |
実行します。
$ ./app
出力
Content-Type: text/html
<html><head><title>Hello CGI</title></head><body><h1>Hello World!</h1></body></html>
ここまでの手順で、C 言語による最小限の CGI プログラムの実行ファイルを作成することができました。
コンテナイメージをビルド
Dockerfile を作成します。
$ vim Dockerfile
ファイルの内容
# build the app.
FROM debian:12-slim
# install httpd.
RUN apt update \
&& apt install -y apache2 \
&& rm -rf /var/lib/apt/lists/* \
&& apt clean
# enable the cgi module in httpd.
RUN a2enmod cgi
# creates a directory for the cgi.
RUN mkdir -p /usr/lib/cgi-bin
# copies the local app to the container.
COPY app /usr/lib/cgi-bin/app
# sets permissions for the cgi.
RUN chmod +x /usr/lib/cgi-bin/app
# sets a script alias directive in httpd config file.
RUN sed -i '/ScriptAlias \/cgi-bin\/ \/usr\/lib\/cgi-bin\//d' /etc/apache2/conf-available/serve-cgi-bin.conf && \
echo "ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/" >> /etc/apache2/conf-available/serve-cgi-bin.conf && \
a2enconf serve-cgi-bin
# sets the server name directive in httpd config file.
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
# expose the port.
EXPOSE 80
# command to run httpd.
CMD ["apachectl","-D","FOREGROUND"]
説明を開きます。
要素 | 説明 |
---|---|
FROM debian:12-slim | ベースイメージとして Debian 12 のスリムバージョンを使用します。 |
RUN apt update | パッケージマネージャのパッケージリストを更新します。 |
RUN apt install -y apache2 | Apache HTTP Server (httpd) をインストールします。-y オプションはインストールプロセス中の確認プロンプトを自動的に "Yes" と回答することを示します。 |
RUN rm -rf /var/lib/apt/lists/* | インストール後、不要なパッケージリストキャッシュを削除します。これにより、Docker イメージサイズを最小限に抑えます。 |
RUN apt clean | インストール時に生成された一時ファイルやキャッシュをクリーンアップします。 |
RUN a2enmod cgi | Apache HTTP Server で CGI モジュールを有効化します。これにより、Apache は CGI プログラムを実行できるようになります。 |
RUN mkdir -p /usr/lib/cgi-bin | CGI アプリケーション用のディレクトリ /usr/lib/cgi-bin を作成します。 |
COPY app /usr/lib/cgi-bin/app | ローカルの app ファイル (CGI アプリケーションの実行可能ファイル) をコンテナ内の /usr/lib/cgi-bin/ ディレクトリにコピーします。 |
RUN chmod +x /usr/lib/cgi-bin/app | CGI アプリケーションファイルに実行権限を付与します。これにより、コンテナ内で実行できます。 |
RUN sed -i '/ScriptAlias /cgi-bin/ /usr/lib/cgi-bin//d' /etc/apache2/conf-available/serve-cgi-bin.conf && \ echo "ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/" >> /etc/apache2/conf-available/serve-cgi-bin.conf && \ a2enconf serve-cgi-bin | Apache の設定ファイル serve-cgi-bin.conf を編集して、CGI スクリプトのエイリアスディレクトリを設定します。 |
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf | Apache の設定ファイルに ServerName ディレクティブを追加して、サーバーのホスト名を設定します。 |
EXPOSE 80 | コンテナがポート 80 を外部に公開することを宣言します。これにより、ホストマシンからコンテナの Apache HTTP Server にアクセスできます。 |
CMD ["apachectl","-D","FOREGROUND"] | コンテナが起動された際に実行されるコマンドを指定します。ここでは Apache HTTP Server をバックグラウンドで実行します。 |
Docker デーモンを起動します。
$ sudo service docker start
* Starting Docker: docker [ OK ]
コンテナイメージをビルドします。
$ docker build \
--no-cache \
-t app-hello-c-cgi .
コンテナイメージを確認します。
$ docker images | grep app-hello-c-cgi
app-hello-c-cgi latest 46bed0912d2c 9 seconds ago 187MB
ここまでの手順で、ローカル環境の Docker にアプリのカスタムコンテナイメージをビルドすることができました。
コンテナを起動
ローカルでコンテナを起動します。
$ docker run --rm \
--name app-local \
-p 8080:80 \
app-hello-c-cgi:latest
このコンテナを停止するには、以下のコマンドを実行します。
$ docker stop app-local
ここまでの手順で、ローカル環境の Docker でアプリのカスタムコンテナを起動することができました。
コンテナの動作確認
別ターミナルから curl コマンドで確認します。
$ curl -v http://localhost:8080/cgi-bin/app -w '\n'
出力
* Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /cgi-bin/app HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Fri, 18 Aug 2023 06:22:40 GMT
< Server: Apache/2.4.57 (Debian)
< Vary: Accept-Encoding
< Transfer-Encoding: chunked
< Content-Type: text/html
<
* Connection #0 to host localhost left intact
<html><head><title>Hello CGI</title></head><body><h1>Hello World!</h1></body></html>
Web ブラウザで以下の URL にアクセスして確認します。
http://localhost:8080/cgi-bin/app
ここまでの手順で、ローカル環境の Docker でアプリのカスタムコンテナを起動することができました。
Docker Hub にコンテナイメージを登録
Docker Hub にログインします。
$ docker login
Login Succeeded
コンテナイメージにタグを付けます。
ここで $USER という埋め込み変数は、Ubuntu のシェル変数 USER のことです。つまり、カスタムコンテナイメージを Docker Hub にプッシュする際に指定するアカウント名と、Ubuntu のユーザー名を同じにすると、イメージの取り扱いが簡単になります。ただし、この方法は検証用途に限定されます。
$ docker tag app-hello-c-cgi:latest \
$USER/app-hello-c-cgi:latest
Docker Hub にコンテナイメージをプュシュします。
$ docker push $USER/app-hello-c-cgi:latest
ここまでの手順で、Docker Hub に $USER/app-hello-c-cgi:latest というカスタムコンテナイメージをプッシュすることができました。
シェル変数の作成
シェル変数として、Ubuntu に以下の値を作成します。状況により、コンテナ アプリの名前を変える必要があります。
location_name=japaneast
resource_group_name=rg-hello
containerapp_env_name=cae-hello
containerapp_name=ca-hello-c-cgi
container_image_name=app-hello-c-cgi:latest
Azure 環境にサインイン
こちらの関連記事の続きから手順を説明する記事となります。
Azure CLI でログインします。
$ az login
Azure 環境
リソースグループ
リソースグループを作成します。
$ az group create \
--name $resource_group_name \
--location $location_name
コンテナ アプリ環境
コンテナ アプリ環境を作成します。
※ Kubernetes 基盤の環境がベースとなっているので少し時間がかかります。
$ az containerapp env create \
--resource-group $resource_group_name \
--name $containerapp_env_name \
--location $location_name
コンテナ アプリ
コンテナ アプリの作成とデプロイを行います。
$ az containerapp create \
--resource-group $resource_group_name \
--environment $containerapp_env_name \
--name $containerapp_name \
--image $USER/$container_image_name \
--target-port 80 \
--ingress 'external' \
--min-replicas 0
--min-replicas 0: と設定することにより、アクセスが300秒間ない場合にアプリケーションがスケールゼロ状態に移行します。
コンテナ アプリを削除する場合は以下のコマンドを実行します。
$ az containerapp delete \
--resource-group $resource_group_name \
--name $containerapp_name
コンテナ アプリの FQDN をシェル変数 containerapp_fqdn として取得します。
$ containerapp_fqdn=$(az containerapp show \
--resource-group $resource_group_name \
--name $containerapp_name \
--query 'properties.configuration.ingress.fqdn' \
--output tsv)
コンテナ アプリの FQDN を確認します。
$ set | grep containerapp_fqdn
containerapp_fqdn=ca-hello-c-cgi.whitewave-41bebcec.japaneast.awesomecontainerapps.io
Azure Portal の確認
ここまでの作業で、Azure Container Apps にコンテナ アプリをデプロイすることができました。
コンテナの動作確認
ターミナルから Web ブラウザを開き、確認します。
$ wslview https://$containerapp_fqdn/cgi-bin/app
ここまでの手順で、Azure Container Apps 環境でアプリのカスタムコンテナを起動することができました。
コンテナに接続
コンテナ アプリに接続
$ az containerapp exec \
--resource-group $resource_group_name \
--name $containerapp_name
コンテナに接続後にディレクトリを確認します。
※ コンテナから出るときは ctrl + D を押します。
# pwd
/
# cd /usr/lib/cgi-bin
# ls -lah
total 24K
drwxr-xr-x 1 root root 4.0K Sep 14 06:56 .
drwxr-xr-x 1 root root 4.0K Sep 14 06:56 ..
-rwxr-xr-x 1 root root 16K Sep 14 06:44 app
top コマンドで状況を確認します。
# apt update
# apt install procps
# top
top - 07:38:33 up 1:09, 0 user, load average: 0.21, 0.19, 0.18
Tasks: 7 total, 1 running, 6 sleeping, 0 stopped, 0 zombie
%Cpu(s): 3.8 us, 1.3 sy, 0.0 ni, 94.8 id, 0.0 wa, 0.0 hi, 0.1 si, 0.0 st
MiB Mem : 15990.8 total, 7951.0 free, 2363.9 used, 6029.1 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 13626.9 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 2576 892 800 S 0.0 0.0 0:00.02 apachectl
9 root 20 0 6624 5360 4016 S 0.0 0.0 0:00.01 apache2
10 www-data 20 0 6284 2900 1560 S 0.0 0.0 0:00.00 apache2
11 www-data 20 0 1932356 11472 3412 S 0.0 0.1 0:00.01 apache2
12 www-data 20 0 1932332 13288 3268 S 0.0 0.1 0:00.01 apache2
69 root 20 0 2576 936 844 S 0.0 0.0 0:00.01 sh
176 root 20 0 8596 4668 2796 R 0.0 0.0 0:00.00 top
top コマンドで cpu を表示した状況です。
top - 07:38:55 up 1:09, 0 user, load average: 0.22, 0.19, 0.18
Tasks: 7 total, 1 running, 6 sleeping, 0 stopped, 0 zombie
%Cpu0 : 4.7 us, 2.0 sy, 0.0 ni, 93.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 3.4 us, 1.7 sy, 0.0 ni, 95.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu2 : 2.7 us, 2.0 sy, 0.0 ni, 95.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 : 4.4 us, 1.3 sy, 0.0 ni, 94.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 15990.8 total, 7963.4 free, 2350.1 used, 6030.5 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 13640.7 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 2576 892 800 S 0.0 0.0 0:00.02 apachectl
9 root 20 0 6624 5360 4016 S 0.0 0.0 0:00.01 apache2
10 www-data 20 0 6284 2900 1560 S 0.0 0.0 0:00.00 apache2
11 www-data 20 0 1932356 11472 3412 S 0.0 0.1 0:00.01 apache2
12 www-data 20 0 1932332 13288 3268 S 0.0 0.1 0:00.01 apache2
69 root 20 0 2576 936 844 S 0.0 0.0 0:00.01 sh
176 root 20 0 8596 4668 2796 R 0.0 0.0 0:00.00 top
コンテナの情報を表示してみます。
# cat /etc/*-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
このコンテナは Debian GNU/Linux をベースに作成されています。つまり、Debian GNU/Linux と同じように扱うことができます。
パフォーマンスの計測
コンテナ 環境
項目 | バージョン |
---|---|
Base Image | Debian GNU/Linux 12 |
コンテナ リソースの割り当て
項目 | 設定値 |
---|---|
CPU コアの数 | 0.5 |
メモリ サイズ(Gi) | 1Gi |
メトリック:CPU使用率
状況 | CPU使用率 |
---|---|
集計:平均 | 0.15mコア |
メトリック:メモリ使用量
状況 | メモリ使用量 |
---|---|
集計:平均 | 17.8MB |
まとめ
Azure Container Apps 環境で、Dockerfile からビルドした C 言語の CGI プログラムのカスタムコンテナイメージを起動することができました。
GCC、Docker、Azure CLI を使って、C 言語の CGI プログラムの開発からコンテナイメージの作成、Azure 環境へのデプロイまで、すべてをターミナルから行うことができます。このように、クラウドでのシステム開発に必要なスキルや理解を深めることができます。初めての人でも簡単に手順を追うことができるので、ぜひ挑戦してみてください。
どうでしたか? 検証目的として、Azure Container Apps 環境で、C 言語の CGI プログラムをコンテナとして手軽に起動することができます。ぜひお試しください。今後も Azure の開発環境などを紹介していきますので、ぜひお楽しみにしてください。
推奨コンテンツ