{"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-07-05T03:26:26","modified_gmt":"2026-07-05T01:26:26","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":"<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:\/\/www.kindsonthegenius.com\/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:\/\/www.kindsonthegenius.com\/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 \/>\n<!-- 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>\r\napiVersion: v1\r\nkind: Service\r\nmetadata:\r\n  name: mysql\r\n  labels:\r\n    app: mysql\r\n    tier: database\r\nspec:\r\n  ports:\r\n    - port: 3307\r\n      targetPort: 3307\r\n  selector:\r\n    app: mysql\r\n    tier: database\r\n  clusterIP: None <span style=\"color: #888888;\"># DNS is used, so clusterIP is not needed<\/span>\r\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>\r\napiVersion: v1\r\nkind: PersistentVolumeClaim\r\nmetadata:\r\n  name: mysql-pv-claim <span style=\"color: #888888;\"># name of PVC essential for identifying the storage data<\/span>\r\n  labels:\r\n    app: mysql\r\n    tier: database\r\nspec:\r\n  accessModes:\r\n    - ReadWriteOnce   <span style=\"color: #888888;\">#This specifies the mode of the claim that we are trying to create.<\/span>\r\n  resources:\r\n    requests:\r\n      storage: 1Gi    <span style=\"color: #888888;\">#This will tell kubernetes about the amount of space we are trying to claim.<\/span>\r\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>\r\napiVersion: apps\/v1\r\nkind: Deployment\r\nmetadata:\r\n  name: mysql\r\n  labels:\r\n    app: mysql\r\n    tier: database\r\nspec:\r\n  selector: <span style=\"color: #888888;\"># mySQL Pod Should contain same labels<\/span>\r\n    matchLabels:\r\n      app: mysql\r\n  strategy:\r\n    type: Recreate\r\n  template:\r\n    metadata:\r\n      labels: <span style=\"color: #888888;\"># Must match 'Service' and 'Deployment' selectors<\/span>\r\n        app: mysql\r\n        tier: database\r\n    spec:\r\n      containers:\r\n        - name: mysql\r\n          image: mysql\r\n          imagePullPolicy: <span style=\"background-color: #fff0f0;\">\"IfNotPresent\"<\/span>\r\n          env:\r\n            - name: MYSQL_ROOT_PASSWORD\r\n              value: root\r\n            - name: MYSQL_DATABASE\r\n              value: fleetdb\r\n          ports:\r\n            - containerPort: 3307\r\n              name: mysql\r\n          volumeMounts:\r\n            - mountPath: \/var\/lib\/mysql\r\n              name: mysql-persistance-storage\r\n      volumes:\r\n        - name: mysql-persistance-storage\r\n          persistentVolumeClaim:\r\n            claimName: mysql-pv-claim\r\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\r\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\r\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 \r\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}\r\nspring.datasource.username=${DB_PASSWORD}\r\nspring.datasource.url=jdbc:mysql:\/\/${DB_HOST}\/${DB_NAME}?useSSL=false\r\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>\r\napiVersion: apps\/v1\r\nkind: Deployment\r\nmetadata:\r\n  name: fleetms-v2\r\nspec:\r\n  selector:\r\n    matchLabels:\r\n      app: fleetms-v2\r\n  replicas: 3\r\n  template:\r\n    metadata:\r\n      labels:\r\n        app: fleetms-v2\r\n    spec:\r\n      containers:\r\n        - name: fleetms-v2\r\n          image: fleetms-v2:1.0\r\n          ports:\r\n            - containerPort: 8080\r\n          env:   <span style=\"color: #888888;\"># Setting Environmental Variables<\/span>\r\n            - name: DB_HOST   <span style=\"color: #888888;\"># Setting Database host address<\/span>\r\n              value: mysql\r\n            - name: DB_NAME  <span style=\"color: #888888;\"># Setting Database name<\/span>\r\n              value: fleetdb\r\n            - name: DB_USERNAME  <span style=\"color: #888888;\"># Setting Database username<\/span>\r\n              value: root\r\n            - name: DB_PASSWORD <span style=\"color: #888888;\"># Setting Database password<\/span>\r\n              value: root\r\n<span style=\"color: #888888;\"># This seperator --- below is MANDATORY!!!<\/span>\r\n<span style=\"color: #0e84b5; font-weight: bold;\">---<\/span>\r\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>\r\napiVersion: v1\r\nkind: Service\r\nmetadata:\r\n  name: fleetms-service\r\nspec:\r\n  ports:\r\n    - protocol: <span style=\"background-color: #fff0f0;\">\"TCP\"<\/span>\r\n      port: 8080    <span style=\"color: #888888;\"># Port inside the cluster<\/span>\r\n      targetPort:   <span style=\"color: #888888;\"># Port exposed to the outside<\/span>\r\n  selector:\r\n    app: fleetms-v2\r\n  type: NodePort\r\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\r\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","protected":false},"excerpt":{"rendered":"<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. Setup &hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"pagelayer_contact_templates":[],"_pagelayer_content":"","footnotes":""},"categories":[311],"tags":[],"class_list":["post-1997","post","type-post","status-publish","format-standard","hentry","category-sql"],"_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":1,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/posts\/1997\/revisions"}],"predecessor-version":[{"id":2165,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/posts\/1997\/revisions\/2165"}],"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}]}}