<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Malek Ramdani</title>
    <description>The latest articles on DEV Community by Malek Ramdani (@malek_ramdani).</description>
    <link>https://dev.to/malek_ramdani</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F287098%2Fa10b9c96-f5b5-46be-b091-cb0935f8ac57.jpg</url>
      <title>DEV Community: Malek Ramdani</title>
      <link>https://dev.to/malek_ramdani</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/malek_ramdani"/>
    <language>en</language>
    <item>
      <title>When Java meet GKE</title>
      <dc:creator>Malek Ramdani</dc:creator>
      <pubDate>Sun, 07 May 2023 05:15:14 +0000</pubDate>
      <link>https://dev.to/malek_ramdani/when-java-meet-gke-3a9c</link>
      <guid>https://dev.to/malek_ramdani/when-java-meet-gke-3a9c</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This post is the third and last one in our series 'When Java Meets...'. In the first two posts, we learned how to deploy a Java application with Docker and then with Kubernetes in a local environment. &lt;/p&gt;

&lt;p&gt;In this article, we will learn how to deploy our Java application on GKE, which is a managed service for deploying and managing containerized applications on Google Cloud Platform.&lt;br&gt;
 &lt;/p&gt;
&lt;h2&gt;
  
  
  What is GKE ?
&lt;/h2&gt;

&lt;p&gt;GKE stands for Google Kubernetes Engine, which is a managed service for deploying and managing containerized applications on Google Cloud Platform. It is a fully managed platform that allows you to easily run and manage containerized applications in the cloud.&lt;/p&gt;

&lt;p&gt;As we explained in the previous posts, Kubernetes is an open-source container orchestration system that allows you to deploy, scale, and manage containerized applications. GKE provides a fully managed Kubernetes environment that is optimized for running containerized applications on Google Cloud Platform. With GKE, you can focus on your application development while Google manages the underlying infrastructure.&lt;/p&gt;

&lt;p&gt;GKE provides features such as automatic scaling, load balancing, and automatic upgrades to ensure your application is always available and running smoothly. It also integrates with other Google Cloud Platform services such as Cloud Storage, Cloud SQL, and Cloud Build, making it easy to build and deploy modern cloud-native applications.&lt;/p&gt;

&lt;p&gt;In summary, GKE is a powerful and fully managed platform for deploying and managing containerized applications on Google Cloud Platform using Kubernetes.&lt;/p&gt;

&lt;p&gt;    &lt;/p&gt;
&lt;h2&gt;
  
  
  Environment configuration
&lt;/h2&gt;

&lt;p&gt;Before we can create a GKE cluster and deploy our application, The steps below needs to be performed:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Before to start, please ensure that you already have a GCP account, if not you can a create a GCP free tier  account, which will be sufficient for this tutorial.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;
  
  
  Install gcloud CLI
&lt;/h3&gt;

&lt;p&gt;Google Cloud (gcloud) CLI is a tool we can use to interact  with various Google Cloud Platform services from the command line, such as Google Compute Engine, Google Kubernetes Engine, and Google Cloud Storage.  &lt;/p&gt;

&lt;p&gt;For example, you can use the gcloud CLI to create and manage the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compute Engine virtual machine instances and other resources&lt;/li&gt;
&lt;li&gt;Cloud SQL instances&lt;/li&gt;
&lt;li&gt;Google Kubernetes Engine clusters&lt;/li&gt;
&lt;li&gt;Dataproc clusters and jobs&lt;/li&gt;
&lt;li&gt;Cloud DNS managed zones and record sets&lt;/li&gt;
&lt;li&gt;Cloud Deployment Manager deployments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;gcloud also provides access to additional tools and commands for managing Google Cloud Platform services, including authentication and authorization, configuration management, and resource management.&lt;/p&gt;

&lt;p&gt;The installation below was done on a &lt;strong&gt;64-bit Ubuntu 20.04.1 LTS&lt;/strong&gt;. your environment may differ, you can find the installation types for other platfroms in this link : &lt;a href="https://cloud.google.com/sdk/docs/install"&gt;https://cloud.google.com/sdk/docs/install&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;First download the gcloud archive and extract the content of &lt;br&gt;
the file:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -O 
https://dl.google.com/dl/cloudsdk/channels/rapid/downloads
/google-cloud-cli-429.0.0-linux-x86_64.tar.gz

tar -xf google-cloud-cli-429.0.0-linux-x86_64.tar.gz

&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Run the installation script from the root of the folder you &lt;br&gt;
extracted to using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./google-cloud-sdk/install.sh
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Once the installation is done, run the gcloud init command:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud init
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;gcloud init performs the following setup steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authorizes the gcloud CLI to use your user account 
credentials to access Google Cloud, or lets you select an 
account if you have previously authorized access&lt;/li&gt;
&lt;li&gt;Sets up a gcloud CLI configuration and sets a base set of 
properties, including the active account from the step 
above, the current project, and if applicable, the default 
Compute Engine region and zone&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When gcloud init finishes, it prints the properties in the&lt;br&gt;
active configuration to the terminal::&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud init    
[compute]
region = us-east1
zone = us-east1-b
[core]
account = user@google.com
disable_usage_reporting = False
project = example-project```

&lt;/code&gt;&lt;/pre&gt;


&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now we are ready to create our project dedicated to our Players application.&lt;/p&gt;

&lt;p&gt;    &lt;/p&gt;

&lt;h3&gt;
  
  
  Create a new project in GCP
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;To create a new project run this command:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud projects create players-app --name="players-app project" --labels=type=tuto
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Once is done, activate the new project configuration by running this command:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud config configurations create playersapp --account your-gcp-account --project players-app
gcloud config configurations activate playersapp
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This command will create a new configuration and make it active. If you want to see the configuration list, run this command:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud config configurations list
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set the default region and zone for your project. This way you will not need to type those info when creating the GKE cluster and other resources:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud compute project-info add-metadata --metadata google-compute-default-region=europe-west1,google-compute-default-zone=europe-west1-b
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;If you want to do a check, you should see the keys &lt;strong&gt;google-compute-default-region&lt;/strong&gt; and &lt;strong&gt;google-compute-default-zone&lt;/strong&gt; with the region entered above after you execute this command:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud compute project-info describe --project players-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We are almost there, to avoid having an error message when creating our GKE cluster, we need to activate some GCP services by running this command:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud services enable compute.googleapis.com container.googleapis.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Play with GKE!
&lt;/h2&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Create the GKE cluster
&lt;/h3&gt;

&lt;p&gt;Now that everything is ready, we can create a GKE cluster that we will call players-gke by executing this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud container clusters create players-gke --release-channel None
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can check in the GCP web console that our GKE cluster is now up and running:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuhvvnlwdkl2r2wc6ilb1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuhvvnlwdkl2r2wc6ilb1.png" alt="Image description" width="800" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As simple as that! now we have a Kubernetes cluster ready to host our application!&lt;br&gt;
 &lt;/p&gt;
&lt;h3&gt;
  
  
  Install kubectl tool
&lt;/h3&gt;

&lt;p&gt;To interact with our cluster we need to use kubectl. in your shell terminal run this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud components install kubectl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To verify that &lt;strong&gt;kubectl&lt;/strong&gt; is installed run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run this command to update &lt;strong&gt;kubectl&lt;/strong&gt; configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud container clusters get-credentials players-gke \
    --region=northamerica-northeast2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify that your configuration is done properly by typing this command :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl get namespaces
NAME              STATUS   AGE
default           Active   40m
kube-node-lease   Active   40m
kube-public       Active   40m
kube-system       Active   40m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Alright, let's deploy our application on our newly created cluster!&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy players app on GKE
&lt;/h3&gt;

&lt;p&gt;In the same way we did on the local Kubernetes cluster in the &lt;a href="https://dev.to/malek_ramdani/when-java-meet-docker-part-ii-kubernetes-1cm1"&gt;previous post&lt;/a&gt;, we will use kubectl appl to deploy our application, using two yaml files that you can find in this &lt;a href="https://github.com/MalikooR/players_spring_boot/tree/main/kubernetes"&gt;GitHub repo&lt;/a&gt;, one for the SpringBoot application and the other for the postgres database :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl apply -f postgres.yaml 
deployment.apps/playersdb created
service/playersdb created
$ kubectl apply -f deployment.yaml 
deployment.apps/players created
service/players created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our workload is deployed and we can see in the cloud console:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fppl2t4mgswlg5sszje2c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fppl2t4mgswlg5sszje2c.png" alt="Image description" width="800" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can also see the services that has been created:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyig0g0whe4ktmtowx3fh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyig0g0whe4ktmtowx3fh.png" alt="Image description" width="800" height="243"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Test our application
&lt;/h3&gt;

&lt;p&gt;To test our application we need to make a REST api call to the players app which is exposed through a Node port.&lt;/p&gt;

&lt;p&gt;First we need to view the service, the output shows a nodePort value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl get service players --output yaml
apiVersion: v1
kind: Service
metadata:
  annotations:
    cloud.google.com/neg: '{"ingress":true}'
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"creationTimestamp":null,"labels":{"app":"players"},"name":"players","namespace":"default"},"spec":{"ports":[{"port":8080,"protocol":"TCP","targetPort":8080}],"selector":{"app":"players"},"type":"NodePort"},"status":{"loadBalancer":{}}}
  creationTimestamp: "2023-05-08T03:12:39Z"
  labels:
    app: players
  name: players
  namespace: default
  resourceVersion: "27799"
  uid: a719a733-f2d9-4a42-9a97-f49af11d62fb
spec:
  clusterIP: 10.72.9.232
  clusterIPs:
  - 10.72.9.232
  externalTrafficPolicy: Cluster
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - nodePort: 31538
    port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app: players
  sessionAffinity: None
  type: NodePort
status:
  loadBalancer: {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see above that the nodePort value is &lt;strong&gt;31538&lt;/strong&gt;. We create a firewall rule to allow TCP traffic on your node port:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud compute firewall-rules create test-node-port --allow tcp:31538
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need alos to find the external IP address of one of our nodes :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl get nodes --output wide
NAME                                         STATUS   ROLES    AGE   VERSION            INTERNAL-IP   EXTERNAL-IP      OS-IMAGE                             KERNEL-VERSION   CONTAINER-RUNTIME
gke-players-gke-default-pool-5fe50b35-6l48   Ready    &amp;lt;none&amp;gt;   65m   v1.25.7-gke.1000   10.188.0.9    34.130.171.114   Container-Optimized OS from Google   5.15.65+         containerd://1.6.18
gke-players-gke-default-pool-5fe50b35-j7dw   Ready    &amp;lt;none&amp;gt;   65m   v1.25.7-gke.1000   10.188.0.8    34.130.43.212    Container-Optimized OS from Google   5.15.65+         containerd://1.6.18
gke-players-gke-default-pool-5fe50b35-jn77   Ready    &amp;lt;none&amp;gt;   65m   v1.25.7-gke.1000   10.188.0.7    34.130.245.5     Container-Optimized OS from Google   5.15.65+         containerd://1.6.18
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally we can start testing our service by sending our API call using on of the external node IPs in our URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl -i --location --request GET '34.130.43.212:31538/api/player/v1/test'
HTTP/1.1 200 
Content-Type: text/plain;charset=UTF-8
Content-Length: 14
Date: Mon, 08 May 2023 03:40:52 GMT

This is a test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! We can see that our application is responding, now we can make another api calls to add players and get the list of them as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl -i --location --request POST 'http://34.130.171.114:31538/api/player/v1/add' \
--header 'Content-Type: application/json' \
--data-raw '{
    "firstName": "Riyad",
    "lastName": "Mahrez",
    "team": "Manchester City",
    "position": "RW"
}'

HTTP/1.1 200 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Mon, 08 May 2023 03:43:54 GMT

{"id":1,"firstName":"Riyad","lastName":"Mahrez","team":"Manchester City","position":"RW"}

$ curl -i --location --request POST 'http://34.130.171.114:31538/api/player/v1/add' \
--header 'Content-Type: application/json' \
--data-raw '{
    "firstName": "Ismail",
    "lastName": "Bennacer",
    "team": "AC Milan",
    "position": "CM"
}'

{"id":2,"firstName":"Ismail","lastName":"Bennacer","team":"AC Milan","position":"CM"}

$ curl -i --location --request GET 'http://34.130.245.5:31538/api/player/v1/list'

HTTP/1.1 200 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Mon, 08 May 2023 03:47:42 GMT

[{"id":1,"firstName":"Riyad","lastName":"Mahrez","team":"Manchester City","position":"RW"},{"id":2,"firstName":"Ismail","lastName":"Bennacer","team":"AC Milan","position":"CM"}]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congratulations! You've made it to the end of our practical guide on containerizing a Java application and deploying it in various environments using Docker, a local Kubernetes cluster, and a public cloud Kubernetes cluster. By following the steps outlined in this series of posts, you should now have a solid understanding of the containerization process and how to deploy your application to a Kubernetes cluster.&lt;/p&gt;

&lt;p&gt;We hope this guide has been helpful in your journey towards mastering containerization and Kubernetes deployment. Remember, this is just the beginning, and there is always more to learn and explore in this ever-evolving field.&lt;/p&gt;

&lt;p&gt;Thank you for reading, and happy containerizing!&lt;/p&gt;

</description>
      <category>java</category>
      <category>kubernetes</category>
      <category>cloudcomputing</category>
      <category>gcp</category>
    </item>
    <item>
      <title>When Java meet Docker... Part II kubernetes</title>
      <dc:creator>Malek Ramdani</dc:creator>
      <pubDate>Tue, 18 Apr 2023 04:05:30 +0000</pubDate>
      <link>https://dev.to/malek_ramdani/when-java-meet-docker-part-ii-kubernetes-1cm1</link>
      <guid>https://dev.to/malek_ramdani/when-java-meet-docker-part-ii-kubernetes-1cm1</guid>
      <description>&lt;p&gt;In the previous post &lt;a href="https://dev.to/malek_ramdani/when-java-meet-docker-part-i-2iip"&gt;When Java Meets Docker Part I&lt;/a&gt;, we covered the basics of Cloud-Native, Docker, and how to deploy a simple Java application. In this post, we'll take it a step further. First, we'll implement a more sophisticated application using the Spring Boot framework. Then, we'll deploy this application in a more efficient and practical way using Docker Compose. Finally, we'll go even further by deploying it in Kubernetes on our local environment using Minikube. Let's start !&lt;/p&gt;

&lt;p&gt;The architecture of our solution remains the same: a Java application that connects to a database. However, this time, we're going to have a Spring Boot application that exposes REST APIs. We'll have two API endpoints: POST &lt;a href="http://myserver:8080/api/player/v1/add"&gt;http://myserver:8080/api/player/v1/add&lt;/a&gt; to create a new player and save it into our database, and GET &lt;a href="http://myserver:8080/api/player/v1/list"&gt;http://myserver:8080/api/player/v1/list&lt;/a&gt; to retrieve the list of players we have in our database. Additionally, we'll have an API for testing purposes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As the objective of this post is not Java development itself, we won't go into too much detail about how to develop an application in Spring Boot.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Players app v2
&lt;/h2&gt;

&lt;p&gt;For our updated "Players" application, we will be able to add and view the list of players through REST APIs. To achieve this, we'll have two API endpoints. The first will create a new player and save it into our database: POST &lt;a href="http://myserver:8080/api/player/v1/add"&gt;http://myserver:8080/api/player/v1/add&lt;/a&gt;. The second will retrieve the list of players we have in our database: GET &lt;a href="http://myserver:8080/api/player/v1/list"&gt;http://myserver:8080/api/player/v1/list&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In summary, our application should now look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6g8tvxvicw0qj32q7mm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6g8tvxvicw0qj32q7mm.png" alt="Image description" width="800" height="212"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In this solution we will not need to create a table in the database, springboot will take care of it. To achieve this we have put the property spring.jpa.hibernate.ddl-auto=create-drop in our properties file, which will indicate to our application to drop and create the table based on the class (entity) Player.java at every start up. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The code source of the application can be found in this GitHub repo : &lt;a href="https://github.com/MalikooR/players_spring_boot/tree/main/players"&gt;https://github.com/MalikooR/players_spring_boot/tree/main/players&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Push docker image to docker hub
&lt;/h2&gt;

&lt;p&gt;Before we start using Docker Compose, let's containerize our Spring Boot application and push it to Docker Hub. This will allow us to use the container at different stages of this post. Creating the container is a simple process and follows the same steps we covered in the previous post.&lt;/p&gt;

&lt;p&gt;Once we've executed the Maven package goal on our application, a .jar file will be created in the target folder. We'll then copy this jar file to a new folder and create a Dockerfile with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM adoptopenjdk:11-jre-hotspot
ARG JAR_FILE=players.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And run this command :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t malikoo/players:1.0 .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where malikoo is the dockerhub user, players is the repository name and the number after the semicolon is the image tag.&lt;/p&gt;

&lt;p&gt;Now we can push our image into docker hub simply by executing the command below :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker push malikoo/players:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Before running the docker push command, you need to run docker login and use your docker hub credentials to connect to the registry.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Docker compose
&lt;/h2&gt;

&lt;p&gt;In this step we are going to deploy our application using docker compose. Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration. &lt;/p&gt;

&lt;p&gt;In our case our we will have two services, our java application running on &lt;strong&gt;playersapp&lt;/strong&gt; container exposing a service on the port 8080 which will be mapped to the port 8080 of the host machine and the Postgres db &lt;strong&gt;playersdb&lt;/strong&gt; that will expose a service on a port 5432 mapped to the port 5555 of the host machine.&lt;br&gt;
create a yaml file and past the following :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services:
  web:
    container_name: playersapp
    depends_on:
      - post
    image: malikoo/players:1.0
    ports:
      - "8080:8080"
    environment:
      POSTGRES_URL: playersdb:5432/testdb
  post:
    image: postgres
    container_name: playersdb
    ports:
      - "5555:5432"
    environment:
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: testdb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note that the default compose file name is docker-compose.yaml, with this filename you won't need to specify the file to docker compose as long as it's in the current path. Otherwise, you should use -f option to specify your custom file name.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that our docker compose file is ready, all we need is to run this command :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can test that the process went well by checking this address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl --location --request GET 'localhost:8080/api/player/v1/test'
Output: This is a test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you can see the test message, it means that now our Spring-boot application is running and listening to the port 8080, now let's try to make some API call and confirm that our application is talking properly to our database.&lt;br&gt;
let's run those two API calls to add two players :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl  -i --location --request POST 'localhost:8080/api/player/v1/add' \
 --header 'Content-Type: application/json' \
 --data-raw '{
         "firstName": "Roberto",
         "lastName": "Boutabout",
         "team":"Real Madrid",
         "position":"CF"
     }'
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Wed, 09 Feb 2022 19:18:58 GMT

{"id":1,"firstName":"Roberto","lastname":"Boutabout","team":"Real Madrid","position":"CF"}


$ curl -i --location --request POST 'localhost:8080/api/player/v1/add' \
 --header 'Content-Type: application/json' \
 --data-raw '{
         "firstName": "Mahmoud",
         "lastName": "Donadoni",
         "team":"FC Barcelona",
         "position":"LW"
     }'
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Wed, 09 Feb 2022 19:19:48 GMT

{"id":2,"firstName":"Mahmoud","lastname":"Donadoni","team":"FC Barcelona","position":"LW"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see above that the two players have been added with a unique Id.&lt;br&gt;
Now, let's try to get the list of our players :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl -i --location --request GET 'localhost:8080/api/player/v1/list'
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Wed, 09 Feb 2022 19:21:45 GMT

[{"id":1,"firstName":"Roberto","lastname":"Boutabout","team":"Real Madrid","position":"CF"},{"id":2,"firstName":"Mahmoud","lastname":"Donadoni","team":"FC Barcelona","position":"LW"},]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fine, at this stage we already see that our deployment is more elegant and simpler, but what if our application have 20, 30 or maybe 100 containers, here an ORCHESTRATOR comes into the picture, and this is exactly what Kubernetes do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kuberenetes
&lt;/h2&gt;

&lt;p&gt;Kubernetes, also known as k8s, is an open-source container orchestration platform used for deploying, scaling, and managing containerized applications. It provides a way to automate the deployment, scaling, and management of containerized applications, allowing developers to focus on writing code without worrying about the underlying infrastructure. Kubernetes provides a platform for running and managing containers, with features like load balancing, automatic scaling, self-healing, and rolling updates, making it easier for developers to deploy and manage their applications. It is commonly used in cloud-native environments, allowing applications to be deployed and managed in a consistent way across multiple cloud providers and on-premises environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Environment
&lt;/h3&gt;

&lt;p&gt;For this tutorial we will use minikube. Minikube is an open-source tool that enables us to set up a single-node Kubernetes cluster on our local machine.&lt;br&gt;
The installation is pretty simple, all you have to do is to follow the steps from the official doc in this link : &lt;a href="https://minikube.sigs.k8s.io/docs/start/"&gt;https://minikube.sigs.k8s.io/docs/start/&lt;/a&gt;&lt;br&gt;
Once the installation is done, run &lt;code&gt;minikube start&lt;/code&gt; and here you go, now you have a local Kubernetes cluster on your machine.&lt;/p&gt;
&lt;h3&gt;
  
  
  Workload
&lt;/h3&gt;

&lt;p&gt;As defined in the official Kubernetes documentation (&lt;a href="https://kubernetes.io/docs/home/"&gt;https://kubernetes.io/docs/home/&lt;/a&gt;), a workload is an application running on Kubernetes. Whether your workload is a single component or several components that work together, in Kubernetes, you run it inside a set of pods. In Kubernetes, a Pod represents a set of running containers on your cluster.&lt;/p&gt;

&lt;p&gt;In our case, we will create manifests for the following Kubernetes objects: two Deployments and two Services. The Deployments will roll out ReplicaSets, which in turn will create Pods containing the Application and Database containers. One Service will expose the database port, allowing the application to communicate with it. The second Service will expose the application endpoints we will call. &lt;/p&gt;
&lt;h3&gt;
  
  
  Manifests
&lt;/h3&gt;

&lt;p&gt;One of the core principles of Kubernetes is the concept of desired state, where you define the state you want your application to be in, and Kubernetes takes care of the rest.&lt;/p&gt;

&lt;p&gt;In Kubernetes, the desired state is defined using a declarative approach, where you specify the desired configuration of your application in a YAML or JSON file called a manifest. This manifest includes information about the application's containers, networking, volumes, and other resources required to run the application.&lt;/p&gt;

&lt;p&gt;When you deploys the manifest to Kubernetes, Kubernetes compares the desired state to the actual state of the cluster and takes the necessary steps to reconcile any differences. This process is known as the reconciliation loop and is the key to Kubernetes' ability to maintain the desired state of an application.&lt;/p&gt;

&lt;p&gt;The reconciliation loop consists of four steps. The first step is to observe the current state of the cluster and compare it to the desired state specified in the manifest. In the second step, Kubernetes determines what actions need to be taken to bring the actual state in line with the desired state. These actions may include creating new resources, updating existing resources, or deleting resources that are no longer needed.&lt;/p&gt;

&lt;p&gt;Once Kubernetes has determined the necessary actions, it takes the third step of executing those actions to make the required changes to the cluster. Finally, Kubernetes waits for the changes to take effect and repeats the process to ensure that the actual state of the cluster matches the desired state.&lt;/p&gt;

&lt;p&gt;In summary, Kubernetes takes the desired state defined in a manifest file and uses a reconciliation loop to compare it to the actual state of the cluster. It then takes the necessary steps to bring the actual state in line with the desired state and repeats the process to ensure that the application remains in the desired state.&lt;/p&gt;

&lt;p&gt;Four our solution and for a sake of simplicity we are going to create two manifest files, &lt;strong&gt;application.yaml&lt;/strong&gt; for the application's Deployment and Service objects. And &lt;strong&gt;database.yaml&lt;/strong&gt; for the Database's Deployment and Service objects.&lt;/p&gt;
&lt;h3&gt;
  
  
  Application.yaml manifest
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: players
  name: players
spec:
  replicas: 1
  selector:
    matchLabels:
      app: players
  strategy: {}
  template:
    metadata:
      labels:
        app: players
    spec:
      containers:
      - image: malikoo/players:2.0
        name: players
        resources: {}
        env:
        - name: POSTGRES_URL
          value: playersdb:5432/testdb
      initContainers:
      - name: init-postgres
        image: postgres:9.6.5
        command: ['sh', '-c', 'until pg_isready -h playersdb -p 5432; do echo waiting for database; sleep 2; done;'] 

apiVersion: v1
kind: Service
metadata:
  labels:
    app: players
  name: players
spec:
  ports:
  - name: 8080-8080
    port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app: players
  type: ClusterIP
status:
  loadBalancer: {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This manifest defines a Deployment in Kubernetes that creates a single replica of a container based on the Docker image malikoo/players:2.0. The container is named "players".&lt;/p&gt;

&lt;p&gt;this manifest creates also a Service that exposes the players pods on port 8080 within the cluster.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that we have an init container; this section is used to specify any containers that should run before the main container starts. Our goal here is to wait until the database is up and running before running our Spring Boot application.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Database.yaml manifest
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: playersdb
  name: playersdb
spec:
  replicas: 1
  selector:
    matchLabels:
      app: playersdb
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: playersdb
    spec:
      containers:
      - image: postgres
        name: postgres
        resources: {}
        env:
        - name: POSTGRES_PASSWORD
          value: postgres
        - name: POSTGRES_DB
          value: testdb 
status: {}
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: playersdb
  name: playersdb
spec:
  ports:
  - name: 5432-5432
    port: 5432
    protocol: TCP
    targetPort: 5432
  selector:
    app: playersdb
  type: ClusterIP
status:
  loadBalancer: {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;this manifest creates a Postgres database deployment and a Service that exposes the database within the Kubernetes cluster on the port 5432.&lt;/p&gt;
&lt;h3&gt;
  
  
  Kubectl Apply
&lt;/h3&gt;

&lt;p&gt;Minikube comes with a built-in kubectl installation. Kubectl is a command-line interface (CLI) tool used to interact with Kubernetes clusters. It allows us to deploy, inspect, and manage applications running on Kubernetes, as well as access and manage cluster resources such as nodes, pods, services, and configurations. &lt;/p&gt;

&lt;p&gt;To deploy our solution all we have to do is run those two commands :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f application.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f database.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can use kubectl to see the newly created k8s objects :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;kubectl get deployment
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
players     1/1     1            1           11d
playersdb   1/1     1            1           11d

&amp;gt;Kubectl get pods
NAME                         READY   STATUS    RESTARTS   AGE
players-69cc7f875d-4rnph     1/1     Running   0          12m
playersdb-668967cfb5-859hn   1/1     Running   2          11d

&amp;gt;kubectl get services
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    
kubernetes   ClusterIP   10.96.0.1       &amp;lt;none&amp;gt;        443/TCP    
players      ClusterIP   10.99.208.51    &amp;lt;none&amp;gt;        8080/TCP   
playersdb    ClusterIP   10.100.152.81   &amp;lt;none&amp;gt;        5432/TCP 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great, now our application is up and running, we can test it to confirm that it's working properly.&lt;br&gt;
Before to do test we need to make a port forwarding to be able to access the application, to do this run this command :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;gt;kubectl port-forward service/players 8080:8080
 Forwarding from 0.0.0.0:8080 -&amp;gt; 8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's do our test :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;curl -i  --request GET 'localhost:8080/api/player/v1/test'
HTTP/1.1 200 
Content-Type: text/plain;charset=UTF-8
Content-Length: 14
Date: Sun, 09 Apr 2023 11:51:42 GMT

This is a test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congratulations! You have successfully deployed your application on Kubernetes. You can now access your application using the service endpoint the same way we did previously in this tutorial after using docker compose.&lt;/p&gt;

&lt;p&gt;So, to wrap up, we can summarize the different steps to go from an application to Kubernetes as follows : &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc526y60tm66hgekxc5kw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc526y60tm66hgekxc5kw.png" alt="Image description" width="800" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for following this tutorial, and I hope it was helpful. If you have any questions or feedback, please don't hesitate to reach out.&lt;/p&gt;

</description>
      <category>java</category>
      <category>docker</category>
      <category>kubernetes</category>
      <category>learning</category>
    </item>
    <item>
      <title>When Java meet Docker... Part I</title>
      <dc:creator>Malek Ramdani</dc:creator>
      <pubDate>Tue, 18 Jan 2022 23:21:16 +0000</pubDate>
      <link>https://dev.to/malek_ramdani/when-java-meet-docker-part-i-2iip</link>
      <guid>https://dev.to/malek_ramdani/when-java-meet-docker-part-i-2iip</guid>
      <description>&lt;p&gt;In this post, we are going to learn the very basics of how to run a java application inside a Docker container, we will start with a few definitions, and then we will build a small silly Java application which will, at the end of the post, run in a container.&lt;/p&gt;

&lt;p&gt;This, will be a first post of a series about Java and Docker, our application will evolve along the series, until we reach the cloud ☁️ !! So let's start the journey ✈️ &lt;/p&gt;

&lt;h2&gt;
  
  
  Cloud-Native
&lt;/h2&gt;

&lt;p&gt;Before we start talking about Docker and Java, let's have a few words about Cloud-Native, a term we hear often in the IT world nowadays. So what cloud-native means ? &lt;br&gt;
Here is how CNCF (Cloud Native Computing Foundation) defines it : &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Cloud native technologies empower organizations to build and run scalable applications in modern, dynamic environments such as public, private, and hybrid clouds. Containers, service meshes, microservices, immutable infrastructure, and declarative APIs exemplify this approach.&lt;/p&gt;

&lt;p&gt;These techniques enable loosely coupled systems that are resilient, manageable, and observable. Combined with robust automation, they allow engineers to make high-impact changes frequently and predictably with minimal toil.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In other words, Cloud-Native is a set of principles and technologies we should follow and use to build highly available, scalable, reliable and resilient software, and all of this with speed and agility.&lt;/p&gt;

&lt;p&gt;But, isn't cloud, cloud-native ? Well, we need to differentiate between the two, as explained by Cornelia Davis in her book &lt;a href="https://www.manning.com/books/cloud-native-patterns"&gt;Cloud Native Patterns&lt;/a&gt;, when talking about differentiating the cloud-native from the cloud :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;the latter is about where, whereas the former is about how and is the really interesting part).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Docker
&lt;/h2&gt;

&lt;p&gt;But what docker have to do with all of this ? Wait, we are almost there 😊, one of the pillar of cloud-native is the containerization, and the most popular software to manage containers and ship applications into it is &lt;strong&gt;Docker&lt;/strong&gt; !!&lt;/p&gt;

&lt;p&gt;If the concept of containerization is a decade old in Linux systems (cgroups and kernel namespaces), the emergence of Docker accelerated the use of this technology. A glimpse of docker underlying technology can be found in the official documentation : &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Docker is written in the Go programming language and takes advantage of several features of the Linux kernel to deliver its functionality. Docker uses a technology called namespaces to provide the isolated workspace called the container. When you run a container, Docker creates a set of namespaces for that container. &lt;/p&gt;

&lt;p&gt;These namespaces provide a layer of isolation. Each aspect of a container runs in a separate namespace and its access is limited to that namespace.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  What are we going to build
&lt;/h2&gt;

&lt;p&gt;Now that we have the context, we can start working on our Java application and run it in a container later on.&lt;/p&gt;

&lt;p&gt;First, we are going to code a very simple application that query a MySQL database and get a list of football (Soccer in North America ) players. Then we will create a jar file from this application and write a dockerfile to create a Docker image and then run container where our application will be executed.&lt;/p&gt;

&lt;p&gt;We will also deploy MySQL database in a Docker container, run everything and see the magic.&lt;/p&gt;

&lt;p&gt;At the end, our application should looks to something like this :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9jlh420ffp8vhmlsptbj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9jlh420ffp8vhmlsptbj.png" alt="Image description" width="800" height="296"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  MySQL Database with Docker
&lt;/h2&gt;

&lt;p&gt;First, let's start with the database, we are going to run a MySQL container with our user and password, and then go inside the container to create our schema, table and some dummy data.&lt;br&gt;
Our schema will have only on table "players" :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4lffzzwbzxwq3gbggb9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4lffzzwbzxwq3gbggb9.png" alt="Image description" width="800" height="900"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before we run the database container, we need to create a network on which our containers will be running, in fact when containers are created by Docker they are isolated and do not communicate with each other, this why we need to specify that the containers are on the same network in order to enable communication between them.&lt;br&gt;
When we create a new network, Docker by default will create it as a bridge netwrok, to do this let's run this command :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;docker network create mynet&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;the output of this command should be a long alhphanumeric string (f9bc75b98986ac....)&lt;br&gt;
You can type &lt;code&gt;docker network ls&lt;/code&gt; and you will see your network newly created, you should see something like this :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F96kinswwy1vlbfrcs2d9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F96kinswwy1vlbfrcs2d9.png" alt="Image description" width="441" height="108"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have our network, let's run our MySQL container. For this, we are going to use the official MySQL Docker image, and execute this command :&lt;br&gt;
&lt;code&gt;docker run --name playersdb --network mynet -e MYSQL_ROOT_PASSWORD=1234 -d mysql:latest&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The command above will run a container from mysql image &lt;code&gt;docker run&lt;/code&gt; with the latest version &lt;code&gt;mysql:latest&lt;/code&gt;, the name of the container will be playersdb &lt;code&gt;--name playersdb&lt;/code&gt;, the container will run on a network mynet &lt;code&gt;--network mynet&lt;/code&gt;, the root password will be '1234' &lt;code&gt;-e MYSQL_ROOT_PASSWORD=1234&lt;/code&gt; (-e is used to determine the environment variables of the container) and the container will run in a detached mode (in the background) &lt;code&gt;-d&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let's check our container now, using &lt;code&gt;docker ps&lt;/code&gt; :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfja4hyqzh6ii3fzidad.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfja4hyqzh6ii3fzidad.png" alt="Image description" width="800" height="29"&gt;&lt;/a&gt;&lt;br&gt;
Cool, our database container is now up and running, what we need to do now is to connect to our instance and create the schema we will use in our application.&lt;br&gt;
we could have used the port mapping by adding the option &lt;code&gt;-p 3306:3306&lt;/code&gt; in the Docker command above and would have used mysql workbench to manage the database. Instead we will use docker, specifically the "docker exec" command to open a mysql cli session into the container. To do this we need to run this command :&lt;br&gt;
&lt;code&gt;docker exec -it playersdb mysql -uroot -p1234&lt;/code&gt;&lt;br&gt;
here we should find ourselves in the mysql cli, now we can copy past the sql code below, it will create a schema &lt;strong&gt;playersdb&lt;/strong&gt;, a user &lt;strong&gt;juser*, our table **players&lt;/strong&gt; as described above and finally insert some data into our db :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE DATABASE `playersdb` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;
CREATE USER 'juser'@'%' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON * . * TO 'juser'@'%';
FLUSH PRIVILEGES;

USE playersdb;

CREATE TABLE `players` (
  `id` int DEFAULT NULL,
  `lastname` varchar(255) DEFAULT NULL,
  `firstname` varchar(255) DEFAULT NULL,
  `team` varchar(255) DEFAULT NULL,
  `position` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

INSERT INTO `playersdb`.`players`
(`id`,
`lastname`,
`firstname`,
`team`,
`position`)
VALUES
(1,
'Ryad',
'Boudebouz',
'Algeria',
'RW'),
(2,
'Manuel',
'Ruicosta',
'Portugal',
'CM'),
(3,
'Fernando',
'Redondo',
'Argentina',
'DM'),
(4,
'Ricardo',
'Kaka',
'Brazil',
'CM'),
(5,
'Ronaldo',
'TheOnlyRonaldo',
'Brazil',
'CF'),
(6,
'Paolo',
'Maldini',
'Italy',
'CB');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to check if the sql script executed without issue, you can run a select query &lt;code&gt;select * from playersdb.players&lt;/code&gt;, the result below should be displayed :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh0a6o7j6deblthhtpvte.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh0a6o7j6deblthhtpvte.png" alt="Image description" width="566" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Our Java application
&lt;/h2&gt;

&lt;p&gt;Now that our database, schema and data are all set, we can jump to our Java application.&lt;br&gt;
This will be a basic application that will connect to the database using JDBC, and run a select query on players table and display the result.&lt;/p&gt;

&lt;p&gt;Let's start by creating simple project using Maven :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mvn archetype:generate -DgroupId=com.players.app -DartifactId=players-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will create a simple Java project with an App.java class. The first thing we need to do is to modify our pom.xml by adding the jdbc driver for MySQL database as a dependency and the build plugins to generate a Jar file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;mysql&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;mysql-connector-java&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;8.0.22&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;build&amp;gt;
  &amp;lt;plugins&amp;gt;
    &amp;lt;plugin&amp;gt;
      &amp;lt;artifactId&amp;gt;maven-assembly-plugin&amp;lt;/artifactId&amp;gt;
        &amp;lt;configuration&amp;gt;
      &amp;lt;archive&amp;gt;
        &amp;lt;manifest&amp;gt;
          &amp;lt;mainClass&amp;gt;com.players.app.App&amp;lt;/mainClass&amp;gt;
        &amp;lt;/manifest&amp;gt;
          &amp;lt;/archive&amp;gt;
          &amp;lt;descriptorRefs&amp;gt;
            &amp;lt;descriptorRef&amp;gt;jar-with dependencies&amp;lt;/descriptorRef&amp;gt;
          &amp;lt;/descriptorRefs&amp;gt;
    &amp;lt;/configuration&amp;gt;
    &amp;lt;/plugin&amp;gt;
    &amp;lt;plugin&amp;gt;
    &amp;lt;!-- Build an executable JAR --&amp;gt;
      &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;maven-jar-plugin&amp;lt;/artifactId&amp;gt;
      &amp;lt;version&amp;gt;3.1.0&amp;lt;/version&amp;gt;
        &amp;lt;configuration&amp;gt;
          &amp;lt;archive&amp;gt;
            &amp;lt;manifest&amp;gt;                   
                  &amp;lt;addClasspath&amp;gt;true&amp;lt;/addClasspath&amp;gt;              
                    &amp;lt;classpathPrefix&amp;gt;lib/&amp;lt;/classpathPrefix&amp;gt;                          
                      &amp;lt;mainClass&amp;gt;com.players.app.App
                        &amp;lt;/mainClass&amp;gt;
        &amp;lt;/manifest&amp;gt;
          &amp;lt;/archive&amp;gt;
        &amp;lt;/configuration&amp;gt;
      &amp;lt;/plugin&amp;gt;
    &amp;lt;/plugins&amp;gt;
&amp;lt;/build&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can write some Java code, our application is a silly application which will connect to the playersdb database (we ran on a container previously), execute an sql query and display the result,&lt;br&gt;
This is the code of our Java class, you will find the github url at the end of this post.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class App {
    // in the dbhost the first playersdb is the container name and the second one is the database name
    private static String connString = "jdbc:mysql://playersdb:3306/playersdb";
    private static String username = "juser";
    private static String password = "password";
    private static Connection conn;
    private static String sql_req = "select * from players";
    private static Statement stmt;
    private static ResultSet results;

    public static void main(String[] args) {

        try {
            conn = DriverManager.getConnection(dbhost, username, password);
            System.out.println("Connecting...");
            System.out.println("Connected !!");

            stmt = conn.createStatement();
            results = stmt.executeQuery(sql_req);

            while (results.next()) {
                System.out.println("Id = " + results.getInt("id") + "\n" + "FirstName = "
                        + results.getString("firstname") + "\n" + "LastName = " + results.getString("lastname") + "\n"
                        + "Team = " + results.getString("team") + "Position = " + results.getString("position"));

            }
        } catch (SQLException e) {
            System.out.println("Cannot connect to database connection");
            e.printStackTrace();
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Tip : we can test our java application locally, to do this all we need to do is run the mysql container with a port mapping option -p 3306:3306, and replace the host name in connection string by localhost or 127.0.0.1, which will give us &lt;strong&gt;jdbc:mysql://localhost:3306/playersdb&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once this is done, we can run maven to generate the Jar file, to do this you can run maven from your IDE (Eclipse, IntelliJ, VScode...) or you can simply open your terminal (CMD in windows, terminal in linux...) go to the project folder and run :&lt;br&gt;
&lt;code&gt;mvn assembly:single&lt;/code&gt;&lt;br&gt;
This will build the project and will create a Jar file in the target folder. This is what you should see after the build finish:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiquny7lwxemq711rj0t9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiquny7lwxemq711rj0t9.png" alt="Image description" width="800" height="285"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
You can see that a Jar file with the name &lt;strong&gt;players-app-1.0-jar-with-dependencies.jar&lt;/strong&gt; has been created.&lt;/p&gt;
&lt;h2&gt;
  
  
  Our java application containerization with Docker
&lt;/h2&gt;

&lt;p&gt;At this point, we have our MySQL container ready, we have our jar file as well, all we need now, is a container in which our jar will be executed. For this let's create a new folder, copy in it the Jar file we created above, for simplification let's rename it players.jar. In the same folder let create a file called dockerfile, this file will contains the instructions to create a Docker image with our specific needs, in this case, an image that contains our jar file which will be executed every time we run the container from this image.&lt;br&gt;
Let's open our dockerfile with a text editor and paste into it those instructions :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM openjdk:11

COPY /players.jar /players.jar

CMD ["java", "-jar", "/players.jar"]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So what those instructions means ? the FROM instruction set the base image, a valid Docker file must start with a FROM.&lt;br&gt;
Then COPY will copy our jar file into the image.&lt;br&gt;
And finally CMD, this instruction will provides defaults for an executing container, in our case, every time we run the container the command &lt;code&gt;java -jar players.jar&lt;/code&gt; will be executed, this command we usually use to execute a jar file.&lt;/p&gt;

&lt;p&gt;Once our dokcerfile created, we can create our image by executing this command :&lt;br&gt;
&lt;code&gt;docker build -t playersapp:1.0 .&lt;/code&gt; &lt;br&gt;
This command will build our image file from the dockerfile.&lt;/p&gt;

&lt;p&gt;Now we can see that our image &lt;strong&gt;playersapp&lt;/strong&gt; with the tag 1.0 is available, to check this we need to run &lt;code&gt;docker images&lt;/code&gt; :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnlca64en9dvzxind57dc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnlca64en9dvzxind57dc.png" alt="docker images" width="689" height="38"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are almost there !! Now, all will need to do is to run a container from our image &lt;strong&gt;playersapp:1.0&lt;/strong&gt;, this container need to be in the same network than our MySQL container, so let's run this command :&lt;br&gt;
&lt;code&gt;docker run --name playersapp --network mynet playersapp:1.0&lt;/code&gt;&lt;br&gt;
And now we can see the list of the players we created before in this post :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpukfqyikropnfafufrob.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpukfqyikropnfafufrob.png" alt="Image description" width="800" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We have reached the end of this tutorial, although the application is very simple, the objective here is have an idea about what cloud-native is, and a step-by-step to follow to run a java program from a container.&lt;/p&gt;

&lt;p&gt;In the next post, our application will evolve into a spring boot application, and we will use docker compose. So see you soon ✌️ &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;GitHub repo of the players app : &lt;a href="https://github.com/MalikooR/players-app"&gt;players-app&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you want to learn more a about cloud native :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This book : &lt;a href="https://www.manning.com/books/cloud-native-patterns"&gt;cloud-native-patterns&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/architecture/cloud-native/introduction"&gt;Microsoft docs Introduction to cloud-native&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To learn Docker, the official doc is very good : &lt;a href="https://docs.docker.com/"&gt;docker docs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
      <category>docker</category>
      <category>cloudnative</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
