1. はじめに
本記事では、Kubernetes上にSpring Bootで構築したアプリを動作させるハンズオンをご紹介します。ひととおり実施して基本を理解すれば、ご自身で開発したアプリもKubernetes上で運用できるようになると思いますので、ぜひトライしてみて下さい。今回はStep2としてAPコンテナの作成方法をご説明します。
2. ハンズオン環境
Kubernetesがインストールされている環境を準備してください。今回はWindowsマシンのVirtualBox上に構築した仮想マシン上でKubernetesを構成しています。
・ホストマシン:Windows11
・仮想化ソフトウェア:VirtualBox 7.0
・仮想マシン:RHEL 8.5(Master Node:1台、Worker Node:2台)
・コンテナ・オーケストレーション:Kubernetes v1.29.12
オンプレでKuberntesインストールからやってみたいという方がいれば、下記を参考にして構築してもらえればと思います。
【初心者向け】Kubernetes学習向けのハンズオン(Linux(CentOS))
まだDBコンテナ作成が終わってないようでしたら下記を実施下さい。
【初心者向けハンズオン】KubernetesでJava(Spring Boot)アプリデプロイ ~Step1:DBコンテナ作成~
3. システム構成
Kubernetes上に構築するシステム構成を記載します。Web/AP、DBのシンプルなシステム構成で構築しています。AP PodについてはJavaが動作するDocker Imageをデプロイし、Executable Jarを起動することでアプリケーションを動作させます。

4. APコンテナの作成
4.1 Dockerイメージ作成
最初にDockerイメージを作成していきましょう。Dockerイメージとは、コンテナを作成・実行するためのテンプレートとなります。事前にDocker Hubにイメージを登録し、APコンテナ起動時にDocker Hubからイメージをpullして起動する流れとしています。Docker Hubを使用せずにプライベートレジストリを構築して利用する方法もありますので、どちらが良いかはご自身の用途に合わせて選択してください。
まだJarファイルを作成していない場合は、下記を参考にExecutable Jarを作成してください。
【初心者向け】Spring BootによるWebアプリ開発ハンズオン ~Step5:Linuxサーバへのデプロイ~
ローカル環境で動作させる時との違いとしては、データベースアクセス用のホスト名にStep1で作成したpostgresのサービス名を指定するという点になります。参考までに今回のハンズオン向けに作成したデータベースの設定ファイル(application.properties)を記載します。
#
# JDBC properties
#
spring.datasource.driver-class-name=org.postgresql.Driver
#spring.datasource.url=jdbc:postgresql://localhost:5432/quiz
spring.datasource.url=jdbc:postgresql://postgres:5432/quiz ##localhostからpostgres(サービス名)に変更##
spring.datasource.username=postgres
spring.datasource.password=password
#spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDiaLect
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
server.port=80
Executable Jarファイルが作成できたら、下記の通り適当なディレクトリに配置します。
[root@masternode ~]# cd /app/quizapp/
[root@masternode quizapp]#
[root@masternode quizapp]# ll
total 102588
-rw-r--r-- 1 root root 52519897 Feb 1 15:07 quizapp-1.0.jar
[root@masternode quizapp]#
続いてDockerfileを作成します。DockerfileとはDockerイメージ作成のための情報を記載したファイルとなります。各項目を簡単に説明します。
FROM | Dockerイメージのベースとなるイメージを指定します。ここでは、openjdk:21-jdkが使用できるイメージを指定しています。 |
ARG | ローカル変数を指定しています。 |
COPY | Podに対するコピー処理を記載します。ここではローカルのjarファイルをapp.jarという名称でPodに配置するための設定を記載しています。 |
ENTRYPOINT | Pod起動時にデフォルトで実行するコマンドを記載します。ここではjava -jarコマンドでSpring Bootアプリを起動する処理を記載しています。 |
下記の通りDockerfileを作成します。
[root@masternode ~]# cd /app/quizapp/
[root@masternode quizapp]# vi Dockerfile
[root@masternode quizapp]# cat Dockerfile
FROM openjdk:21-jdk
ARG JAR_FILE=./*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
[root@masternode quizapp]#
docker buildコマンドでDockerイメージを作成します。
[root@masternode quizapp]# docker build -t eeengineer1111/quizapp .
[+] Building 8.5s (8/8) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 142B 0.0s
=> [internal] load metadata for docker.io/library/openjdk:21-jdk 3.3s
=> [auth] library/openjdk:pull token for registry-1.docker.io 0.0s
=> [internal] load .dockerignore 0.1s
=> => transferring context: 2B 0.0s
=> [internal] load build context 2.0s
=> => transferring context: 52.53MB 2.0s
=> CACHED [1/2] FROM docker.io/library/openjdk:21-jdk@sha256:af9de795d1f8d3b6172f6c55ca9ba1c5768baa11bb2dc8af7045c7db9d4c33ac 0.0s
=> [2/2] COPY ./*.jar app.jar 1.8s
=> exporting to image 0.7s
=> => exporting layers 0.5s
=> => writing image sha256:f36301bfc8e12bab9e2b63db6726f4a0135cb64e56a30b4f283ef44432eab9e6 0.0s
=> => naming to docker.io/eeengineer1111/quizapp 0.1s
[root@masternode quizapp]#
docker imagesコマンドでDockerイメージが作成できていることを確認します。
[root@masternode quizapp]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
eeengineer1111/quizapp latest b7eb804d5b85 2 weeks ago 557MB
[root@masternode quizapp]#
作成したDockerイメージが実行できるか確認しましょう。docker imagesrunコマンドを下記の通り実行して下さい。
ローカル環境からはpostgres Podのサービスに接続できないのでデータベース接続のところでエラーになってはしまいますが、作成したDockerイメージが実行できるか確認してみて下さい。
[root@masternode quizapp]# docker run eeengineer1111/quizapp
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.3.7)
2025-02-19T23:54:04.608Z INFO 1 --- [ restartedMain] eeengineer.quizapp.QuizApplication : Starting QuizApplication v1.0 using Java 21 with PID 1 (/app.jar started by root in /)
2025-02-19T23:54:04.637Z INFO 1 --- [ restartedMain] eeengineer.quizapp.QuizApplication : No active profile set, falling back to 1 default profile: "default"
2025-02-19T23:54:04.947Z INFO 1 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
~~Omission~~
2025-02-19T23:54:38.692Z ERROR 1 --- [ restartedMain] o.h.engine.jdbc.spi.SqlExceptionHelper : The connection attempt failed.
2025-02-19T23:54:38.699Z WARN 1 --- [ restartedMain] o.h.e.j.e.i.JdbcEnvironmentInitiator : HHH000342: Could not obtain connection to query metadata
org.hibernate.exception.JDBCConnectionException: unable to obtain isolated JDBC connection [The connection attempt failed.] [n/a]
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:100) ~[app.jar:1.0]
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:58) ~[app.jar:1.0]
~~Omission~~
4.2 Docker HubにDockerイメージをPush
作成したDockerイメージをDocker HubにPushします。まず、下記サイトを参考にDocker Hubでアカウントを作成してください。
https://docs.docker.jp/mac/step_five.html
アカウントが作成できたら、下記コマンドを実行してDocker Hubにログインします。
[root@masternode ~]# docker login
Log in with your Docker ID or email address to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com/ to create one.
You can log in with your password or a Personal Access Token (PAT). Using a limited-scope PAT grants better security and is required for organizations using SSO. Learn more at https://docs.docker.com/go/access-tokens/
Username: eeengineer1111
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See

docker login
Login Succeeded
[root@masternode ~]#
docker pushコマンドを実行し、Docker Hubに作成したimageを登録します。
[root@masternode ~]# docker push eeengineer1111/quizapp
Using default tag: latest
The push refers to repository [docker.io/eeengineer1111/quizapp]
~~Omission~~
4611c85d409a: Pushed
latest: digest: sha256:f59f4b3ba8365aa570ecf1c2b382aefdbebacaf0bc98943a79565d47bfbb4ddb size: 1166
docker searchコマンドを実行し、Docker HubにイメージがPushできていることを確認します。
[root@masternode ~]# docker search eeengineer1111/quizapp
NAME DESCRIPTION STARS OFFICIAL
eeengineer1111/quizapp 0
~~Ommission~~
[root@masternode ~]#
4.3 AP Pod作成
Dockerイメージの準備ができたので、AP Podを作成していきましょう。下記の通りdeployment向けのマニフェストを作成します。
imageの項目にDocker Hubに登録したイメージ(eeengineer1111/quizapp)を指定して下さい。
[root@masternode ~]# cd /app/quizapp/manifest/
[root@masternode manifest]#
[root@masternode manifest]# vi quizapp-deployment.yaml
[root@masternode manifest]# cat quizapp-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: quizapp
name: quizapp
namespace: quizapp
spec:
replicas: 3
selector:
matchLabels:
app: quizapp
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: quizapp
spec:
containers:
- image: eeengineer1111/quizapp
ports:
- containerPort: 8080
name: quizapp
resources: {}
status: {}
[root@masternode manifest]#
deploymentのマニフェストを適用します。下記の通りquizappのPodのSTATUSがRunningになっていれば成功です。
[root@masternode manifest]# kubectl apply -f quizapp-deployment.yaml
deployment.apps/quizapp created
[root@masternode manifest]#
[root@masternode manifest]# kubectl get pod -n quizapp
NAME READY STATUS RESTARTS AGE
postgres-58c98dcd44-5hf7z 1/1 Running 0 68m
postgres-58c98dcd44-cbspd 1/1 Running 0 68m
postgres-58c98dcd44-rq9d9 1/1 Running 0 68m
quizapp-9446b7c78-dml2g 1/1 Running 0 18s
quizapp-9446b7c78-f89x7 1/1 Running 0 18s
quizapp-9446b7c78-gpqv6 1/1 Running 0 18s
[root@masternode manifest]#
続いてquizappのserviceを作成します。Step3でIngress Gateway経由で接続する際に必要となりますので、この時点で作成しておきましょう。下記の通りマニフェストを作成してください。
[root@masternode manifest]# vi quizapp-service.yaml
[root@masternode manifest]# cat quizapp-service.yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: quizapp
name: quizapp
namespace: quizapp
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
selector:
app: quizapp
status:
loadBalancer: {}
[root@masternode manifest]#
serviceのマニフェストを適用します。下記の通りquizappのserviceが取得できれば成功です。
[root@masternode manifest]# kubectl apply -f quizapp-service.yaml
service/quizapp created
[root@masternode manifest]#
[root@masternode manifest]# kubectl get service -n quizapp
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
postgres LoadBalancer 10.106.194.35 192.168.100.200 5432:30168/TCP 9m7s
quizapp NodePort 10.106.216.155 <none> 80:30247/TCP 9s
[root@masternode manifest]#
4.4 AP Podの動作確認
AP Podの動作確認をしていきましょう。まずはkubectl getコマンドに-o wideオプションをつけて、quizapp Podに直接アクセスするためのIPアドレスを取得します。
[root@masternode manifest]# kubectl get pod -o wide -n quizapp
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
postgres-58c98dcd44-5hf7z 1/1 Running 0 70m 192.168.100.42 masternode <none> <none>
postgres-58c98dcd44-cbspd 1/1 Running 0 70m 192.168.100.43 workernode1 <none> <none>
postgres-58c98dcd44-rq9d9 1/1 Running 0 70m 192.168.100.24 workernode2 <none> <none>
quizapp-9446b7c78-dml2g 1/1 Running 0 118s 192.168.100.45 masternode <none> <none>
quizapp-9446b7c78-f89x7 1/1 Running 0 118s 192.168.100.26 workernode1 <none> <none>
quizapp-9446b7c78-gpqv6 1/1 Running 0 118s 192.168.100.25 workernode2 <none> <none>
[root@masternode manifest]#
curlコマンドでアプリケーションにアクセスしてみましょう。下記の通りアプリ画面の情報が取得できれば成功です。
[root@masternode ~]# curl http://192.168.100.45:8080/quiz/public
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ITエンジニア育成クイズ</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
</head>
<body>
<div class="container">
<h3>ITエンジニア育成クイズ</h3>
<a href= "/login" >ユーザ登録/ログイン</a>
~~Omission~~
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>[root@masternode ~]#
5. まとめ
APコンテナ作成のハンズオンは以上となります。Step2では個別のAP Podに対してアクセスできることを確認しました。Step3ではIngress経由でアクセスすることで、AP Podへのアクセスを振り分ける方法についてご紹介します。
コメント