# Docker
URL: /overview/self-hosting/docker

---
title: Docker
sidebarTitle: Docker
description: Self-Hosting Steel Browser Using Docker
full: true
llm: true
---
# Overview

This guide provides step-by-step instructions to set up your own Steel Browser instance using Docker. The setup consists of multiple deployment options – from the traditional docker-compose setup to the new, simplified single Docker image deployment.

## Prerequisites

* Docker (20.10.0 or later)
* At least 4GB of RAM
* 10GB of free disk space

## Quick Start Using Docker Compose

1. Create a new directory for your Steel Browser instance:

```bash Terminal -wc
mkdir steel-browser && cd steel-browser
```

2. Create the following file:

### docker-compose.yaml

```yaml YAML -wcn
services:
  api:
    image: ghcr.io/steel-dev/steel-browser-api:latest
    ports:
      - "3000:3000"
      - "9223:9223"
    volumes:
      - ./.cache:/app/.cache
    networks:
      - steel-network

  ui:
    image: ghcr.io/steel-dev/steel-browser-ui:latest
    ports:
      - "5173:80"
    depends_on:
      - api
    networks:
      - steel-network

networks:
  steel-network:
    name: steel-network
    driver: bridge
```

3. Launch the containers:

```bash Terminal -wc
docker compose up -d
```

4. Access Steel Browser by opening `http://localhost:5173` in your web browser.

## Alternative Deployment: Single Docker Image

Steel Browser can now be deployed using a single Docker image—no more complex docker-compose setup!

### Single Docker Image Deployment

Run the following command to launch Steel Browser:

```bash Terminal -wc
docker run --rm -it -p 3000:3000 -p 9223:9223 ghcr.io/steel-dev/steel-browser:latest
```

This command will:
- Pull the latest Docker image from GitHub Container Registry.
- Expose the API on port 3000 and Chrome debugging on port 9223.
- Run the container interactively and remove it when stopped.

Access Steel Browser via your browser at `http://localhost:3000` and the UI at `http://localhost:3000/ui`.

## Building the Singular Docker Image Locally

If you wish to build the Docker image from source rather than relying on the pre-built image, follow these steps:

1. Clone the repository:

```bash Terminal -wc
git clone https://github.com/steel-dev/steel-browser.git
cd steel-browser
```

2. Build the Docker image:

```bash Terminal -wc
docker build -t steel-browser:local .
```

3. Run the newly built image:

```bash Terminal -wc
docker run --rm -it -p 3000:3000 -p 9223:9223 steel-browser:local
```

This method gives you the flexibility to modify the image locally. Compared to the docker-compose setup where the API and UI are managed in separate containers, here everything runs within one container, simplifying deployment for testing and development.

## Advanced Setup

### Building From Source with Docker Compose

If you prefer to build the containers yourself with docker-compose:

1. Clone the repository:

```bash Terminal -wc
git clone https://github.com/steel-dev/steel-browser.git
cd steel-browser
```

2. Create a `.env` file (optional).

3. Build and start using the development compose file:

```bash Terminal -wc
docker compose -f docker-compose.dev.yml up -d --build
```

_The “-d” flag runs the containers in the background._

### Configuration Options

* **API Port**: Default is 3000 (internally also 3000). If changed in the compose file, update the API binding accordingly.
* **UI Port**: Default is 5173 (or 80 inside container). Adjust if needed.
* **Chrome Debugging Port**: Default is 9223. Required for browser communication.

### Volume Persistence

The `.cache` directory stores Chrome data and extensions. Mount it as a volume for persistence:

```yaml YAML -wcn
volumes:
  - ./.cache:/app/.cache
```

## Architecture

Steel Browser consists of two main components when using docker-compose:

1. **API Container**: Runs Chrome in headless mode and provides CDP (Chrome DevTools Protocol) services.
2. **UI Container**: An Nginx-based frontend for interacting with the browser.

When using the single Docker image deployment, both the API and UI are integrated into one container.

## Customizing the Build

### Using a Different Chrome Version

The API container uses Chrome 128.0.6613.119 by default. To use a different version:

1. Create a custom Dockerfile based on the API one.
2. Modify the Chrome installation section:

```dockerfile Dockerfile -wcn
ARG CHROME_VERSION="128.0.6613.119"
RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
    wget \
    ca-certificates \
    curl \
    unzip \
    && CHROME_DEB="google-chrome-stable_${CHROME_VERSION}-1_amd64.deb" \
    && wget -q "https://mirror.cs.uchicago.edu/google-chrome/pool/main/g/google-chrome-stable/${CHROME_DEB}"
    # ...rest of the installation...
```

### Changing Node Version

Both containers use Node 22.13.0 by default. To use a different version, modify the build arguments:

```yaml YAML -wcn
services:
  api:
    build:
      context: .
      dockerfile: ./api/Dockerfile
      args:
        NODE_VERSION: 18.19.0
```

## Troubleshooting

### Chrome Won't Start

Ensure your host has enough resources and check the API container logs:

```bash Terminal -wcn
docker logs steel-browser_api_1
```

Common issues include:
* Running on ARM architecture (There are official images for ARM, or build the image yourself)
* Insufficient memory
* Missing shared libraries
* Permission issues with the `.cache` directory

### Connectivity Issues

If the UI can't connect to the API:
1. Verify both containers are running.
2. Check if the API is accessible:

```bash Terminal -wcn
curl http://localhost:3000/api/health
```

3. Ensure the containers can communicate over the network:

```bash Terminal -wcn
docker exec steel-browser_ui_1 curl http://api:3000/api/health
```

## Production Deployment

For production environments:
1. Use specific image versions rather than `latest`.
2. Set up a proper reverse proxy with HTTPS.
3. Configure appropriate resource limits.

Example production compose file:

```yaml YAML -wcn
services:
  api:
    image: ghcr.io/steel-dev/steel-browser-api:sha256:...
    restart: always
    ports:
      - "3000:3000"
    deploy:
      resources:
        limits:
          memory: 2G
    volumes:
      - ./data/.cache:/app/.cache
    networks:
      - steel-network

  ui:
    image: ghcr.io/steel-dev/steel-browser-ui:sha256:...
    restart: always
    ports:
      - "5173:80"
    networks:
      - steel-network

networks:
  steel-network:
    name: steel-network
    driver: bridge
```

## Security Considerations

* Avoid exposing the Chrome debugging port (9223) to the public internet.
* Consider not exposing the API if the UI and API are running within the same secured network.
* Set up proper authentication if deploying publicly.
* Keep containers updated with the latest versions.

## Updating

To update to the latest version:

```bash Terminal -wcn
docker compose pull
docker compose up -d
```

For custom builds:

```bash Terminal -wcn
git pull
docker compose -f docker-compose.dev.yml up -d --build
```

:::callout
type: help
### Need help running locally?
Reach out to us on the **#help** channel on [Discord](https://discord.gg/steel-dev) under the ⭐ community section.
:::
