Docker-compose: ports vs expose explained

Docker-compose allows you to access container ports in two different ways: using “ports” and “expose:”. In this tutorial we will learn what is the difference between “ports” and “expose:” providing clear examples.

Docker-compose: ports vs expose

Before diving into the differences between “ports” and “expose”, we recommend checking this article if you are new to Docker-Compose: Orchestrate containers using Docker compose

Understanding Port Exposure in Docker Compose

Docker Compose offers two primary mechanisms for exposing container ports:

  • ports: This configuration maps a container port to a host port, making it accessible from your machine or external systems.
  • expose: This option announces a port within the container network, enabling communication between containers on the same Docker network.

Choosing the Right Approach

The choice between “ports” and “expose:” depends on your application’s communication needs:

  • Use “ports” when you need a service within a container to be accessible from outside the Docker network, such as a web server.
  • Use “expose:” when you want containers within the same Docker network to communicate with each other on the specified port.

Scenario 1: Exposing a Web Server (Using “ports”)

Let’s assume you have a web server running in a container on port 8080. You want to access it from your browser on the host machine.

version: "3.8"  # Or a compatible version

services:
  my-webserver:
    image: nginx:latest
    ports:
      - "8080:8080"  # Maps container port 8080 to host port 8080

In this configuration:

  • ports exposes the container’s port 8080 on the host machine, also using port 8080.
  • Now, you can access your web server by visiting http://localhost:8080 in your browser.

Scenario 2: Enabling Inter-Container Communication (Using “expose:”)

Consider a scenario where you have two containers: a database (port 5432) and an application that needs to connect to it.

version: "3.8"

services:
  my-database:
    image: postgres:latest
    expose:
      - "5432"  # Exposes port 5432 within the Docker network

  my-application:
    image: my-app-image
    depends_on:
      - my-database  # Ensures database starts before application
    links:
      - my-database:database  # Links database container to 'database' alias

Here, we’ve employed “expose:” for the database:

  • expose: 5432 indicates that port 5432 is available to other containers on the same Docker network.

The application container utilizes linking to connect:

  • depends_on: my-database guarantees the database starts first.
  • links: my-database:database establishes an alias (database) for the database container within the application container’s network.

Within the application container, you can configure database connection settings using database:5432 (assuming its internal hostname resolution aligns with the alias).

Key Points to Remember

  • “ports” maps container ports to host ports, enabling external access.
  • “expose:” announces ports within the Docker network for inter-container communication.
  • Choose the method that best suits your application’s architecture and communication requirements.

By understanding these concepts, you can effectively configure port exposure in your Docker Compose projects to facilitate communication between services.