10分で.NETプログラムをLinuxに自動デプロイする

10分で.NETプログラムをLinuxに自動デプロイする

これまで、プログラムのデプロイは非常に面倒で退屈な作業でした。会社では通常、devopsソリューションがあり、CICDプロセス全体に関わるツールはかなり多く、セットアップが面倒です。

最終更新 2022/07/02 21:57
xhznl
読了目安 4 分
カテゴリ
.NET
タグ
.NET C#

背景

これまで、プログラムのデプロイは非常に面倒で退屈な作業でした。企業では通常、devops のソリューションが用意されており、CI/CD プロセス全体で使用するツールは多く、構築が面倒です。では、個人の小規模なプロジェクトでこのような環境を構築したくない場合はどうすればよいでしょうか… 最近、阿里云效 pipeline + Gitee + ECS を試してみたところ、非常に便利でした。主に無料であること、サーバーも自前や他のものを使用できる点が魅力です。以下で使用方法を共有します。

コードの準備

適当なデモプロジェクトを用意し、Gitee にプッシュします。

## aspnetcore web プロジェクトを作成
dotnet new web -o aspnetcoredemo

サーバー環境

まずサーバーに dotnet ランタイムをインストールします。ここでは CentOS を使用します。

公式ドキュメントを参照: CentOS に .NET をインストールする - .NET | Microsoft Docs

## .NET をインストールする前に、以下のコマンドを実行して Microsoft パッケージ署名キーを信頼済みキーリストに追加し、Microsoft パッケージリポジトリを追加します。ターミナルを開き、次のコマンドを実行します:
sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm

## ASP.NET Core ランタイムを使用すると、.NET で開発されランタイムが提供されていないアプリケーションを実行できます。以下のコマンドは、.NET と最も互換性のある ASP.NET Core ランタイムをインストールします。ターミナルで次のコマンドを実行します:
sudo yum install aspnetcore-runtime-6.0

インストール完了:

自動デプロイ

雲效プラットフォームのパイプラインにアクセスします。

.NET Core パイプラインテンプレートを選択し、作成します。

パイプラインの設定

  • 最初のステップはパイプラインソースの設定です。

コードソースを選択: 码云(Gitee)(もちろん GitHub、自前の Git など他のものを選択することもできます)

認証を行い、コードリポジトリとデフォルトブランチ名を選択します。作業ディレクトリは適当に、例えば demo と入力します。

  • 2番目のステップはビルドの設定です。

主に実行コマンドとパッケージパスに注意します。他のオプションはデフォルトで構いません。

## プロジェクトディレクトリに移動
cd aspnetcoredemo

## プロジェクトを復元
dotnet restore
## プロジェクトを公開
dotnet publish -c Release -o out
  • 3番目のステップはデプロイの設定です。

ホストグループはここでは阿里云 ECS を選択します(他の非阿里云ホストを選択することも可能で、その場合はプラグインのインストールが必要です)。

サーバー接続を追加し、認証して作成します。

ホストを選択し、次へ進み、保存します(ここでは1台のマシンのみですが、複数台のマシンにデプロイすることも可能です)。

デプロイスクリプト:

## ディレクトリを作成

mkdir -p /home/admin/aspnetcoredemo/

## ファイルを /home/admin/aspnetcoredemo/ ディレクトリに解凍
tar zxvf /home/admin/aspnetcoredemo/package.tgz -C /home/admin/aspnetcoredemo/

## デプロイスクリプトを実行
sh /home/admin/aspnetcoredemo/deploy.sh restart

デプロイスクリプト

この deploy.sh をプロジェクトコードに追加します。このスクリプトの大まかな内容は、プロセスを強制終了 → アプリケーションを再起動 → ヘルスチェック → デプロイ完了、です。

内容は以下の通りです:

#!/bin/bash

# APP_NAME を雲效上のアプリケーション名に変更
APP_NAME=aspnetcoredemo


PROG_NAME=$0
ACTION=$1
APP_START_TIMEOUT=20    # アプリケーション起動を待つ時間
APP_PORT=5000          # アプリケーションのポート
HEALTH_CHECK_URL=http://127.0.0.1:${APP_PORT}/HealthChecks  # アプリケーションのヘルスチェックURL
HEALTH_CHECK_FILE_DIR=/home/admin/status   # スクリプトはこのディレクトリに nginx-status ファイルを生成します
APP_HOME=/home/admin/${APP_NAME}           # package.tgz から解凍された dll はこのディレクトリに配置されます
DLL_NAME=${APP_HOME}/${APP_NAME}.dll        # dll の名前
DLL_OUT=${APP_HOME}/logs/start.log         # アプリケーションの起動ログ

# 関連ディレクトリを作成
mkdir -p ${HEALTH_CHECK_FILE_DIR}
mkdir -p ${APP_HOME}
mkdir -p ${APP_HOME}/logs
usage() {
    echo "使用方法: $PROG_NAME {start|stop|restart}"
    exit 2
}

health_check() {
    exptime=0
    echo "${HEALTH_CHECK_URL} をチェック中"
    while true
        do
            status_code=`/usr/bin/curl -L -o /dev/null --connect-timeout 5 -s -w %{http_code}  ${HEALTH_CHECK_URL}`
            if [ "$?" != "0" ]; then
               echo -n -e "\rapplication not started"
            else
                echo "code is $status_code"
                if [ "$status_code" == "200" ];then
                    break
                fi
            fi
            sleep 1
            ((exptime++))

            echo -e "\rアプリケーションがヘルスチェックを通過するのを待機中: $exptime..."

            if [ $exptime -gt ${APP_START_TIMEOUT} ]; then
                echo 'アプリケーションの起動に失敗しました'
               exit 1
            fi
        done
    echo "${HEALTH_CHECK_URL} のチェックに成功しました"
}
start_application() {
    echo "dotnet プロセスを起動中"
    # chmod +x ${DLL_NAME}
    # chmod +x ${APP_HOME}/appsettings.json
    # nohup dotnet ${DLL_NAME} Urls=http://*:${APP_PORT} > ${DLL_OUT} 2>&1 &
    cd ${APP_HOME}
    nohup dotnet ${APP_NAME}.dll Urls=http://*:${APP_PORT} > ${DLL_OUT} 2>&1 &
    echo "dotnet プロセスを起動しました"
}

stop_application() {
   checkdotnetpid=`ps -ef | grep dotnet | grep ${APP_NAME} | grep -v grep |grep -v 'deploy.sh'| awk '{print$2}'`

   if [[ ! $checkdotnetpid ]];then
      echo -e "\rdotnet プロセスがありません"
      return
   fi

   echo "dotnet プロセスを停止中"
   times=60
   for e in $(seq 60)
   do
        sleep 1
        COSTTIME=$(($times - $e ))
        checkdotnetpid=`ps -ef | grep dotnet | grep ${APP_NAME} | grep -v grep |grep -v 'deploy.sh'| awk '{print$2}'`
        if [[ $checkdotnetpid ]];then
            kill -9 $checkdotnetpid
            echo -e  "\r        -- dotnet プロセスを停止中、経過時間 `expr $COSTTIME` 秒。"
        else
            echo -e "\rdotnet プロセスは終了しました"
            break;
        fi
   done
   echo ""
}
start() {
    start_application
    health_check
}
stop() {
    stop_application
}
case "$ACTION" in
    start)
        start
    ;;
    stop)
        stop
    ;;
    restart)
        stop
        start
    ;;
    *)
        usage
    ;;
esac

出力ディレクトリにコピーすることを忘れないでください:

デプロイスクリプトのヘルスチェック用に HealthChecks エンドポイントを追加します:

手動ビルド

パイプラインで「実行」をクリックします。これまでの設定が正しければ、ビルドとデプロイが成功するはずです。

アクセスしてみます。OK です:

自動ビルド

次に、webhook を設定して、コードがプッシュされたら自動的にビルド&デプロイが実行されるようにします。

パイプラインの「トリガー設定」を選択し、webhook トリガーを有効にします:

この webhook URL をコピーし、Gitee リポジトリの設定に追加して保存します:

次に、コードを少し変更してテストします:

コードをプッシュすると、自動的にパイプラインのビルドとデプロイがトリガーされました:

OK です:

終わりに

Happy coding ...

—— 本記事は【Typora】+【EasyBlogImageForTypora】を使用して編集されました。

私の公式アカウントをフォローして、一緒に学びましょう。

この記事がお役に立ちましたら、右下の【おすすめ】ボタンをクリックして応援してください。記事に不適切な点があれば、ご指摘いただけますと幸いです。ありがとうございます!

さらに探索

関連読書

その他の記事
同じカテゴリ / 同じタグ 2026/04/22

各OSバージョンの.NETサポート状況(250707更新)

仮想マシンとテストマシンを使用して、各OSバージョンの.NETサポート状況を確認します。OSインストール後、対応するランタイムをインストールし、Stardustエージェントを実行できることを確認します(合格条件)。

続きを読む
同じカテゴリ / 同じタグ 2026/02/07

AOTの使用経験のまとめ

プロジェクト作成当初から、新機能を追加したり新しい構文を使用したりした場合には、すぐにAOT公開テストを実施するという良い習慣を身につけるべきです。

続きを読む