Docker - Managing Ports



By design, Docker containers are isolated, keeping internal ports to themselves and not allowing response to the external. This configuration of the ports on the Docker host can be done while creating a container using the -p or --publish Docker flag; then, it allows the port to be published. This mapping makes applications running within the containers accessible, as they receive traffic from outside sources. Multiple port mappings can be enabled for one container, which caters to scenarios where various services are running within the same container.

Additionally, Docker Compose abstracts the port-mapping complexity for multi-container applications. With a docker-compose.yml file defining all services and their port mappings, it becomes easier for Docker Compose to create and wire containers. This is done so that it automatically assigns unique ports in a way that does not cause conflicts, making communication between containers in an application stress-free.

The ability to escape from conflicts and make communication seamless enables it to control ports effectively, hence being a very resourceful tool for enhancing the workflow in development to deployment in complex applications. It is a precious tool for managing containerized environments.

In this chapter, let’s learn about managing Docker ports in detail.

EXPOSE vs. PUBLISH: Understanding the Differences

Both EXPOSE and PUBLISH (or -p) deal with ports in Docker, but they are two different things −

EXPOSE

EXPOSE acts as documentation regarding which ports a containerized application intends to use for communication. It is a directive in a Dockerfile that lets anyone building or running the container know what services it can potentially offer.

But remember that EXPOSE alone does not make those container ports accessible outside the container; the directive itself more or less acts like a note for the developers or system administrators.

PUBLISH

This is the actual port mapping. When you PUBLISH a port, that is, when you include the -p in the docker run or the ports section in the docker-compose.yml, you are making an association between some PORT in the Docker container and the PORT on the Docker host. And that is what enables external traffic to access an application running inside a container, i.e., where the "intention" that you EXPOSE is made real.

How to Expose a Port in Docker using PUBLISH?

Docker proposes several ways by which it can be done, but the most straightforward and widely known is by using the -p when running a container. Below is an example −

Basic Syntax

The basic syntax for exposing a port when running a Docker container is −

$ docker run -p <host_port>:<container_port> <image_name>
  • <host_port> − This indicates the port number on the Docker host where you want to expose the application.
  • <container_port> − The port number in the container on which your application listens for traffic.
  • <image_name> − The name of the Docker image you want to run.

Example: Public Web Server Port

For example, you have an application configured to run a web server on port 80 in the container. You can map this to a local machine port, 8080, by doing −

$ docker run -p 8080:80 <your_web_server_image>

Now, you can open http://localhost:8080 with your favorite web browser and see your application being served!

Publish Multiple Ports in Docker

If your application requires multiple ports to be open, you can just add the -p flag more than once.

$ docker run -p 8080:80 -p 4433:443 <your_app_image>

This exposes port 80 (for HTTP) and port 443 (for HTTPS) on your host machine to the service.

Publish Ports Using Docker Compose

It's pretty simple to maintain port mappings with Docker Compose for multi-container applications. You do this inside your docker-compose.yml file, under each service, in the ports section −

services:
   web:
      image: <your_web_server_image>
      ports:
      - "8080:80"
   db:
      image: <your_database_image>
      # ... other configurations

Key Considerations

  • Port Conflicts − Ensure that a host port selected by yourself is not already being used by any other application or service within your system.
  • Firewall − If Docker runs on a remote server, you may want to configure your firewall to enable traffic across the exposed ports.
  • Security − Docker vulnerabilities are easily exposed - your port will be exposed, and attackers can breach the container. Consider using reverse proxies or other security measures to protect your containers.

How to Expose a Port in Dockerfile?

While the `EXPOSE` instruction in a Dockerfile does not publish the port, it provides information about the port that the container is expected to listen on at runtime. In reality, though, it documents the ports that'll be used by your Docker image so that users know which ports they can consider publishing in the container. Here's how to define it in your Dockerfile −

The EXPOSE Instruction

The syntax is simple −

EXPOSE <port> [<port>/<protocol>]
  • `<port>` − Port that you wish to expose.
  • `<protocol>` − optional, with a default of TCP. May be TCP or UDP.

Example: Exposing a Web Server Port

In a Dockerfile for a web server image, you would have −

# ... other Dockerfile instructions
EXPOSE 80

This informs anyone looking at your image that very probably the inside application is listening to an incoming connection on port 80, the standard HTTP port.

Opening up multiple ports and protocols

You can have more than one `EXPOSE` in your Dockerfile −

EXPOSE 80
EXPOSE 443/tcp
EXPOSE 443/udp

This would mean your application uses TCP port 80 by default and TCP/UDP port 443.

Key Points to Note

`EXPOSE` is not necessary; however, it is good practice to document your container's network usage.

It doesn't publish ports to the host - doing that still requires the use of `-p` when running the container or defining ` ports` in your `docker-compose.yml` file.

When an image is built from your Dockerfile, an instruction from the `EXPOSE` automatically takes a note in the metadata of the picture, and you can expose that using `docker inspects <image_name>`.

Dockerfile and Running the Container

FROM nginx

EXPOSE 80

# ... any additional configuration you need

Run this container and the web server is now accessible on port 8080 of your host −

$ docker run -p 8080:80 <your_nginx_image>

Conclusion

Mastering port management in Docker is essential for any person dealing with applications running in containers. Understanding the differences between EXPOSE and PUBLISH and applying best practices for opening ports ensures all container communication is perfect with the world beyond.

Whether you are developing a simple application or managing multi-container environments at scale, Docker port management has the flexibility and controls to create effective reachable solutions.

As you continue your Docker journey, please always consider security best practices. Remember to keep port mappings updated, use secure communication protocols, and think more security layers - for example, reverse proxies. This then lets you take full advantage of the power of Docker, all while keeping applications and infrastructure safe through your focus on being proactive.

FAQ

Q 1. What's the difference between EXPOSE and -p(or PUBLISH) in docker?

They both deal with ports but in entirely different ways. EXPOSE is an instruction in a Dockerfile and acts more as a rule statement to describe ports that your application will leverage for communication.

Think of it as a nice note for someone building or running your container. -p or PUBLISH, on the other hand, is an actual runtime command to map a port on the Docker host to a port in the container to make your application accessible from the outside.

Q 2. Why can't I access my application even after exposing a port?

There could be a few culprits here. Make sure your host machine's firewall isn't blocking traffic over this exposed port. Ensure you didn't select a port already being used by some other application.

If you run Docker on some virtual machine or remote server, ensure once again that the network configuration is correct. Finally, make sure that the port mapping you have given (host port to container port) is correct and aligns with how your application has been configured.

Q 3. How do I expose multiple ports for a single container?

Docker manages it effortlessly. Do it simply by specifying -- multiple -p flags to your docker run command, each with a different port mapping. When using Docker Compose, multiple mappings must be made in the ports section of your docker-compose.yml file.

Each mapping will provide a separate pathway for the outside traffic toward different services or components running within your container.

Q 4. Is it safe to expose ports in Docker?

Every port exposed for accessing your applications creates an increasing attack surface for potential attackers. Adhere to all security best practices to curb the risks. Enable strong authentication, allow access only from trusted sources, and possibly add more security layers like reverse proxies or firewalls.

Monitor the systems and update the Docker images whenever routine updates are available to patch known vulnerabilities.

Q 5. What are some common errors to avoid while managing ports in Docker?

The most common mistake is security negligence in port exposure, exposing applications to attackers. The other is in using ports used by another service that has been previously launched; in such a case, conflicts will arise.

Be very careful with port mappings and ensure that the correct ports on the host and the correct ports inside the container are connected.

Finally, don't forget to document your port mappings, whether through EXPOSE in your Dockerfile or through your project documentation, so that you or others can reference it with ease in the future.

Advertisements