VPSにSpringBootのアプリケーションをJenkinsを使用してデプロイする。

# VPS契約ガイド
### 1. スペックの選定
これらを合計すると、全体として最低でも6-8GBのRAMと120GB以上のディスクスペースが必要となると見積もられます。
※これはあくまで概算。
| ソフトウェア | 推奨リソース |
| --- | --- |
| CentOS | 最低でも1GBのRAMが必要ですが、他のアプリケーションを動作させるためには2GB以上のRAMを確保することを推奨します。 |
| Jenkins | Jenkinsの動作には最低でも256MBのRAMと1GBのディスクスペースが必要ですが、大規模なビルドや多数のジョブを実行する場合にはさらに多くのリソースが必要となります。一般的には、2GB以上のRAMと50GB以上のディスクスペースを確保することが推奨されます。 |
| Docker Compose | Docker自体の動作には最低でも512MBのRAMと20GBのディスクスペースが必要ですが、動作させるコンテナによってはさらに多くのリソースが必要となります。 |
| Spring Boot Webアプリケーション | 必要とするリソースはアプリケーションの規模や負荷によりますが、最低でも512MB～1GBのRAMを確保することが推奨されます。 |
| Redis | 必要なリソースは使用するデータの量によりますが、最低でも512MBのRAMを確保することが推奨されます。 |
| PostgreSQL | 小規模なデータベースの場合、最低でも512MBのRAMと50GBのディスクスペースを確保することが推奨されます。 |

### 2. VPSの契約
今回契約をしたVPSはコスパ重視でCONTABOのVPSサーバー
https://contabo.com/en

| 項目     | 内容             |
| -------- | ---------------- |
| プラン      | Cloud VPS Sプラン     |
| CPU      | 4 vCPU Cores     |
| RAM      | 8 GB RAM         |
| STORAGE  | 200 GB SSD       |
| Region   | Asia (Japan)     |
| OS       | Cent OS 7        |


# CentOS 7 設定ガイド
### 1.作業用のユーザーアカウントを作成する

1. 新しいユーザーアカウントを作成します。ここではユーザー名を`username`とします。適切なユーザー名に置き換えてください。

    ```bash
    adduser username
    ```

2. 作成したユーザーにパスワードを設定します。

    ```bash
    passwd username
    ```

3. このユーザーにsudo権限を付与します。

    ```bash
    usermod -aG wheel username
    ```

### 2. 公開鍵認証の設定

1. ユーザーを切り替えます。

    ```bash
    su - username
    ```

2. ユーザーのホームディレクトリで.sshディレクトリを作成します。

    ```bash
    mkdir ~/.ssh
    ```

3. 公開鍵を`~/.ssh/authorized_keys`ファイルに追加します。公開鍵はあらかじめローカルマシンで生成しておく必要があります。
リンク参照：[SSH公開鍵と秘密鍵の作成方法](https://qiita.com/msugou/items/c9208be74a8bc65f648c)
    ```bash
    echo 'your_public_key' >> ~/.ssh/authorized_keys
    ```

4. 必要なパーミッションを設定します。

    ```bash
    chmod 700 ~/.ssh
    chmod 600 ~/.ssh/authorized_keys
    ```

5. rootユーザーに戻ります。

    ```bash
    exit
    ```

### 3. パスワード認証を無効化

1. SSHの設定ファイル`/etc/ssh/sshd_config`を開きます。

    ```bash
    vi /etc/ssh/sshd_config
    ```

2. 以下の行を見つけて変更または追加します。
    ```bash
    PubkeyAuthentication  yes
    ```
    ```bash
    PasswordAuthentication no
    ```
    ```bash
    PermitRootLogin no
    ```
    ```bash
    ChallengeResponseAuthentication no
    ```
3. SSHサーバーを再起動します。

    ```bash
    systemctl restart sshd
    ```

### 4. ファイアウォールの設定

1. firewalldサービスの開始

    ```bash
    systemctl start firewalld
    ```
2. firewalldが正常に起動したことを確認
    ```bash
    systemctl status firewalld
    ```
    active (running)という結果を返すならば、firewalldは正常に起動しています。
3. firewall-cmdコマンドを実行してHTTP、HTTPS、SSHをファイアウォールに追加   
     ```bash
    firewall-cmd --permanent --add-service=ssh
    firewall-cmd --permanent --add-service=http
    firewall-cmd --permanent --add-service=https
    firewall-cmd --reload
    ```
4. firewalldがシステム起動時に自動的に起動するように設定
    ```bash
    systemctl enable firewalld
    ```
この設定は基本的なものですが、セキュリティをさらに強化するためには、SELinuxの設定、不要なサービスの停止、定期的なパッチ適用などを行うことが重要です。また、システムの監視やロギングも重要なセキュリティ対策の一部となります。

# ソフトウェアインストール

### 1. JenkinsやDocekr設定用の、shスクリプトを実行する。
※jenkins.io-2023.keyは頻繁に更新される為、最新versionをインストールする必要がある
```sh:jenkins.sh
#!/bin/bash
    
# Javaのインストール
sudo yum install -y java-11-openjdk-devel
    
# Gitのインストール
sudo yum install git

# yum-utils のインストール
sudo yum install -y yum-utils

# Dockerのインストール
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
sudo systemctl enable docker
 
# DockerComposeのインストール
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo usermod -aG docker jenkins
    
# Jenkinsリポジトリの追加
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat/jenkins.io-2023.key
    
# Jenkinsのインストール
sudo yum install -y jenkins
    
# Jenkinsの起動と自動起動の設定
sudo systemctl start jenkins
sudo systemctl enable jenkins
    
# ファイアウォールの設定
sudo firewall-cmd --permanent --zone=public --add-port=8000/tcp
sudo firewall-cmd --permanent --zone=public --add-port=8080/tcp
sudo firewall-cmd --reload
```

### 2. Jenkinsのport番号の変更
   1. Jenkinsの設定ファイル`/usr/lib/systemd/system/jenkins.service`を開きポートを`8000`に変更。
    
       ```sh:jenkins.service
       Environment="JENKINS_PORT=8000" 
       ```
   2. Jenkinsの設定ファイル`/etc/sysconfig/jenkins`を開きポートを`8000`に変更。
       ```sh:jenkins
       JENKINS_PORT="8000"
       ```
       ```sh:jenkins
       JENKINS_HTTPS_PORT="8000"
       ```    
   4. 再起動して設定を反映
        ```sh:bash
       sudo systemctl daemon-reload
       sudo systemctl restart jenkins
        ```
   5. 初期パスワードの表示
        ```sh:bash
        echo "Initial Admin Password:"
        sudo cat /var/lib/jenkins/secrets/initialAdminPassword
        ```
   6. 初回ログイン
       `<VPSのホスト名>:8000`でJenkinsにアクセスして、取得したPWを入力して初回ログインを行う。

# CICDの構築
### 1. Jenkinsのセットアップ：
以下の手順でJenkinsと必要なプラグインをセットアップします。

1. Jenkinsのダッシュボードにログインします。
2. 「Jenkinsの管理」をクリックします。
3. 次に「プラグインの管理」をクリックします。
4. 「利用可能なプラグイン」タブを開き、「GitHub plugin」と「Docker plugin」を検索します。
5. プラグインの横にあるチェックボックスをオンにし、「再起動せずにインストール」をクリックします。

### 2. ソースコード管理（GitHub）：
Jenkinsジョブを設定し、ソースコードのリポジトリとしてGitHubを指定します。

1. Jenkinsのダッシュボードで、「新規ジョブ作成」をクリックします。
2. 任意のジョブ名を入力し、「フリースタイル・プロジェクトのビルド」を選択して、「OK」をクリックします。
3. 「ソースコード管理」セクションで、「Git」を選択します。
4. 「リポジトリURL」にGitHubリポジトリのURLを入力します。
5. 「認証情報」にGitHubの認証情報を追加します。
6. 「ビルドするブランチ」でビルドするブランチを指定します。

### 3. Dockerビルド：
Dockerfileを使ってアプリケーションのDockerイメージをビルドします。

1. 「ビルド」セクションで、「ビルド手順の追加」をクリックし、「シェルの実行」を選択します。
2. シェルスクリプトでDockerビルドコマンドを実行します。
例：`docker-compose build app`

### 4. DockerHubへのプッシュ：
ビルドしたDockerイメージをDockerHubにプッシュします。

1. 「ビルド」セクションで、「ビルド手順の追加」をクリックし、「シェルの実行」を選択します。
2. シェルスクリプトでDocker pushコマンドを実行します。
例：`docker login -u $DOCKERHUB_USER -p $DOCKERHUB_PASS
docker push lunch-app`

### 5. デプロイ（Docker Compose）：
新しいイメージを使用してアプリケーションをデプロイします。

1. 「ビルド後の処理」で、「ビルド後の処理の追加」をクリックし、「シェルの実行」を選択します。
2. シェルスクリプトでDocker Composeを使用してアプリケーションをデプロイします。
例：`docker-compose up -d`

### 6. Jenkinsジョブのスケジューリング：
すべてのステップをJenkinsジョブとしてスケジュールします。

1. 「ビルド・トリガ」セクションで、「SCMをポーリング」を選択します。
2. スケジュールを設定します。例：`H/15 * * * *`（15分ごとにチェック）