DEV Community

Shani G
Shani G

Posted on

πŸš€ Secure Your Microservices: API Gateway + Docker Private Networks

πŸš€ A practical guide for developers building their first distributed system

When building microservices for the first time, most developers focus on features,
scaling, or breaking the monolith β€” but almost nobody talks about security architecture.

And that’s exactly where things can go wrong.

While developing my own distributed system, I discovered that several internal APIs β€”
and even the PostgreSQL database β€” were accidentally exposed to the public. 😬

So I implemented a simple, production-ready pattern:
API Gateway + Docker Private Networks.

This post will show you exactly how (and why) I did it, and how you can use the same approach in your own projects.

πŸ’₯ The Real Problem: Microservices Accidentally Exposing Everything

Here’s how many beginner systems accidentally look:

  • Each service is exposed on its own port
  • The client talks to everything directly
  • The database (!) may also be exposed
  • No central control or routing

This creates security issues, debugging complexity, and a messy architecture.

🧩 Part 1 β€” The API Gateway: Your Single Entry Point

Why the API Gateway is critical

How it works

  • The client sends a single request to the Gateway.
  • The Gateway decides which service should handle it.
  • It forwards the request inside the private Docker network.
  • Internal URLs are never exposed to the outside world.

A Gateway is not just a fancy router β€” it becomes the front door to your entire system.

Why it's so important:

  • One place for authentication
  • One place for routing
  • Internal services remain hidden
  • Cleaner code and better control

Instead of:

http://localhost:3000/orders
http://localhost:4000/reports

Your client only calls:

http://gateway/api/orders

The Gateway forwards the request internally.
Your services never need to be exposed again.

🧱 Part 2 β€” Docker Private Networks (The Physical Security Layer)

How Docker networks protect your system

Why this matters
Without a private network, Docker exposes containers to the host machine.
With it:

βœ” Only the Gateway is reachable
βœ” All internal traffic stays inside the network
βœ” Databases cannot be accessed directly

Putting services into a private Docker network prevents the outside world
from reaching anything except what you explicitly expose.

Most developers don't realize that Docker exposes containers publicly unless configured otherwise.

The solution?

Put all internal services in a private network.

This prevents the outside world from reaching anything except what you explicitly expose.

What this gives you:

  • Internal-only communication
  • Zero accidental port exposure
  • Database fully isolated
  • Clean, professional architecture

Even if someone bypasses the Gateway (rare),
they still can't access Service A, B, or the Database β€” because they're not on a public network.

πŸ›‘οΈ Combining the Two: A Simple, Solid Security Pattern

How the full architecture works together

When you combine:

βœ” Logical Security (API Gateway)
βœ” Physical Security (Private Network)

You get a microservices architecture that's both simple and robust β€” without Kubernetes, service mesh, or any heavy DevOps tooling.

The architecture becomes:

Client
   ↓
 API Gateway
   ↓
Private Docker Network
 β”œβ”€β”€ Service A
 β”œβ”€β”€ Service B
 └── Database
Enter fullscreen mode Exit fullscreen mode

Only the Gateway is public.
Everything else is safely tucked away behind it.

πŸ§ͺ Minimal Docker Compose Example (Copy/Paste Ready
Here’s the minimal setup I used β€” clean, simple, and production-friendly:

services:
  api-gateway:
    build: ./gateway
    ports:
      - "8080:8080"
    networks:
      - public_net
      - private_net

  service-a:
    build: ./service-a
    expose:
      - "3000"
    networks:
      - private_net

  service-b:
    build: ./service-b
    expose:
      - "4000"
    networks:
      - private_net

  internal-db:
    image: postgres:16
    expose:
      - "5432"
    environment:
      POSTGRES_PASSWORD: password
    networks:
      - private_net

networks:
  public_net:
  private_net:
Enter fullscreen mode Exit fullscreen mode

Key takeaways

  • Only the Gateway has ports β†’ public
  • Internal services use expose β†’ private
  • Everything sits inside private_net
  • Clean, secure architecture with minimal configuration

🎯 What I Learned

Implementing this pattern gave me:

βœ” Zero accidental exposure of internal services
βœ” A secure, predictable entry point
βœ” Faster debugging
βœ” Easier onboarding for teammates
βœ” A scalable foundation for future services
βœ” Professional-level architecture with beginner-friendly tools

✨ Final Thoughts

This architecture may look simple β€” and that’s exactly why it works.

You don’t need Kubernetes, a service mesh, or complex DevOps setups
to build a secure and scalable distributed system.

Start with:
βœ” One API Gateway

βœ” One private Docker network

This foundation will naturally support your system as it grows.
Simple. Clean. Secure. Effective.

Top comments (0)