Home > OS >  Relationship between Dockerfile EXPOSE and Kubernetes service/container ports?
Relationship between Dockerfile EXPOSE and Kubernetes service/container ports?

Time:10-16

I was under the impression in Kubernetes the way you expose a port for your application was by first exposing it in the Dockerfile using EXPOSE, then setting the containerPort setting in the deployment yaml file, and finally setting the targetPort in the service yaml file. I thought these all had to be the same value e.g. 7214.

However I've just noticed that I've had the incorrect port exposed in one my applications Dockerfile as 7124 (but have the correct port in the other two files) like so :

Dockerfile

expose 7124 #This is incorrect

Deployment.yaml

ports:
  - containerPort: 7214

Service.yaml

apiVersion: v1
kind: Service
metadata:
 name: my-service
spec:
 type: NodePort
 ports:
  - port: 7214
    targetPort: 7214

However my other applications are hitting the service fine and the requests are being forwarded onto the application at port 7214 without issue.

Why is this working? Is it not required for me to expose the port in the Dockerfile at all? Does containerPort take precedence or something? This users answer on a similar question says the exposed port doesn't have to match, but doesn't explain why.

CodePudding user response:

The port on which a process is listening is only known to the developer of the process as the port binding happens in code. EXPOSE and containerPort are ways to communicate this to outside world.

EXPOSE directive in the Dockerfile doesn't do anything other than acting as documentation for the person reading your dockerfile to understand which port the process in the container might be listening on and for some UI purpose when you run docker ps command. It's like a communication between the author of the dockerfile and another person who might be using your image or modifyng your dockerfile.

Even the containerPort section in your deployment.yaml has no affect on anything. It also acts as documentation for people reading your manifest to know on which ports your process within the pod might be listening on. Another use is that you can give a name to the port using the name field and then you can reference this port by name in other places like the service object.

The only thing that matters is the actual port that your process is listening on in the container and making sure that port is used in targetPort field in the service port.

CodePudding user response:

The EXPOSE option in a Dockerfile serves merely as a documentation, it is not exposing the port as stated by the official documentation:

The EXPOSE instruction does not actually publish the port. It functions as a type of documentation between the person who builds the image and the person who runs the container, about which ports are intended to be published.

In Kubernetes the equivalent to EXPOSE is spec.containers.ports.containerPort. You can set both values to whatever you want and it will not change anything at all. Think of it as a comment.

With a Service object it is a little bit different, there the values do matter. A Service takes spec.ports.port and spec.ports.targetPort. If you don't specify the targetPort then Kubernetes will set its value to the same as specified in port (which is required).

However, it is not necessary for targetPort and `port to be the same, in fact they do have different purposes:

  • port specifies the port of the Service
  • targetPort specifies the port of the Pod

So the general flow looks something like this:

call to <service-name>:port -> forwards to a Pod with label foo: bar -> Pod receives the call on targetPort

Here is an example:

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 12345

Resulting in:

curl my-service:80 -> forwards to a Pod with label app: MyApp -> Pod receives the request on 12345.

In your case you communicate with your Service on port 7214 and it forwards the request to the Pod also to port 7214, that's why it will continue to work no matter what you set for EXPOSE or containerPort.

  • Related