
【初心者向け】Git + GitHub Actions + Docker Hub + Helm で作るオンプレ Kubernetes へのCI/CDパイプライン構築完全ガイド
はじめに
このブログ記事では、初心者の方でも理解しやすいように、以下の順番で手順と考え方を説明します。
- GitとGitHubの基本操作
- Dockerfile作成とローカル確認
- GitHub Actionsの設定方法(自動Dockerイメージビルド・Docker Hubプッシュ)
- Helmチャートを作成し、Docker Hubのイメージを使ってKubernetesにデプロイ
1. GitとGitHubの基本操作
1-1. Gitとは?
Gitは「ソースコードの変更履歴を管理するツール」です。
これにより、プログラムの変更を追跡したり、複数人での共同作業が可能になります。
1-2. GitHubとは?
GitHubはGitリポジトリをインターネット上でホスティングし、複数人が協力してコード管理できるサービスです。
1-3. GitHubリポジトリの作成
- GitHubにログインし、画面右上の「New 」をクリック

リポジトリ名を入力(例:my-sample-app
)

「Public」か「Private」を選択(今回はPublicでOK)

「Create repository」をクリック

1-4. ローカルPCのソースをGitHubにアップロード(push)する基本操作
今回はgit のコマンドはローカルPCに導入済みである程度git コマンドには慣れ親しんでいるという前提でご説明します。今回はrepoだけではなくworkflow も使うのでsecurity token には下記のworkflow も許可しておいてください

1. 初期化(初回のみ)
cd my-sample-app # プロジェクトフォルダに移動
git init # Gitリポジトリを初期化
2. 変更をステージングエリアに追加
git add . # 変更をすべて追加(ファイルをGitに登録)
3. コミット(変更履歴として保存)
git commit -m "初回コミット"
4. リモートリポジトリを登録(GitHubと連携)
git remote add origin https://github.com/ユーザー名/my-sample-app.git
5. GitHubへプッシュ(アップロード)
git push -u origin master
補足: GitHubのリポジトリ作成時にデフォルトブランチ名が
main
かmaster
かを確認してください。
ここでは masterを使う例で進めています。
2. Dockerfileの作成とローカルでの確認
2-1. Dockerfileの作成
my-sample-app
フォルダの中に Dockerfile
を作成し、以下の内容を書きます。
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
CMD ["nginx", "-g", "daemon off;"]
2-2. index.htmlの作成
同じフォルダに index.html
を作成し、簡単なHTMLを書きます。
<!DOCTYPE html>
<html>
<head><title>My Sample App</title></head>
<body>
<h1>Hello from Docker + Kubernetes!</h1>
</body>
</html>
2-3. Dockerイメージのビルドと動作確認(ローカル)
docker build -t my-sample-app:latest .
docker run -p 8080:80 my-sample-app:latest
ブラウザで http://localhost:8080
にアクセスして、ページが表示されれば成功です。
3. GitHub Actions で Dockerイメージを自動ビルドし Docker Hubにプッシュする
3-1. Docker Hub アカウントを作成
- https://hub.docker.com にアクセスし無料登録

- 「Account Settings」から「Security」→「New Access Token」を作成し、アクセストークンを控える(これをパスワード代わりに使います) dockerイメージをpushするのでscope はRead&Write です

アクセストークンが生成されるので、控えておきましょう

3-2. GitHub Secrets に認証情報を登録
GitHubリポジトリの画面で、
「Settings」→「Secrets and variables」→

「Actions」→「New repository secret」から

ここから先ほどのdocker-hubのユーザ名とシークレットを登録します
DOCKERHUB_USERNAME
→ Docker Hub のユーザー名DOCKERHUB_TOKEN
→ 先ほど控えたアクセストークン

シークレットも登録

最終的に下記のように登録できるはずです

3-3. GitHub Actions の設定ファイルを作成
my-sample-app/.github/workflows/docker-publish.yml
を作成します。
name: Build and Push Docker Image
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build Docker image
run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/my-sample-app:latest .
- name: Push Docker image
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/my-sample-app:latest
3-4. Git管理にファイルを追加し、プッシュする
git add Dockerfile index.html
git add .github/workflows/docker-publish.yml
git commit -m "Add Dockerfile and GitHub Actions workflow"
git push origin master
このプッシュにより、GitHub Actions が起動してDocker Hubにイメージをビルド&プッシュします。下記のようにActions のタブから自動的にbuildが始まっているのがわかります

下記のようにビルドが成功したことを確認

Dockerhubにもビルドが追加されているはずなので確認しましょう

4. Helm チャートで Docker Hubのイメージを使い Kubernetes にデプロイ
4-1. Helm とは?
Helm は Kubernetes マニフェストをテンプレート化し、管理しやすくするパッケージマネージャです。
4-2. Helm チャートの作成例
my-sample-app/helm/my-sample-app
フォルダを作り、以下のファイルを作成します。
Chart.yaml
apiVersion: v2
name: my-sample-app
version: 0.1.0
description: Sample app deployed by Helm
values.yaml
image:
repository: your-dockerhub-username/my-sample-app
tag: latest
service:
type: ClusterIP
port: 80
ingress:
enabled: false
※ ここで your-dockerhub-username
は実際のDocker Hubユーザー名に置き換えてください。
templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Chart.Name }}
spec:
replicas: 1
selector:
matchLabels:
app: {{ .Chart.Name }}
template:
metadata:
labels:
app: {{ .Chart.Name }}
spec:
containers:
- name: {{ .Chart.Name }}
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
ports:
- containerPort: 80
templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ .Chart.Name }}
spec:
type: {{ .Values.service.type }}
selector:
app: {{ .Chart.Name }}
ports:
- port: {{ .Values.service.port }}
targetPort: 80
4-3. Helmでデプロイ
helm install my-sample-app ./helm/my-sample-app
NAME: my-sample-app
LAST DEPLOYED: Mon Jun 2 14:17:50 2025
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
Kubernetesクラスタに Docker Hub からイメージがダウンロードされ、PodとServiceが作成されます。
下記のように確認してみるといいでしょう
# kubectl get pods
NAME READY STATUS RESTARTS AGE
my-sample-app-6bd68cd9d5-htlh2 1/1 Running 0 82s
openmediavault-544c5b85db-6zb5c 0/1 Pending 0 196d
# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 197d
my-sample-app ClusterIP 10.111.253.16 <none> 80/TCP 2m33s
# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
david-pc Ready control-plane 197d v1.30.6 192.168.2.6 <none> Ubuntu 22.04.5 LTS 6.8.0-60-generic containerd://1.7.27
この手順をマスターすれば、コードの変更 → 自動ビルド → 自動デプロイの流れが理解できます。
Helm で NodePort を使う構成に変更する
、helm
を使ってアプリをデプロイしましたが、Service のタイプが LoadBalancer
または ClusterIP
になっていた場合、オンプレ環境ではアクセスできない可能性があります。。
オンプレ環境で外部からアクセス可能にするには、Service のタイプを NodePort に変更する必要があります。
values.yaml
の編集
以下のように service.type
を NodePort
に変更します。nodePort
は使いたいポート番号(30000~32767)に変更可能です。
service:
type: NodePort
port: 80
nodePort: 30080
この values.yaml
を使って Helm でデプロイし直します:このコマンドは同じディレクトリにChart.yaml とvalues.yaml がある場合のコマンドです
helm upgrade --install my-sample-app ./ -f ./values.yaml
Release "my-sample-app" has been upgraded. Happy Helming!
NAME: my-sample-app
LAST DEPLOYED: Mon Jun 2 21:00:32 2025
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None
デプロイできたら ポートがきちんと30081 で動いていることを確認
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 197d
my-sample-app NodePort 10.111.253.16 <none> 80:30081/TCP 7h1m
オンプレ NGINX のリバースプロキシ設定
オンプレの NGINX を介して外部からアプリにアクセスさせるには、NodePort を経由するようにリバースプロキシ設定を変更します。
例:/etc/nginx/nginx.conf
server {
server_name sample.cosicosilife.com;
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/argo.cosicosilife.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/argo.cosicosilife.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
location / {
proxy_pass http://192.168.2.6:30081;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# ここを http にすることでアプリが「HTTPS じゃない」と判断してリダイレクトを止める
proxy_set_header X-Forwarded-Proto https;
}
}
注意:
192.168.0.100
は Kubernetes ノードの IP に置き換えてください。
設定反映後、NGINX を再起動します。
sudo systemctl restart nginx
最後にsample.cosicosilife.com を入力すれば下記のような画面になります
