What Is the Difference Between ports and expose in Docker Compose?

When working with Docker Compose, one of the most common points of confusion is the difference between ports and expose. Both deal with container networking, but they serve very different purposes.

In this blog, we’ll clarify how each works, when to use them, and the best practices for designing containerized applications.


Quick Definitions

  • ports: Maps a container’s internal port to the host machine, making the service accessible from outside Docker.
  • expose: Makes a container’s port available only to other services within the same Docker network, but not exposed to the host machine.

How ports Works

The ports directive creates a port mapping between the container and the host.

Example:

version: "3.8"

services:
  web:
    image: nginx
    ports:
      - "8080:80"
  • Port 80 inside the container is mapped to port 8080 on the host.
  • You can now access the Nginx server at:
    http://localhost:8080

This is how you expose your service to the outside world (developers, users, APIs, etc.).


How expose Works

The expose directive only makes ports available internally to other services defined in the same Docker Compose network. It does not publish them to the host machine.

Example:

version: "3.8"

services:
  app:
    image: my-app
    expose:
      - "5000"

  worker:
    image: my-worker
    depends_on:
      - app
  • The app service exposes port 5000.
  • The worker service can connect to app:5000 over the internal network.
  • But you cannot access http://localhost:5000 from the host.

This is useful for microservices or backend services that should only communicate internally.


Key Differences Between ports and expose

Featureportsexpose
AccessibilityHost machine + other containersOnly other containers (internal)
Syntax Example“8080:80”“5000”
Use CasePublic-facing services (e.g., web)Internal-only communication
SecurityLess restrictiveMore restrictive

When to Use Which

  • Use ports when:
    • The service must be accessed from your local machine or external clients.
    • Examples: Nginx web server, API gateway, PostgreSQL database (when you want to connect with local client).
  • Use expose when:
    • The service should only be accessed by other containers in the same network.
    • Examples: Internal APIs, background workers, private databases.

Best Practices

  • Minimize ports usage in production for security; only expose what’s needed.
  • Use expose for internal-only communication between microservices.
  • Remember that by default all services in the same Compose project share a network, so they can already talk to each other on their container ports — expose is more like documentation than enforcement.

Conclusion

In Docker Compose:

  • ports publishes ports from the container to the host machine.
  • expose makes ports available to other containers only, without exposing them externally.

Choosing between them depends on whether your service should be public-facing or private to your container ecosystem. Use ports for external access and expose for internal communication — and you’ll have a cleaner, more secure architecture.

Sharing Is Caring:

Leave a Comment