Deploying with Java (Spring Boot)
Overview
There are three steps to deploy your application:
- Containerize your application by creating a
Dockerfile
- Modify
devfile.yaml
to add your Kubernetes code - Run
odo deploy
Prerequisites
Prerequisites:
Before we begin, you must login to a container registry that we will be pushing our application to.
Login to your container registry with either podman
or docker
:
podman login
Or
docker login
In order for odo deploy
to push your image, your container registry needs to be accessible.
NOTE for MacOS: If you are running Apple Silicon (M1/M2), you must set your Docker build platform to the cluster you are deploying to.
For example, if you are deploying to linux/amd64
:
export DOCKER_DEFAULT_PLATFORM=linux/amd64
Step 1. Create the initial development application
Complete the Developing with Java (Spring Boot) guide before continuing.
Step 2. Containerize the application
In order to deploy our application, we must containerize it in order to build and push to a registry. Create the following Dockerfile
in the same directory:
FROM registry.access.redhat.com/ubi8/openjdk-11 as builder
USER jboss
WORKDIR /tmp/src
COPY --chown=jboss . /tmp/src
RUN mvn package
FROM registry.access.redhat.com/ubi8/openjdk-11
COPY --from=builder /tmp/src/target/*.jar /deployments/app.jar
Step 3. Modify the Devfile
Let's modify the devfile.yaml
and add the respective deployment code.
caution
When copy/pasting to devfile.yaml
, make sure the lines you inserted are correctly indented.
odo deploy
uses Devfile schema 2.2.0. Change the schema to reflect the change:
# Deploy "kind" ID's use schema 2.2.0+
schemaVersion: 2.2.0
Add the variables
and change them appropriately:
# Add the following variables code anywhere in devfile.yaml
# This MUST be a container registry you are able to access
variables:
CONTAINER_IMAGE: quay.io/MYUSERNAME/java-odo-example
RESOURCE_NAME: my-java-app
CONTAINER_PORT: "8080"
DOMAIN_NAME: java.example.com
Add the commands used to deploy:
# This is the main "composite" command that will run all below commands
commands:
- id: deploy
composite:
commands:
- build-image
- k8s-deployment
- k8s-service
- k8s-url
group:
isDefault: true
kind: deploy
# Below are the commands and their respective components that they are "linked" to deploy
- id: build-image
apply:
component: outerloop-build
- id: k8s-deployment
apply:
component: outerloop-deployment
- id: k8s-service
apply:
component: outerloop-service
- id: k8s-url
apply:
component: outerloop-url
Add the Docker image location as well as Kubernetes Deployment and Service resources to components
:
components:
# This will build the container image before deployment
- name: outerloop-build
image:
dockerfile:
buildContext: ${PROJECT_SOURCE}
rootRequired: false
uri: ./Dockerfile
imageName: "{{CONTAINER_IMAGE}}"
# This will create a Deployment in order to run your container image across
# the cluster.
- name: outerloop-deployment
kubernetes:
inlined: |
kind: Deployment
apiVersion: apps/v1
metadata:
name: {{RESOURCE_NAME}}
spec:
replicas: 1
selector:
matchLabels:
app: {{RESOURCE_NAME}}
template:
metadata:
labels:
app: {{RESOURCE_NAME}}
spec:
containers:
- name: {{RESOURCE_NAME}}
image: {{CONTAINER_IMAGE}}
ports:
- name: http
containerPort: {{CONTAINER_PORT}}
protocol: TCP
resources:
limits:
memory: "1024Mi"
cpu: "500m"
# This will create a Service so your Deployment is accessible.
# Depending on your cluster, you may modify this code so it's a
# NodePort, ClusterIP or a LoadBalancer service.
- name: outerloop-service
kubernetes:
inlined: |
apiVersion: v1
kind: Service
metadata:
name: {{RESOURCE_NAME}}
spec:
ports:
- name: "{{CONTAINER_PORT}}"
port: {{CONTAINER_PORT}}
protocol: TCP
targetPort: {{CONTAINER_PORT}}
selector:
app: {{RESOURCE_NAME}}
type: ClusterIP
To be able to access our application we need to add one more component
to the Devfile.
For OpenShift cluster we add Route. For Kubernetes cluster we add Ingress.
- Kubernetes
- OpenShift
- name: outerloop-url
kubernetes:
inlined: |
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{RESOURCE_NAME}}
spec:
rules:
- host: "{{DOMAIN_NAME}}"
http:
paths:
- path: "/"
pathType: Prefix
backend:
service:
name: {{RESOURCE_NAME}}
port:
number: {{CONTAINER_PORT}}
- name: outerloop-url
kubernetes:
inlined: |
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: {{RESOURCE_NAME}}
spec:
path: /
to:
kind: Service
name: {{RESOURCE_NAME}}
port:
targetPort: {{CONTAINER_PORT}}
Step 4. Run the odo deploy
command
Now we're ready to run odo deploy
:
odo deploy
$ odo deploy
__
/ \__ Deploying the application using java Devfile
\__/ \ Namespace: default / \__/ odo version: v3.0.0~beta3
\__/
↪ Building & Pushing Container: MYUSERNAME/java-odo-example
• Building image locally ...
✓ Building image locally [880ms]
• Pushing image to container registry ...
✓ Pushing image to container registry [5s]
↪ Deploying Kubernetes Component: java-example
✓ Searching resource in cluster
✓ Creating kind Deployment [48ms]
↪ Deploying Kubernetes Component: java-example
✓ Searching resource in cluster
✓ Creating kind Service [51ms]
↪ Deploying Kubernetes Component: java-example
✓ Searching resource in cluster
✓ Creating kind Ingress [49ms]
Your Devfile has been successfully deployed
Your application has now been deployed to the Kubernetes cluster with Deployment, Service, and Ingress resources.
Test your application by visiting the DOMAIN_NAME
variable that you had set in the devfile.yaml
.
Step 5. Delete the resources
After testing your application, you may optionally undeploy using the odo delete component
command:
odo delete component
$ odo delete component
Searching resources to delete, please wait...
This will delete "myapp" from the namespace "default".
• The component contains the following resources that will get deleted:
- Deployment: myapp
- Service: myapp
- Ingress: myapp
? Are you sure you want to delete "myapp" and all its resources? Yes
The component "myapp" is successfully deleted from namespace "default"
• There are still resources left in the cluster that might be belonging to the deleted component.
- Endpoints: svc
- Service: svc
If you want to delete those, execute `odo delete component --name myapp --namespace default`