简体   繁体   中英

Cannot access exposed Dockerized React app on Kubernetes

I'm trying to deploy my Dockerized React app to Kubernetes. I believe I've dockerized it correctly, but i'm having trouble accessing the exposed pod.

I don't have experience in Docker or Kubernetes, so any help would be appreciated.

My React app is just static files (from npm run build) being served from Tomcat.

My Dockerfile is below. In summary, I put my app in the Tomcat folder and expose port 8080.

FROM private-docker-registry.com/repo/tomcat:latest

EXPOSE 8080:8080

# Copy build directory to Tomcat webapps directory
RUN mkdir -p /tomcat/webapps/app
COPY /build/sample-app /tomcat/webapps/app

# Create a symbolic link to ROOT -- this way app starts at root path 
(localhost:8080)

RUN ln -s /tomcat/webapps/app /tomcat/webapps/ROOT

# Start Tomcat
ENTRYPOINT ["catalina.sh", "run"]

I build and pushed the Docker image to the Private Docker Registry. I verified that container runs correctly by running it like this:

docker run -p 8080:8080 private-docker-registry.com/repo/sample-app:latest

Then, if I go to localhost:8080, I see the homepage of my React app.

Now, the trouble I'm having is deploying to Kubernetes and accessing the app externally.

Here's my deployment.yaml file:

kind: Deployment
apiVersion: apps/v1beta2
metadata:
  name: sample-app
  namespace: dev
  labels:
    app: sample-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
      - name: sample-app
        image: private-docker-registry.com/repo/sample-app:latest
        ports:
        - containerPort: 8080
          protocol: TCP
      nodeSelector:
        TNTRole: luxkube
---
kind: Service
apiVersion: v1
metadata:
  name: sample-app
  labels:
    app: sample-app
spec:
  selector:
    app: sample-app
  type: NodePort
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP

I created the deployment and service by running kubectl --namespace=dev create -f deployment.yaml

Output of 'describe deployment'

    Name:                   sample-app
    Namespace:              dev
    CreationTimestamp:      Sat, 21 Jul 2018 12:27:30 -0400
    Labels:                 app=sample-app
    Annotations:            deployment.kubernetes.io/revision=1
    Selector:               app=sample-app
    Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable
    StrategyType:           RollingUpdate
    MinReadySeconds:        0
    RollingUpdateStrategy:  25% max unavailable, 25% max surge
    Pod Template:
      Labels:  app=sample-app
      Containers:
       sample-app:
        Image:        private-docker-registry.com/repo/sample-app:latest
        Port:         8080/TCP
        Host Port:    0/TCP
        Environment:  <none>
        Mounts:       <none>
      Volumes:        <none>
    Conditions:
      Type           Status  Reason
      ----           ------  ------
      Available      True    MinimumReplicasAvailable
      Progressing    True    NewReplicaSetAvailable
    OldReplicaSets:  <none>
    NewReplicaSet:   sample-app-bb6f59b9 (1/1 replicas created)
    Events:          <none>

Output of 'describe service'

Name:                     sample-app
Namespace:                fab-dev
Labels:                   app=sample-app
Annotations:              <none>
Selector:                 app=sample-app
Type:                     NodePort
IP:                       10.96.29.199
Port:                     <unset>  80/TCP
TargetPort:               8080/TCP
NodePort:                 <unset>  34604/TCP
Endpoints:                192.168.138.145:8080
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

Now I don't know which IP and port I should be using to access the app. I have tried every combination but none has loaded my app. I believe the port should be 80, so if I just have the IP, i shuold be able to go to the browser and access the React app by going to http://.

Does anyone have suggestions?

The short version is that the Service is listening on the same TCP/IP port on every Node in your cluster ( 34604 ) as is shown in the output of describe service :

NodePort:                 <unset>  34604

If you wish to access the application through a "nice" URL, you'll want a load balancer that can translate the hostname into the in-cluster IP and port combination. That's what an Ingress controller is designed to do, but it isn't the only way -- changing the Service to be type: LoadBalancer will do that for you, if you're running in a cloud environment where Kubernetes knows how to programmatically create load balancers for you.

I believe you found the answer by now :), I landed here as I was facing this issue. Solved for self, hope this helps everyone.

Here's what can help:

  1. Deploy your app (say: react-app).
  2. Run below command: kubectl expose deployment <workload> --namespace=app-dev --name=react-app --type=NodePort --port=3000 output: service/notesui-app exposed

Publish the service port as 3000, Target Port 3000, Node Port (auto selected 32250)

kubectl get svc react-app --namespace=notesui-dev
NAME          TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
react-app   NodePort   10.23.22.55   <none>        3000:32250/TCP   48m

Yaml: (sample)

apiVersion: v1
kind: Service
  name: react-app
  namespace: app-dev
spec:
  selector: <workload>
  ports:
  - nodePort: 32250
    port: 3000
    protocol: TCP
    targetPort: 3000

  type: NodePort
status: {}

Access the app on browser:

http://<Host>:32250/index

is your node ip where pod is running. If you have app running in multiple nodes (scaled). It is a NodePort setting on every node. App can be accessed:

http://<Host1>:32250/index
http://<Host2>:32250/index

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM