Home > Mobile >  React works from docker image on localmachine but unreachable from kubernetes. service looks to be c
React works from docker image on localmachine but unreachable from kubernetes. service looks to be c

Time:10-23

I want to put my docker image running react into kubernetes and be able to hit the main page. I am able to get the main page just running docker run --rm -p 3000:3000 reactdemo locally. When I try to deploy to my kubernetes (running locally via docker-desktop) I get no response until eventually a timeout.

I tried this same process below with a springboot docker image and I am able to get a simple json response in my browser.

Below is my Dockerfile, deployment yaml (with service inside it), and commands Im running to try and get my results. Morale is low, any help would be appreciated!

Dockerfile:

# pull official base image
FROM node

# set working directory
RUN mkdir /app
WORKDIR /app
# install app dependencies
COPY package.json /app
RUN npm install
# add app
COPY . /app

#Command to build ReactJS application for deploy might not need this...
RUN npm run build

# start app
CMD ["npm", "start"]

Deployment file:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: demo  
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
      - name: reactdemo
        image: reactdemo:latest
        imagePullPolicy: Never
        ports:
          - containerPort: 80             
---
apiVersion: v1
kind: Service
metadata:
  name: demo
spec:
  type: NodePort
  selector:
    app: demo
  ports:
    - port: 3000
      targetPort: 3000
      protocol: TCP
      nodePort: 31000
  selector:
    app: demo

I then open a port on my local machine to the nodeport for the service:

PS C:\WINDOWS\system32> kubectl port-forward pod/demo-854f4d78f6-qv4mt 31000:3000
Forwarding from 127.0.0.1:31000 -> 3000

My assumption is that everything is in place at this point and I should be able to open a browser to hit localhost:31000. I expected to see that spinning react symbol for their landing page just like I do when I only run a local docker container.

Here is it all running:

$ kubectl get all
NAME                        READY   STATUS    RESTARTS   AGE
pod/demo-854f4d78f6-7dn7c   1/1     Running   0          4s

NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
service/demo         NodePort    10.111.203.209   <none>        3000:31000/TCP   4s
service/kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP          9d

NAME                   READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/demo   1/1     1            1           4s

NAME                              DESIRED   CURRENT   READY   AGE
replicaset.apps/demo-854f4d78f6   1         1         1       4s

Some extra things to note:

  • Although I don't have it setup currently I did have my springboot service in the deployment file. I logged into it's pod and ensured the react container was reachable. It was.
  • I havent done anything with my firewall settings (but sort of assume I dont have to since the run with the springboot service worked?)
  • I see this in chrome developer tools and so far dont think it's related to my problem: crbug/1173575, non-JS module files deprecated. I see this response in the main broswer page after some time: localhost didn’t send any data. ERR_EMPTY_RESPONSE

CodePudding user response:

if you are using Kubernetes using minikube in your local system then it will not work with localhost:3000, because it runs in minikube cluster which has there owned private IP address, so instead of trying localhost:3000 you should try minikube service <servicename> this in your terminal and it shows the URL of your service.

CodePudding user response:

You don't need a Service to port-forward to a pod. You just port-forward straight to it

kubectl port-forward <pod-name> <local-port>:<pod-port>

This creates a "tunnel" between your local machine on a chosen port (<local-port>) and your pod (pod-name), on a chosen pod's port (<pod-port>).
Then you can curl your pod with

curl localhost:<local-port>

If you really want to use a Service, then port-forward to the Service (service/demo in your case) service port, but it will be translated to POD's IP eventually.

  1. Change .spec.port.[0].targetPort in your Service to be the same as .spec.template.spec.containers.port.containerPort in your deployment, so in your case:
...
    - port: 3000
      targetPort: 80
...
  1. Port forward to a Service, with Service port
kubectl port-forward service/demo 8080:3000

Then curl your Service with

curl localhost:8080

This have a side effect if there are more pods under the same service. Port forward almost always will be connected to the same pod.

CodePudding user response:

Thanks for all the feedback peeps! In trying out the solutions presented I found my error and it was pretty silly. I tried removing the service and trying the different port configs mentioned above. What solved it was using 127.0.0.1:31000 instead of localhost. Not sure why that fixed it but it did!

That being said a few comments I found while looking at the above comments.

  1. I found that I couldnt hit the cluster without doing the port forwarding regardless of whether I had a service defined or not.
  2. ContainerPort to my understanding is for kubernetes to work on pod to pod communication and doesnt impact application function from a user perspective (could be wrong!)
  3. good to know on minikube Im thinking about trying it out and if I do I'll know why port 3000 stops working.

Thanks

  • Related