こんにちは、ナナオです。

以前の記事で図書館予約管理システムの構築と自宅k8sサーバーの構築を行いました。

今回は構築したk8s環境に予約システムをデプロイしようと思います。

実装

まずはDockerイメージのプッシュです。

Dockerレジストリを何にしようか…というのが最初のポイントですが、docker.ioはプライベートリポジトリが1リポジトリしか使えないのでナシ。

ghcr.ioは自分がGithubアカウントがプロなのもあって2GBまでストレージ使えるのと月の通信量が10GBまでなら課金なしなので、ghcr.ioにします。

ということでイメージをビルドしていきます。

docker build -f docker/Dockerfile -t library-checker:0.1.0 .

プッシュもやっちゃいましょう。

ここからはこのドキュメントを参照します。

https://docs.github.com/ja/packages/working-with-a-github-packages-registry/working-with-the-container-registry

GitHub Container Registry(ghcr)でコンテナイメージを管理する #Docker - Qiita

PATを発行し、以下のコマンドを実行します。

echo "<発行したPAT>" | docker login ghcr.io -u <username> --password-stdin

ログインに成功したら、以下のコマンドでプッシュします。

docker push ghcr.io/NAMESPACE/IMAGE_NAME:latest

次にイメージのプルに必要な認証情報をクラスタに渡します。

kubectl create secret docker-registry ghcr-secret \
  --docker-server=https://ghcr.io \
  --docker-username=ユーザー名 \
  --docker-password=PAT(ghp_xxxx...) \
  --docker-email=メールアドレス

また、定義していた.envもシークレットとして登録しておきます。

kubectl create secret generic library-checker-env --from-env-file=.env

それでは、システムを動かすためのファイルを実装します。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: library-checker
spec:
  replicas: 1
  selector:
    matchLabels:
      app: library-checker
  template:
    metadata:
      labels:
        app: library-checker
    spec:
      imagePullSecrets:
      - name: ghcr-secret # 先ほどクラスタに設定したイメージのプルに必要な認証情報
      containers:
      # --- 1. アプリ本体 (Streamlit等のUIを想定) ---
      - name: app
        image: ghcr.io/<ユーザー名>/library-checker:0.1.0
        ports:
        - containerPort: 8501
        env:
        - name: SELENIUM_URL
          value: "http://localhost:4444" # 同じPod内なのでlocalhostでOK
        # .envの内容は本来ConfigMapやSecretを使いますが、一旦直接指定か環境変数で対応
        envFrom:
        - secretRef:
            name: library-checker-env # 先ほどデプロイしたシークレット
        # 生存確認
        readinessProbe:
            httpGet:
                path: /healthz
                port: 8501
            initialDelaySeconds: 5
            periodSeconds: 5
        livenessProbe:
            httpGet:
                path: /healthz
                port: 8501
            initialDelaySeconds: 10
            periodSeconds: 5

      # --- 2. Selenium Chrome (サイドカー) ---
      - name: chrome
        image: selenium/standalone-chrome:4.39.0-20251212
        ports:
        - containerPort: 4444
        resources:
          limits:
            memory: "2Gi"
            cpu: "1000m"
        volumeMounts:
        - name: dshm
          mountPath: /dev/shm

      # 共有メモリ (/dev/shm) の不足によるクラッシュを防ぐ設定
      volumes:
      - name: dshm
        emptyDir:
          medium: Memory
---
# --- 3. 外部公開用サービス ---
apiVersion: v1
kind: Service
metadata:
  name: library-checker-service
spec:
  type: NodePort
  selector:
    app: library-checker
  ports:
    - name: ui
      port: 8501
      targetPort: 8501
      nodePort: 30501 # 外部からアクセスするポート
    - name: selenium
      port: 4444
      targetPort: 4444
      nodePort: 30444

今回もGemini先生に頑張ってもらいました。

ということで動かしてみます。

動いてる!

動きました!やったー!

感想

自宅サーバー、あると便利ですね。

今後もk8sクラスタを活用した開発をしていこうと思います。

参考

Liveness ProbeとReadiness Probeを今度こそ理解する #kubernetes - Qiita