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

# Docker Deployment

<Callout type="info">
  **Docker Compose is recommended for small teams and evaluation** (\< 50 users).
  For production deployments, first read the [Overview](/en/deploy/production-overview), then follow [Kubernetes](/en/deploy/k8s) or a cloud-specific guide.
</Callout>

## Docker Compose Deployment

**Recommended Scale**: 0-50 users

| Advantages             | Disadvantages                              |
| ---------------------- | ------------------------------------------ |
| Simple deployment      | Single-machine deployment, complex scaling |
| Full control           |                                            |
| Flexible configuration |                                            |

**Server Requirements**

Ensure your server meets these basic requirements:

* Operating System: Recommended Linux distribution, such as Ubuntu 20.04 LTS
* Memory: Minimum 4GB RAM
* CPU: At least 2 cores
* Disk Space: Minimum 40GB available space
* Network: Stable internet connection with necessary port access

#### Prerequisites

Before starting, ensure you have:

* Basic understanding of Docker and containerization principles
* Docker and Docker Compose installed on your machine. Visit the official Docker documentation for installation guides.

### **Installing Docker**

```bash theme={null}
# Download the latest version of Docker
curl -fsSL https://get.docker.com | bash -s docker

# Verify the installation
docker --version
docker-compose --version
```

### Installing the Application

#### Create docker-compose.yaml File

Access your server, create and enter the teable folder:

```bash theme={null}
mkdir teable

cd teable
```

Create a `docker-compose.yaml` and a `.env` file, then paste the following content:

```bash theme={null}
vim docker-compose.yaml
```

#### **Minimal Deployment:**

```yaml docker-compose.yaml theme={null}
services:
  teable:
    image: ghcr.io/teableio/teable:latest
    restart: always
    ports:
      - '3000:3000'
    volumes:
      - teable-data:/app/.assets:rw
    env_file:
      - .env
    environment:
      - NEXT_ENV_IMAGES_ALL_REMOTE=true
    networks:
      - teable
    depends_on:
      teable-db:
        condition: service_healthy
      teable-cache:
        condition: service_healthy
    healthcheck:
      test: ['CMD', 'curl', '-f', 'http://localhost:3000/health']
      start_period: 5s
      interval: 5s
      timeout: 3s
      retries: 3

  teable-db:
    image: postgres:15.4
    restart: always
    ports:
      - '42345:5432'
    volumes:
      - teable-db:/var/lib/postgresql/data:rw
    environment:
      - POSTGRES_DB=${POSTGRES_DB}
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
    networks:
      - teable
    healthcheck:
      test: ['CMD-SHELL', "sh -c 'pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}'"]
      interval: 10s
      timeout: 3s
      retries: 3

  teable-cache:
    image: redis:7.2.4
    restart: always
    expose:
      - '6379'
    volumes:
      - teable-cache:/data:rw
    networks:
      - teable
    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
    healthcheck:
      test: ['CMD', 'redis-cli', '--raw', 'incr', 'ping']
      interval: 10s
      timeout: 3s
      retries: 3

networks:
  teable:
    name: teable-network

volumes:
  teable-db: {}
  teable-data: {}
  teable-cache: {}
```

```bash .env theme={null}
# Replace the default password below with a strong password (ASCII) of at least 8 characters.
POSTGRES_PASSWORD=replace_this_password
REDIS_PASSWORD=replace_this_password
SECRET_KEY=replace_this_secret_key

# Replace the following with a publicly accessible address
PUBLIC_ORIGIN=http://127.0.0.1:3000

# ---------------------

# Postgres
POSTGRES_HOST=teable-db
POSTGRES_PORT=5432
POSTGRES_DB=teable
POSTGRES_USER=teable

# Redis
REDIS_HOST=teable-cache
REDIS_PORT=6379
REDIS_DB=0

# App
PRISMA_DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
BACKEND_CACHE_PROVIDER=redis
BACKEND_CACHE_REDIS_URI=redis://default:${REDIS_PASSWORD}@${REDIS_HOST}:${REDIS_PORT}/${REDIS_DB}
```

#### **Adding Storage Service (Optional)**

For production deployments, use **S3-compatible object storage** (such as S3, MinIO, OSS/OBS/COS with S3-compatible endpoints, or another S3-compatible service) for better durability and scaling.

See: [Object Storage (S3-compatible)](/en/deploy/storage)

<Tabs>
  <Tab title="Add MinIO to docker-compose">
    MinIO provides an additional storage management interface (port 9001) and more powerful, stable file service.

    ```yaml docker-compose.yaml theme={null}
    services:
      # ...previous content
      teable-storage:
        image: minio/minio:RELEASE.2024-02-17T01-15-57Z
        ports:
          - "9000:9000"
          - "9001:9001"
        environment:
          - MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY}
          - MINIO_SECRET_KEY=${MINIO_SECRET_KEY}
        volumes:
          - teable-storage:/data:rw
        networks:
          - teable
        command: server /data --console-address ":9001"
      createbuckets:
        image: minio/mc
        networks:
          - teable
        entrypoint: >
          /bin/sh -c "
          /usr/bin/mc alias set teable-storage http://teable-storage:9000 ${MINIO_ACCESS_KEY} ${MINIO_SECRET_KEY};
          /usr/bin/mc mb teable-storage/public;
          /usr/bin/mc anonymous set public teable-storage/public;
          /usr/bin/mc mb teable-storage/private;
          exit 0;
          "
        depends_on:
          teable-storage:
            condition: service_started

    networks:
      teable:
        name: teable-network

    volumes:
      teable-db: {}
      teable-cache: {}
      # Add a new volume
      teable-storage: {}

    ```

    ```bash .env theme={null}
    # Replace the default passwords below with strong passwords (ASCII) of at least 8 characters.
    POSTGRES_PASSWORD=replace_this_password
    REDIS_PASSWORD=replace_this_password
    SECRET_KEY=replace_this_secret_key

    # If you enable HTTPS, set PROTOCOL to https.
    PROTOCOL=http
    # Set PUBLIC_HOST to the IP or domain name of your deployment. Cannot use localhost or 127.0.0.1.
    PUBLIC_HOST=192.168.x.x
    # Modify the final port to match your access port, or remove :port if using standard ports (80/443).
    PUBLIC_ORIGIN=${PROTOCOL}://${PUBLIC_HOST}:3000

    # ---------------------

    # Postgres
    POSTGRES_HOST=teable-db
    POSTGRES_PORT=5432
    POSTGRES_DB=teable
    POSTGRES_USER=teable

    # Redis
    REDIS_HOST=teable-cache
    REDIS_PORT=6379
    REDIS_DB=0

    # Minio
    MINIO_ACCESS_KEY=teable_minio_access
    MINIO_SECRET_KEY=${SECRET_KEY}

    # App
    PRISMA_DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
    BACKEND_CACHE_PROVIDER=redis
    BACKEND_CACHE_REDIS_URI=redis://default:${REDIS_PASSWORD}@${REDIS_HOST}:${REDIS_PORT}/${REDIS_DB}
    BACKEND_STORAGE_PROVIDER=minio
    BACKEND_STORAGE_PUBLIC_BUCKET=public
    BACKEND_STORAGE_PRIVATE_BUCKET=private
    BACKEND_STORAGE_MINIO_USE_SSL=false # If you enable HTTPS, modify this value to true
    BACKEND_STORAGE_MINIO_ENDPOINT=${PUBLIC_HOST}
    BACKEND_STORAGE_MINIO_PORT=9000
    BACKEND_STORAGE_MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY}
    BACKEND_STORAGE_MINIO_SECRET_KEY=${MINIO_SECRET_KEY}
    STORAGE_PREFIX=${PROTOCOL}://${PUBLIC_HOST}:${BACKEND_STORAGE_MINIO_PORT}
    ```
  </Tab>

  <Tab title="Connect to External MinIO">
    Before starting, you need to create two buckets on MinIO. One public bucket stores profile images and form headers, and one private bucket stores attachment content.

    ```sh .env theme={null}
    # ...previous content
    # Use minio provider
    BACKEND_STORAGE_PROVIDER=minio
    # Public bucket name
    BACKEND_STORAGE_PUBLIC_BUCKET=public
    # Private bucket name
    BACKEND_STORAGE_PRIVATE_BUCKET=private
    # Minio service endpoint ip or domain name
    BACKEND_STORAGE_MINIO_ENDPOINT=minio.example.com
    # Minio port
    BACKEND_STORAGE_MINIO_PORT=443
    # Whether HTTPS is enabled
    BACKEND_STORAGE_MINIO_USE_SSL=true
    # minio access key
    BACKEND_STORAGE_MINIO_ACCESS_KEY=_minio_access_key_
    # minio secret key
    BACKEND_STORAGE_MINIO_SECRET_KEY=_minio_secret_key_
    # Full access address
    STORAGE_PREFIX=https://minio.example.com

    # ---Internal Network Configuration (Optional)---
    # Internal minio service endpoint ip or domain name (not supported for HTTPS)
    BACKEND_STORAGE_MINIO_INTERNAL_ENDPOINT=teable-storage.internal
    # Internal minio port
    BACKEND_STORAGE_MINIO_INTERNAL_PORT=9000
    # ---region configuration (Optional)---
    # Region name
    BACKEND_STORAGE_MINIO_REGION=us-east-1

    ```
  </Tab>

  <Tab title="Connect to AWS S3">
    <Note>
      Note: You must configure **two buckets** (public/private). The **public bucket** must be **public-read** and must allow **CORS for any origin**, otherwise browser access may fail.
    </Note>

    Before starting, you need to create two buckets in AWS S3. One public bucket for storing avatars and form headers, and one private bucket for storing attachment content.

    ```sh .env theme={null}
    # ...previous content
    # Use standard S3 provider
    BACKEND_STORAGE_PROVIDER=s3
    # Region name
    BACKEND_STORAGE_S3_REGION=us-west-2
    # Endpoint, must include protocol (typically https)
    BACKEND_STORAGE_S3_ENDPOINT=https://s3.us-west-2.amazonaws.com
    # Access key
    BACKEND_STORAGE_S3_ACCESS_KEY=access_key
    # Secret key
    BACKEND_STORAGE_S3_SECRET_KEY=secret_key
    # Public bucket
    BACKEND_STORAGE_PUBLIC_BUCKET=your-public-bucket
    # Private bucket
    BACKEND_STORAGE_PRIVATE_BUCKET=your-private-bucket
    # Full access address, your public bucket's access address
    STORAGE_PREFIX=https://your-public-bucket.s3.us-west-2.amazonaws.com

    ```

    This process applies to most cloud providers, not just AWS S3. For exact bucket policy and CORS examples, see: [Object Storage (S3-compatible)](/en/deploy/storage)
  </Tab>
</Tabs>

#### Start the Application

Run the following commands in the current directory to start the application. Once started, you can access the application at 127.0.0.1:3000

<Note>
  HTTPS environment is required for large-scale data copying operations, otherwise asynchronous clipboard access will not be possible
</Note>

```bash theme={null}
docker-compose pull

docker-compose up -d
```

#### Using Managed Databases (Optional)

If you prefer to use managed databases, you can further simplify the deployment process:

1. Remove services.teable-db
2. Remove volumes.teable-db
3. Update .env with your managed database configuration

Fill in the database parameters with your managed database connection parameters:

```sh .env theme={null}
POSTGRES_HOST=your-database.com
POSTGRES_PORT=5432
POSTGRES_DB=teable
POSTGRES_USER=teable
```

<Note>
  Note that `127.0.0.1` is the container's internal network. If you want to connect to a locally deployed database, use `host.docker.internal` instead of `127.0.0.1` as the host address, otherwise the connection will fail
</Note>

**Similarly for external managed Redis:**

* Remove service.teable-cache
* Remove service.teable.depends\_on.teable-cache
* Remove volumes.teable-cache
* Update .env with your managed Redis configuration

### Next Steps

[Configure Email Service](/en/deploy/email)

[Configure External Database Connection](/en/deploy/database-connection)

## Support and Feedback

If you encounter any issues during deployment, please contact our support team at [support@teable.ai](mailto:support@teable.ai) or [submit an issue](https://github.com/teableio/teable/issues).

## License

Teable includes open-source Community features under the AGPL-3.0 license. To unlock paid features in self-hosted deployments, please subscribe on our [pricing page](https://app.teable.ai/public/pricing?host=self-hosted\&billing=year).

<Note>
  The `ghcr.io/teableio/teable:latest` image includes the full feature set. Paid features require a valid subscription license to activate.

  If you only need the open-source Community feature set, you can choose the `ghcr.io/teableio/teable-community:latest` image.
</Note>

## Common Issues

<Accordion title="How do I log in after the first deployment?">
  After the instance starts, open your instance URL and create an account there. Teable does not ship with a preset administrator account, and your self-hosted instance does not use your teable.ai cloud account.

  The first user who signs up on the instance becomes the instance administrator.
</Accordion>

<Accordion title="Why can't I import CSV/xlsx or upload images after installation">
  File import issues are typically due to incorrect configuration of the PUBLIC\_ORIGIN environment variable. You need to set PUBLIC\_ORIGIN to the currently accessible address:

  ```bash theme={null}
  # For local development
  PUBLIC_ORIGIN=http://127.0.0.1:3000

  # For local network access
  PUBLIC_ORIGIN=http://192.168.1.100:3000

  # For domain name access
  PUBLIC_ORIGIN=https://teable.example.com
  ```

  <Callout type="warning">
    Important: Do not include a trailing slash ("/") at the end of the URL.
  </Callout>

  After changing this configuration, you'll need to restart your Teable instance for the changes to take effect.
</Accordion>

<Accordion title="How to enable HTTPS">
  Enabling HTTPS requires the following steps:

  * Obtain a valid SSL certificate
  * Set `PROTOCOL=https` (or set `PUBLIC_ORIGIN=https://teable.example.com` depending on your setup)
  * If using MinIO, set `BACKEND_STORAGE_MINIO_USE_SSL=true`

  <Tip>
    It's recommended to use a reverse proxy (like Nginx or Traefik) to handle SSL termination.
  </Tip>

  <Tip>
    If you’re unsure how to configure Nginx (HTTPS/certificates, WebSocket, Docker networking, Nginx Proxy Manager, etc.), see: [Nginx (Reverse Proxy)](/en/deploy/nginx).
  </Tip>
</Accordion>

<Accordion title="How do I backup my data?">
  For Docker Compose deployments, you have several backup options:

  **Option 1: Full Virtual Machine Backup** (Recommended for simplicity)

  * Regularly backup the entire virtual machine hosting Teable
  * Provides complete system recovery capability

  **Option 2: Docker Volume Backup**

  * Backup all Docker volumes defined in your `docker-compose.yaml`
  * List volumes: `docker volume ls`
  * Backup a volume:
    ```bash theme={null}
    docker run --rm -v <volume_name>:/data -v $(pwd):/backup alpine tar czf /backup/<volume_name>.tar.gz /data
    ```

  **Option 3: Component-Level Backup** (Recommended for granular control)

  * **PostgreSQL database**: Contains all table data
    ```bash theme={null}
    docker exec teable-db pg_dump -U teable teable > backup.sql
    ```
  * **Redis database**: Contains automation queue data
    ```bash theme={null}
    docker exec teable-cache redis-cli --rdb /data/dump.rdb
    ```
  * **Data directory**: Backup the `teable-data` volume (contains all attachment files)
    ```bash theme={null}
    docker run --rm -v teable-data:/data -v $(pwd):/backup alpine tar czf /backup/teable-data.tar.gz /data
    ```

  For production environments, we recommend setting up automated daily backups with retention policies.
</Accordion>
