Your Docker Compose file is probably exposing services that should stay internal

Your Docker Compose file is probably exposing services that should stay internal

Published Sep 9, 2026, 4:00 PM EDT Beginning his professional journey in the tech industry in 2018, Yash spent over three years as a Software Engineer. After that, he shifted his focus to empowering readers through informative and engaging content on his tech blog – DiGiTAL BiRYANi. He has also published tech articles for MakeTechEasier. He loves to explore new tech gadgets and platforms. When he is not writing, you’ll find him exploring food. He is known as Digital Chef Yash among his readers because of his love for Technology and Food. I’ve been using Docker long enough to know my way around Compose files, containers, and the usual networking settings. But for years, I treated port configuration as one of those things that simply worked if the syntax was right. That changed when I started dealing with more complex setups and had to troubleshoot why services behaved differently depending on where a connection came from. I realized I had been looking at Docker networking too narrowly. The commands weren't the hard part. The missing piece was understanding what Docker was doing between the application, container, host, and network. That shift completely changed how I configure containers. I thought Docker Port Mapping was just a number game The left and right matter For a long time, I treated Docker port mapping like a simple number-matching exercise. If my application used port 3000, I would usually write something like 3000:3000 in my Compose file and move on. If I wanted to use another port on my machine, I changed the first number and assumed I had changed the application's port too. That assumption caused more confusion than I realized. I eventually understood that the two numbers in a mapping have completely different jobs. The number on the left is the port on my host, while the number on the right is the port where the application is listening inside the container. So 8080:3000 doesn't tell my application to move from 3000 to 8080. It simply gives me a way to reach the application through port 8080 on the host while the application continues using port 3000 inside the container. Once I understood that distinction, Docker port mappings stopped looking like arbitrary syntax and started making sense. I was publishing ports that never needed to be public Not every container needs a doorway I used to publish ports for almost every container because it made accessing services feel easier. If I could see a port in the container's documentation, I often added it to my Compose file without thinking much about who actually needed it. That habit became a problem when I started running multiple services together. My database, cache, and internal API didn't always need to be accessed directly from my computer. They mainly needed to talk to other containers in the same application stack. Docker's internal networking already handles that communication. Containers can reach each other over the Docker network without every service needing a port published on the host. I was adding host mappings for connections that never needed to leave the container network. The distinction became much clearer once I started thinking about where the traffic was going. Container-to-container communication is different from accessing a container from the host, which is different again from allowing external devices to reach it. Publishing fewer ports also meant fewer services were unnecessarily exposed on my host. My Compose files became simpler, and I had fewer things to worry about. EXPOSE and localhost sometimes cause confusion Two small concepts caused big confusion EXPOSE and localhost are two Docker concepts that can easily create confusion, even when the rest of the networking setup is clear. The EXPOSE instruction in a Dockerfile indicates which port a containerized application is expected to listen on. It doesn't publish that port on the host or automatically make the service reachable from outside the container. Localhost is equally important because its meaning depends on where the connection originates. Inside a container, localhost refers to that same container. It doesn't refer to the Docker host or another container running alongside it. This distinction matters when applications communicate across containers. A service may be running correctly, while a connection still fails because the address points to the wrong network namespace. Understanding these two concepts helps separate application configuration from Docker networking and makes connection issues much easier to troubleshoot. Now I ask one question before publishing any Docker port Before mapping, I think about access Before publishing a Docker port now, I ask myself one simple question: who actually needs to access this service? That question changes how I configure a Compose stack. If a service is only part of the application's internal plumbing, I don't automatically give it a host-facing port. If I need to access it during development, I consider whether that access is temporary or something the setup genuinely requires. I also consider each service's role before adding another mapping. A web application may need direct access, while a database, cache, or internal worker may not. Keeping those decisions intentional prevents my Compose files from filling up with ports that exist simply because they were convenient at the time. This approach has made my Docker configurations easier to maintain. Instead of publishing ports by habit, I now treat every mapping as a deliberate networking decision with a specific reason behind it. The biggest lesson wasn't about ports Docker made me realize that configuration and networking are more connected than they first appear. A setup can work perfectly while still hiding assumptions that become painful later. Once I started paying attention to how services communicate, many of those confusing moments became easier to reason about. The biggest improvement wasn't learning another Docker command. It was developing a better mental model of what was happening underneath the containers. That understanding has stayed useful far beyond port mappings.

Original Source

Read the full article at Xda-developers →

KhanList aggregates and links to publicly available news content. We do not host full articles from third-party sources. Always verify important information with original sources.