# The domain tab

This page explains how to expose a stack to the web, or how to expose a raw TCP port. You will need at least one deployed stack that publishes a port.

If you haven't deployed a stack yet, [follow the quickstart](../quickstart).

## How to expose a port in a Docker Compose file

If you already know how to do this, jump to [Expose a port on a DNS domain](#deploy-the-expose-to-a-dns-domain).

As explained in the [official Docker documentation](https://docs.docker.com/get-started/docker-concepts/running-containers/publishing-ports/), you publish a port by declaring it in your docker-compose.yml file.

Here is a quick example that exposes port 80 of an nginx container:

```yaml
services:
    webserver:
        image: nginx:latest
        ports:
            - 80:80 # bind port 80 of the container to port 80 of the host
```

import { Alert, AlertDescription, AlertTitle } from "zudoku/ui/Alert";

<Alert className="border-yellow-200 bg-yellow-50 text-yellow-800 dark:border-yellow-800 dark:bg-yellow-950 dark:text-yellow-400">
  <AlertTitle>Warning!</AlertTitle>
  <AlertDescription>Two services in the same Docker Compose file can't bind the same host port.</AlertDescription>
</Alert>

If you want the container port to differ from the host port, the Compose file looks like this:

```yaml
services:
    webserver:
        image: nginx:latest
        ports:
            - 3000:80 # bind port 80 of the container to port 3000 of the host
```

## Deploy the expose to a DNS domain

> This example uses the free `*.composerun.live` domains. If you own a domain, you can register it on compose_run and publish your app under your own domain name instead.

<div className="grid grid-cols-2 gap-5 w-full">
    <div>
        In your stack playground, open the domain tab in the inspector (1), then click the "Add domain" button (2).
    </div>
    <img className="w-100 ml-auto" src="./domaintab.png" alt="domain tab screenshot"/>
</div>

<div className="grid grid-cols-2 gap-5 w-full">
    <img className="w-100 ml-auto" src="./wizard1.png" alt="domain tab screenshot"/>
    <div>
        Follow the wizard by clicking the "Get a free subdomain" button (3).
        On the next step, select the port you want to deploy and continue to the last step.
    </div>
</div>

<div className="grid grid-cols-2 gap-5 w-full">
    <div>
        The last screen shows you live progress.
        <ol start="4">
            <li>The backend checks that the DNS record resolves to the compose_run load balancer</li>
            <li>The domain is allocated on our infrastructure</li>
            <li>A TLS certificate is provisioned</li>
        </ol>
    </div>
    <img className="w-100 ml-auto" src="./wizard3.png" alt="domain tab screenshot"/>
</div>

Once it's done, hit "Finish" and see your stack live on the web!

## Deploy the expose as a raw TCP port

Sometimes you don't want to expose a port through a web proxy, but as a raw TCP port instead.

<div className="grid grid-cols-2 gap-5 w-full">
    <div>
        To do so, enter the port you want to expose in the public port input (1).
    </div>
    <img src="./rawexpose.png" className="w-100"/>
</div>

<div className="grid grid-cols-2 gap-5 w-full">
    <img src="./rawcopy.gif" className="w-100"/>
    <div>
        You can then copy the assigned public port by hovering over the expose with your mouse.
    </div>
</div>

The port is now exposed. In the example below, we connect to the PostgreSQL port `5432` through the assigned public port `32998`, on the hostname `gateway.infra.composerun.dev`.
<img src="./dbeaver.png" className="w-100"/>