> ## Documentation Index
> Fetch the complete documentation index at: https://thenile.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Getting started with Nile's Postgres platform locally with Docker

<Steps>
  <Step title="Prerequisites">
    Nile provides a cloud offering to help build multi-tenant apps. You can also get started with Nile's Docker image
    and try Nile locally. [Join our discord](https://discord.com/invite/8UuBB84tTy) to give feedback or ask questions about running Nile locally.

    * [Docker](https://www.docker.com/get-started)
    * Postgres client. We'll use `psql` in this guide.
  </Step>

  <Step title="Run the Docker Container">
    ```bash theme={null}
    docker run -p 5432:5432 -p 3000:3000 -ti ghcr.io/niledatabase/testingcontainer:latest
    ```

    This will start a Postgres database with Nile extensions installed. It will also start Nile Auth (optional).
    If this is the first time you are running the container, it will also pull the latest image,create the `test` database
    and the `00000000-0000-0000-0000-000000000000` user.
  </Step>

  <Step title="Connecting to the Database">
    You can use `psql` with the following connection string:

    ```bash theme={null}
    psql postgres://00000000-0000-0000-0000-000000000000:password@localhost:5432/test
    ```

    Or, if you are using a different client, you use the following connection details:

    ```
    Host: localhost
    Port: 5432
    Database: test
    Username: 00000000-0000-0000-0000-000000000000
    Password: password
    ```
  </Step>

  <Step title="Create a tenant-aware table">
    From this point, you can use the local database just like you would use Nile service.
    All the examples in the documentation are also applicable to the local database.
    Below we'll go through the steps in the quickstart guide using the local database.

    [Tenant-aware tables](/tenant-virtualization/tenant-isolation) are tables that have
    a `tenant_id` column. All the rows in such tables belong to a specific tenant.

    Let us create our first table that has a tenant\_id column and a vector column:

    ```sql theme={null}
    CREATE TABLE IF NOT EXISTS "todos" (
      "id" uuid DEFAULT gen_random_uuid(),
      "tenant_id" uuid,
      "title" varchar(256),
      "estimate" varchar(256),
      "embedding" vector(3),
      "complete" boolean,
      CONSTRAINT todos_pkey PRIMARY KEY("tenant_id","id")
    );
    ```

    If you are using `psql`, you can view the table schema by running `\d todos`.
  </Step>

  <Step title="Create tenants">
    Nile ships with built-in tables, like `tenants` table. Lets create our first tenant by inserting a row into the `tenants` table:

    ```sql theme={null}
    -- Creating the first tenant
    insert into tenants (id, name)
    values ('d24419bf-6122-4879-afa5-1d9c1b051d72', 'my first customer');
    select * from tenants;
    ```
  </Step>

  <Step title="Insert data into a tenant-aware table">
    Now that we have a tenant, we can insert data into our tenant-aware table:

    ```sql theme={null}
    -- adding a todo item for this tenant

    insert into todos (tenant_id, title, estimate, embedding, complete)
    values ('d24419bf-6122-4879-afa5-1d9c1b051d72', 'feed my cat', '1h', '[1,2,3]', false);
    ```

    and you can verify the data was inserted correctly by running:

    ```sql theme={null}
    select * from todos;
    ```

    You can add another tenant and insert data for that tenant in a similar fashion. This will allow us to explore
    tenant isolation (in the next section).

    ```sql theme={null}
    -- creating my second tenant

    insert into tenants (id, name)
    values ('7e93c45f-fe65-4f26-8ab6-922850fa4c7a', 'second customer');
    select * from tenants;

    insert into todos (tenant_id, title, estimate, embedding, complete)
    values ('7e93c45f-fe65-4f26-8ab6-922850fa4c7a', 'take out the trash', '2h', '[0.8,0.2,0.6]', false);
    select * from todos;
    ```
  </Step>

  <Step title="Tenant isolation">
    Nile goes a step further and provides tenant isolation. You can set the session to a specific tenant, and every query that follows will only return data that belongs to this specific tenant.

    Think of it as querying a virtual database dedicated to this one specific tenant.

    ```sql theme={null}
    -- set context to isolate query to a specific tenant DB
    -- our example uses the second tenant here
    set nile.tenant_id = '7e93c45f-fe65-4f26-8ab6-922850fa4c7a';

    SELECT tenants.name, title, embedding, estimate, complete
    FROM todos join tenants on tenants.id = todos.tenant_id;
    ```

    ✏️ Note that the container uses ephemeral storage, so all the data will be lost when the container is stopped.
    This is intentional, as it simplifies the setup (and more importantly - the cleanup), while still allowing you to experiment and test your application.
  </Step>
</Steps>

### Looking good! What's next?

🏆 Tada! You have learned the key Nile concepts. And it only took 5 minutes.

You can learn more about Nile's tenant virtualization features in the following tutorials:

* [Tenant management](/tenant-virtualization/tenant-management)
* [Tenant isolation](/tenant-virtualization/tenant-isolation)

Next, you will probably want to learn how to use Nile for building an app in your favorite language.
Check out our [Getting Started](/getting-started/languages/sql) guides for more information.

## Optional: Docker container configuration

The docker container can be configured with the following environment variables:

* `NILE_TESTING_DB_NAME`: The name of the database. Defaults to `test`.
* `NILE_TESTING_DB_ID`: The ID of the database. Must be a UUID. Defaults to `01000000-0000-7000-8000-000000000000`.
* `NILE_TESTING_DB_USER`: The username for the database user. Must be UUID. Defaults to `00000000-0000-0000-0000-000000000000`.
* `NILE_TESTING_DB_PASSWORD`: The password of the database user. Defaults to `password`.

If you need to change the default values, you can do so by setting the environment variables when running the container.

```bash theme={null}
docker run -p 5432:5432 -ti \
  -e NILE_TESTING_DB_NAME=mydatabase \
  -e NILE_TESTING_DB_PASSWORD=mypassword \
  ghcr.io/niledatabase/testingcontainer:v0.0.2
```

with this configuration, the connection string will be:

```bash theme={null}
psql postgres://00000000-0000-0000-0000-000000000000:mypassword@127.0.0.1:5432/mydatabase
```

You can also change the port mappings in the docker run command, if you want Postgres to listen on a different port.

## Troubleshooting

If you are having trouble running the container, the first step is to check that you are using the latest version of the container.
You can do this by first deleting existing images of `niledatabase/testingcontainer:latest` (since they may refer to older versions) and then running `docker pull ghcr.io/niledatabase/testingcontainer:latest`.

Please check if any of the common issues and solutions below help solve your problem. If not, we welcome you to report the issue on either [GitHub](https://github.com/niledatabase/niledatabase) or [Discord](https://discord.com/invite/8UuBB84tTy)

When reporting the issue, please include:

* The docker container logs (`docker logs <container_id>`)
* The exact error message you're encountering

Here are some common issues you might encounter when running the docker container:

### Server closed the connection unexpectedly

It takes a bit of time for the container to start up. If you get the following error:

```bash theme={null}
➜ psql postgres://00000000-0000-0000-0000-000000000000:password@localhost:5432/test
psql: error: connection to server at "localhost" (::1), port 5432 failed: server closed the connection unexpectedly
	This probably means the server terminated abnormally
	before or while processing the request.
```

Wait for a few seconds, until the container logs indicate that the database is ready:

```bash theme={null}
Database has been created and is ready
```

Then try connecting again.

### Role does not exist

If you get the following error:

```bash theme={null}
➜  niledatabase_private git:(extension_groups) ✗ psql postgres://00000000-0000-0000-0000-000000000000:password@localhost:5432/test
psql: error: connection to server at "localhost" (::1), port 5432 failed: FATAL:  role "00000000-0000-0000-0000-000000000000" does not exist
```

It is likely that you have another Postgres instance running on your machine that also uses port 5432. In this situation, `psql` will try to connect to the default Postgres instance, which fails because we are using a specific user that doesn't exist in the default Postgres instance.

You can either:

* Stop the other Postgres instance - the exact command depends on your operating system and Postgres installation method.
* Change the port mapping when running the container. For example to port 5433, and then connect to the new port:
  ```bash theme={null}
  docker run -p 5433:5432 -ti ghcr.io/niledatabase/testingcontainer:latest
  psql postgres://00000000-0000-0000-0000-000000000000:password@localhost:5433/test
  ```
