---
source: https://carbone.io/documentation/developer/self-hosted-deployment/deploy-with-docker.html
title: "Deploy with Docker"
description: "Deploy Carbone on your server with Docker"
generated_at: "2026-07-24"
---

# Deploy with Docker

Deploy Carbone on your server with Docker

## Introduction

Carbone reference images are available on [Docker Hub](https://hub.docker.com/r/carbone/carbone-ee). You can choose between 3 variants:

-   `slim` : Minimal version of Carbone. This image does not include Libreoffice (no PDF generation possible).
-   `latest`, `full` : Full version of Carbone including the latest version of LibreOffice
-   `latest-fonts`, `full-fonts` : Full version of Carbone including the latest version of LibreOffice. This version also includes all Google Fonts⁠ (royalty-free).

> ℹ️ **Note:** You can use Carbone Community features for free without a license.  
> To use Carbone Enterprise Edition on docker, you need a Carbone license. [Talk to us](https://carboneio.pipedrive.com/scheduler/5Rzzbxu6/carbone-on-premiseaws-presentation) to find out more.

## Quickstart

### Run a single container

To start your instance simply :

```sh
export CARBONE_LICENSE=`MY_CARBONE_LICENSE`

docker run -t -i --rm -p 4000:4000 -e CARBONE_LICENSE -e CARBONE_STUDIO=true carbone/carbone-ee
```

### Run with Docker Compose

Example of `docker-compose.yml` to run a Carbone container, with the license stored as a Docker secret rather than an environment variable:

```yml
version: "3.9"
services:
  carbone:
    image: carbone-ee
    ports:
      - "4000:4000"
    secrets:
      - source: carbone-license
        target: /app/config/prod.carbone-license
    environment:
      - CARBONE_STUDIO=true
    volumes:
      - ./template:/app/template
      - ./render:/app/render
secrets:
  carbone-license:
    file: your_license.carbone-license
```

To start the stack:

```sh
docker-compose up
```

## Configuration

[All configuration options](/documentation/developer/on-premise-installation/configuration.md) can be used by setting environment variables.

### Storage backends

By default, persistent data is stored inside the container.

> ⚠️ **Warning:** For production use, you need to configure a persistent storage space.

**Bind-mounted volume.** With a single Carbone instance, only the `/app/template` folder needs to be bound to a host folder. With multiple instances, you must also bind the `/app/render` folder.

```bash
# Start Carbone with /app/template bind on local folder
docker run -t -i --rm -p 4000:4000 -e CARBONE_LICENSE -e CARBONE_STUDIO=true --volume ./template:/app/template carbone/carbone-ee
```

**S3 or Azure Blob Storage.** Two plugins are preinstalled in docker images:

-   [carbone-ee-plugin-s3](https://github.com/carboneio/carbone-ee-plugin-s3) : Storage of templates and/or renders on an S3-compatible bucket
-   [carbone-ee-plugin-azure-storage-blob](https://github.com/carboneio/carbone-ee-plugin-azure-storage-blob) : Storage of templates and/or renders on an Azure Blob Storage

Here are the environment variables for configuring these plugins:

-   `CARBONE_USE_S3_PLUGIN` : set to `true` to enable S3 plugin. Default : `true`
-   `CARBONE_USE_AZURE_PLUGIN` : set to `true` to enable Azure Blob Storage plugin, and disable S3 plugin. Default : `false`

**S3 Configuration**

-   `AWS_ACCESS_KEY_ID` : Access Key ID
-   `AWS_SECRET_ACCESS_KEY` : Secret Key
-   `AWS_ENDPOINT_URL` : s3.amazonaws.com for AWS, storage.googleapis.com for GCP Storage
-   `AWS_REGION` : storage region
-   `BUCKET_RENDERS` : "BUCKET NAME to store your generated documents"
-   `BUCKET_TEMPLATES` : "BUCKET NAME to store your templates"

**Azure Blob Storage Configuration**

-   `AZURE_STORAGE_ACCOUNT` : Storage Account Name
-   `AZURE_STORAGE_KEY` : Storage Account Key
-   `CONTAINER_TEMPLATES` : Templates Storage Name
-   `CONTAINER_RENDERS` : Renders Storage Name

### Enable Studio

Set the `CARBONE_STUDIO` environment variable to `true` to enable Carbone Studio (already shown in the quickstart above).

### Authentication

To enable API authentication, you need to follow these steps :

**\- Set `CARBONE_AUTHENTICATION` to `true`**

**\- Generate private/public Carbone Key**

The key generation tool is included in the docker image from Carbone version 5 onwards.

```sh
docker run -it --platform "linux/amd64" carbone/carbone-ee:slim-5.0.0-beta.0 generate-keys
```

The two keys will be generated and displayed in the console. Create the files key.pem (with private key) and key.pub (with public key).

**\- Generate JWT token**

Follow the interactive shell:

```sh
docker run -it --platform "linux/amd64" carbone/carbone-ee:slim-5.0.0-beta.0 generate-token

## Paste in terminal content of key.pem
```

A JWT token is then displayed in the console. You can then use it in your API calls.

## Scaling and availability

To run several Carbone instances behind a reverse proxy, scale the `carbone` service in `docker-compose.yml` and share storage across replicas (a bind-mounted volume works for a single host, S3 or Azure Blob Storage for multi-host setups).

Example of `docker-compose.yml` with a high-availability setup, authentication and reverse proxy :

```yml
version: "3.9"
services:
  carbone:
    image: "carbone/carbone-ee:full"
    deploy:
      replicas: 3
    ports:
      - "4000"
    secrets:
      - source: carbone-license
        target: /app/config/license.carbone-license
      - source: carbone-publickey
        target: /app/config/key.pub
    environment:
      - CARBONE_STUDIO=true
      - CARBONE_AUTHENTICATION=true
      - CARBONE_STUDIO_USER=toto:Passw0rd
    volumes:
      - ./template:/app/template
      - ./render:/app/render
  nginx:
    image: nginx:latest
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - carbone
    ports:
      - "4000:4000"
secrets:
  carbone-license:
    file: license.carbone-license
  carbone-publickey:
    file: key.pub
```

Content of nginx.conf :

```text
user  nginx;

events {
  worker_connections   1000;
}
http {
  server {
    listen 4000;
    location / {
      proxy_pass http://carbone:4000;
    }
    client_max_body_size 20M;
  }
}
```

> ℹ️ **Note:** Replicas run independently by default (no metadata replication). If you need [template management](/documentation/developer/on-premise-installation/template-management.md) or the [job balancer](/documentation/developer/on-premise-installation/ha-and-scaling.md#job-balancer) across containers, enable clustering with `CARBONE_TEMPLATE_MANAGEMENT`, `CARBONE_PEER_PORT` and `CARBONE_PEER_ENDPOINTS` — see [HA and Scaling](/documentation/developer/on-premise-installation/ha-and-scaling.md).

## Infrastructure as Code

Ready-to-use `docker-compose` examples are available in the [carbone-ee-docker](https://github.com/carboneio/carbone-ee-docker/tree/master/deployement/docker-compose) repository:

| Scenario | Folder |
| --- | --- |
| Single instance | [simple](https://github.com/carboneio/carbone-ee-docker/tree/master/deployement/docker-compose/simple) |
| Multiple instances behind a reverse proxy | [multiInstance](https://github.com/carboneio/carbone-ee-docker/tree/master/deployement/docker-compose/multiInstance) |
| HTTPS with Let's Encrypt / certbot | [https](https://github.com/carboneio/carbone-ee-docker/tree/master/deployement/docker-compose/https) |
| Reverse proxy with authentication | [proxy-auth](https://github.com/carboneio/carbone-ee-docker/tree/master/deployement/docker-compose/proxy-auth) |

## Upgrade

To upgrade, pull the new image tag and recreate the container(s):

```sh
docker pull carbone/carbone-ee:full
docker compose up -d
```

This is safe as long as `/app/template` (and `/app/render`, for multiple instances) is on a bind-mounted volume or external storage (S3, Azure Blob Storage) rather than inside the container, so template data survives the recreation.

## Troubleshooting

**Container logs**

```sh
docker logs <container_name>
```

**Permission denied on the template/render volume.** The Carbone process inside the container runs as a non-root user. If you bind-mount a host folder, make sure it is writable by that user, for example:

```sh
mkdir -p ./template ./render
chmod 777 ./template ./render
```

**Port already allocated.** Another process (or a previous Carbone container) is already bound to the host port. Stop it, or map Carbone to a different host port with `-p <host_port>:4000`.

**401 on Studio or the API after enabling authentication.** Double-check that `CARBONE_STUDIO_USER` (Studio basic auth) or the JWT `Authorization: Bearer` header (API authentication) matches what you configured — the two are independent.

## Related topics

- [Deploy on Kubernetes](/documentation/developer/self-hosted-deployment/deploy-on-kubernetes.md)
- [Deploy on Google Cloud Platform](/documentation/developer/self-hosted-deployment/deploy-on-gcp.md)
- [Deploy on Azure](/documentation/developer/self-hosted-deployment/deploy-on-azure.md)
- [Deploy on AWS](/documentation/developer/self-hosted-deployment/deploy-on-aws.md)
- [Carbone on Amazon Elastic Container Service](/documentation/developer/self-hosted-deployment/deploy-on-aws-ecs.md)
