{"id":1997,"date":"2022-02-08T12:00:00","date_gmt":"2022-02-08T11:00:00","guid":{"rendered":"https:\/\/kindsonthegenius.com\/blog\/deploy-springboot-with-mysql-to-kubernetes-minikube-step-by-step-tutorial\/"},"modified":"2026-08-28T16:17:18","modified_gmt":"2026-08-28T14:17:18","slug":"deploy-springboot-with-mysql-to-kubernetes-minikube-step-by-step-tutorial","status":"publish","type":"post","link":"https:\/\/kindsonthegenius.com\/blog\/deploy-springboot-with-mysql-to-kubernetes-minikube-step-by-step-tutorial\/","title":{"rendered":"Deploy SpringBoot with MySQL to Kubernetes (Minikube) \u2013 Step by Step Tutorial"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><em>Learn how to deploy SpringBoot with MySQL to Kubernetes using Minikube, including MySQL deployment, application configuration, services, and testing.<\/em><\/p>\n\n\n<h3>TL;DR<\/h3>\n<ul>\n<li>\n<p>Create a Kubernetes deployment for the MySQL database.<\/p>\n<\/li>\n<li>\n<p>Use a PersistentVolumeClaim to provide persistent storage for MySQL.<\/p>\n<\/li>\n<li>\n<p>Test the MySQL deployment inside the Minikube cluster.<\/p>\n<\/li>\n<li>\n<p>Configure the SpringBoot application to connect to MySQL using environment variables.<\/p>\n<\/li>\n<li>\n<p>Create a Kubernetes deployment and service for the SpringBoot application.<\/p>\n<\/li>\n<li>\n<p>Apply the YAML files and access the application through the Minikube node IP and NodePort.<\/p>\n<\/li>\n<\/ul>\n<p>In the previous two tutorials we covered how to setup local Kubernetes (Minikube) and deploy a SpringBoot application. You can find these tutorials below.<\/p>\n<ul>\n<li class=\"bms-title\"><a href=\"https:\/\/kindsonthegenius.com\/blog\/setup-kubernetes-locally-deploy-springboot-application-step-by-step-tutorial\/\" target=\"_blank\" rel=\"bookmark noopener\">Setup Kubernetes Locally \u2013 Deploy SpringBoot Application \u2013 Step by Step Tutorial<\/a><\/li>\n<li class=\"bms-title\"><a href=\"https:\/\/kindsonthegenius.com\/blog\/deploy-springboot-application-to-kubernetesminikube-using-deployment-yaml-file\/\" target=\"_blank\" rel=\"bookmark noopener\">Deploy SpringBoot Application to Kubernetes(Minikube) Using Deployment yaml file<\/a><\/li>\n<\/ul>\n<p>In this tutorial, we would now cover how to deploy SpringBoot application with MySQL database. In this case, we would take the following steps:<\/p>\n<ul>\n<li>Create a deployment for MySQL<\/li>\n<li>Create a deployment for our SpringBoot Application<\/li>\n<\/ul>\n<p>We would cover the following sub-topics:<\/p>\n<ol>\n<li><a href=\"#t1\">Create the Deployment YAML for MySQL<\/a><\/li>\n<li><a href=\"#t2\">Test the MySQL Deployment<\/a><\/li>\n<li><a href=\"#t3\">Modify the Application Properties file<\/a><\/li>\n<li><a href=\"#t4\">Create the Application YAML File<\/a><\/li>\n<li><a href=\"#t5\">Deploy and Test the Application<\/a><\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h4><strong id=\"t1\">1. Create the Deployment Yaml for MySQL<\/strong><\/h4>\n<p>This deployment file for MySQL would be used to setup MySQL in the Kubernetes cluster. It would pull the MySQL image from the local or remote repository, create a new database, and spin up the container inside the cluster. This deployment file would have three parts: Service, PersistentVolumeClaim and Deployment.<\/p>\n<p><strong>Service<\/strong><\/p>\n<p>As you already know, the service is used to expose the deployment and make it accessible from outside and from other pods. The service part of the <strong><em>mysql-deployment.yaml<\/em> <\/strong>file is given below:<br \/><!-- HTML generated using hilite.me --><\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #888888;\"># Define a 'Service' To Expose MySQL to Other Services<\/span>\napiVersion: v1\nkind: Service\nmetadata:\n  name: mysql\n  labels:\n    app: mysql\n    tier: database\nspec:\n  ports:\n    - port: 3307\n      targetPort: 3307\n  selector:\n    app: mysql\n    tier: database\n  clusterIP: None <span style=\"color: #888888;\"># DNS is used, so clusterIP is not needed<\/span>\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>PersistentVolumeClaim<\/strong><\/p>\n<p>A PersistentVolume is a piece of storage provided in a cluster either dynamically or by an administrator.<\/p>\n<p>A PersistentVolumeClaim(PVC) is a request for storage (PV) by a user. Think of it as a pod made specially for providing storage space for other pods.<\/p>\n<p>The PVC is defined in the MySQL deployment file. This is specified in the deployment file as follows:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #888888;\"># Define a 'Persistent Volume Claim'(PVC) for MySQL Storage, dynamically provisioned by cluster<\/span>\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  name: mysql-pv-claim <span style=\"color: #888888;\"># name of PVC essential for identifying the storage data<\/span>\n  labels:\n    app: mysql\n    tier: database\nspec:\n  accessModes:\n    - ReadWriteOnce   <span style=\"color: #888888;\">#This specifies the mode of the claim that we are trying to create.<\/span>\n  resources:\n    requests:\n      storage: 1Gi    <span style=\"color: #888888;\">#This will tell kubernetes about the amount of space we are trying to claim.<\/span>\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Deployment<\/strong><\/p>\n<p>The actual deployment specification is given below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #888888;\"># Deployment specification begins here<\/span>\napiVersion: apps\/v1\nkind: Deployment\nmetadata:\n  name: mysql\n  labels:\n    app: mysql\n    tier: database\nspec:\n  selector: <span style=\"color: #888888;\"># mySQL Pod Should contain same labels<\/span>\n    matchLabels:\n      app: mysql\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels: <span style=\"color: #888888;\"># Must match 'Service' and 'Deployment' selectors<\/span>\n        app: mysql\n        tier: database\n    spec:\n      containers:\n        - name: mysql\n          image: mysql\n          imagePullPolicy: <span style=\"background-color: #fff0f0;\">\"IfNotPresent\"<\/span>\n          env:\n            - name: MYSQL_ROOT_PASSWORD\n              value: root\n            - name: MYSQL_DATABASE\n              value: fleetdb\n          ports:\n            - containerPort: 3307\n              name: mysql\n          volumeMounts:\n            - mountPath: \/var\/lib\/mysql\n              name: mysql-persistance-storage\n      volumes:\n        - name: mysql-persistance-storage\n          persistentVolumeClaim:\n            claimName: mysql-pv-claim\n<\/pre>\n<p>&nbsp;<\/p>\n<p>I would recommend you watch to video tutorial in <a href=\"https:\/\/www.youtube.com\/c\/KindsonTheTechPro\" target=\"_blank\" rel=\"noopener\">my YouTube Channel<\/a> for a more detailed explanation of\u00a0 the various part of the deployment file. The <a href=\"https:\/\/github.com\/KindsonTheGenius\/fleetmsv2\/blob\/master\/src\/main\/resources\/mysql-deployment.yaml\" target=\"_blank\" rel=\"noopener\">complete mysql-deployment.yaml file can be found here.<\/a><\/p>\n<p>&nbsp;<\/p>\n<h4><strong id=\"t2\">2. Test the MySQL Deployment<\/strong><\/h4>\n<p>You now need to actually apply the deployment using the command below.<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">kubectl apply -f mysql-deployment.yaml\n<\/pre>\n<p>This command would deploy the service and spin up the containers (pods) in Minikube.<\/p>\n<p>You can then verify that the pods are created using the <strong><em>kubectl get pods<\/em><\/strong> command<\/p>\n<p><strong>Access the MySQL Database inside the cluster<\/strong><\/p>\n<p>Now that the MySQL is deployed, we would like to connect to the node right inside the cluster. You can use the command below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">kubectl exec -it &lt;pod_name&gt; bash\n<\/pre>\n<p>Then use the command below to connect to the MySQL server.<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">mysql -h mysql -u root -p \n<\/pre>\n<p>&nbsp;<\/p>\n<h4><strong id=\"t3\">3. Modify the Application Properties File<\/strong><\/h4>\n<p>We need to modify the application.properties file so that instead of using the hardcoded environment variables for the database, we need to make the values dynamic. So in this case, we can connect to the MySQL port running inside the cluster.<\/p>\n<p>You actually only need to change the username, password and url like so:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">spring.datasource.password=${DB_USERNAME}\nspring.datasource.username=${DB_PASSWORD}\nspring.datasource.url=jdbc:mysql:\/\/${DB_HOST}\/${DB_NAME}?useSSL=false\n<\/pre>\n<p>The useSSL=false line indicates that the database server need not be verified.<\/p>\n<p>&nbsp;<\/p>\n<h4><strong id=\"t4\">4. Create the Application Deployment<\/strong><\/h4>\n<p>Similar to the mysql-deployment, the app-deployment would contain two parts: the service and the deployment. These are shown below:<\/p>\n<p><strong>the deployment part<\/strong><\/p>\n<p>The deployment part of the app-deployment.yaml file is given below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0e84b5; font-weight: bold;\">---<\/span>\napiVersion: apps\/v1\nkind: Deployment\nmetadata:\n  name: fleetms-v2\nspec:\n  selector:\n    matchLabels:\n      app: fleetms-v2\n  replicas: 3\n  template:\n    metadata:\n      labels:\n        app: fleetms-v2\n    spec:\n      containers:\n        - name: fleetms-v2\n          image: fleetms-v2:1.0\n          ports:\n            - containerPort: 8080\n          env:   <span style=\"color: #888888;\"># Setting Environmental Variables<\/span>\n            - name: DB_HOST   <span style=\"color: #888888;\"># Setting Database host address<\/span>\n              value: mysql\n            - name: DB_NAME  <span style=\"color: #888888;\"># Setting Database name<\/span>\n              value: fleetdb\n            - name: DB_USERNAME  <span style=\"color: #888888;\"># Setting Database username<\/span>\n              value: root\n            - name: DB_PASSWORD <span style=\"color: #888888;\"># Setting Database password<\/span>\n              value: root\n<span style=\"color: #888888;\"># This seperator --- below is MANDATORY!!!<\/span>\n<span style=\"color: #0e84b5; font-weight: bold;\">---<\/span>\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>the service part<\/strong><\/p>\n<p>The service part of the file is given below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #888888;\"># Define a 'Service' To Expose the application<\/span>\napiVersion: v1\nkind: Service\nmetadata:\n  name: fleetms-service\nspec:\n  ports:\n    - protocol: <span style=\"background-color: #fff0f0;\">\"TCP\"<\/span>\n      port: 8080    <span style=\"color: #888888;\"># Port inside the cluster<\/span>\n      targetPort:   <span style=\"color: #888888;\"># Port exposed to the outside<\/span>\n  selector:\n    app: fleetms-v2\n  type: NodePort\n<\/pre>\n<p>&nbsp;<\/p>\n<h4><strong id=\"t5\">5. Deploy and Test the Application<\/strong><\/h4>\n<p>Now\u00a0 that you have the app-deployment.yaml, you can apply the deployment using the command below after you navigate to the resources folder:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">kubectl apply -f app-deployment.yaml\n<\/pre>\n<p>&nbsp;<\/p>\n<p>You can then access the application using the node ip (from<em><strong> minikube ip<\/strong><\/em> command) and the node port (from<em><strong> kubectl get services<\/strong><\/em> command)<\/p>\n<p>I recommend you watch the video in<a href=\"https:\/\/www.youtube.com\/c\/KindsonTheTechPro\" target=\"_blank\" rel=\"noopener\"> my YouTube Channel<\/a> for clarification.<\/p>\n<h3>FAQs<\/h3>\n<p><strong>How do I deploy SpringBoot with MySQL to Kubernetes?<\/strong><\/p>\n<p>Create separate Kubernetes deployments for MySQL and the SpringBoot application, configure a service for each, and connect the application to MySQL using environment variables.<\/p>\n<p><strong>How do I deploy MySQL to Kubernetes with Minikube?<\/strong><\/p>\n<p>Create a MySQL deployment YAML containing a Service, PersistentVolumeClaim, and Deployment, then apply it using <code>kubectl apply -f mysql-deployment.yaml<\/code>.<\/p>\n<p><strong>How do I connect SpringBoot to MySQL running in Kubernetes?<\/strong><\/p>\n<p>Configure the SpringBoot datasource to use environment variables such as the database host, name, username, and password. The MySQL service name can be used as the database host inside the cluster.<\/p>\n<p><strong>How do I test MySQL inside a Kubernetes cluster?<\/strong><\/p>\n<p>Use <code>kubectl get pods<\/code> to find the MySQL pod, then connect to it with <code>kubectl exec -it &lt;pod_name&gt; bash<\/code> and use the MySQL client to connect to the database service.<\/p>\n<p><strong>How do I access the SpringBoot application in Minikube?<\/strong><\/p>\n<p>Expose the SpringBoot deployment using a Kubernetes Service with <code>NodePort<\/code>, then use the Minikube IP and the assigned NodePort to access the application.<\/p>\n<h3>Final Thoughts<\/h3>\n<p>Deploying SpringBoot with MySQL to Kubernetes introduces the basic concepts needed to run an application and its database inside a Minikube cluster. The MySQL deployment provides the database and persistent storage, while the SpringBoot deployment runs the application and connects to MySQL through the Kubernetes service.<\/p>\n<p>Once both deployments are applied and running, you can test the database inside the cluster and access the SpringBoot application through the Minikube node IP and NodePort. This provides a practical foundation for understanding how applications with databases can be deployed to Kubernetes.<\/p>","protected":false},"excerpt":{"rendered":"<p>Learn how to deploy SpringBoot with MySQL to Kubernetes using Minikube, including MySQL deployment, application configuration, services, and testing. TL;DR Create a Kubernetes deployment for &hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"pagelayer_contact_templates":[],"_pagelayer_content":"","footnotes":""},"categories":[311],"tags":[],"class_list":["post-1997","post","type-post","status-publish","format-standard","hentry","category-sql"],"acf":[],"_links":{"self":[{"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/posts\/1997","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/comments?post=1997"}],"version-history":[{"count":3,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/posts\/1997\/revisions"}],"predecessor-version":[{"id":2583,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/posts\/1997\/revisions\/2583"}],"wp:attachment":[{"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/media?parent=1997"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/categories?post=1997"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/tags?post=1997"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}