Gotenberg is a Docker-powered stateless API for converting HTML, Markdown and Office documents to PDF.
Gotenberg is shipped within a Docker image.
It uses a dedicated non-root user called
gotenbergwith uid and gid1001.
You may start it with:
$ docker run --rm -p 3000:3000 thecodingmachine/gotenberg:6
The API will be available at http://localhost:3000.
You may also add it in your Docker Compose stack:
version: '3' services: # your others services gotenberg: image: thecodingmachine/gotenberg:6
The API will be available under
gotenberg:3000in your Docker Compose network.
It may also be deployed with Kubernetes.
Make sure to provide enough memory and CPU requests (for instance 512Mi and 0.2 CPU).
The more resources are granted, the quicker will be the conversions.
In the deployment specification of the pod, also specify the uid 1001 of the user gotenberg:
securityContext: privileged: false runAsUser: 1001
If you’re looking for cost savings, you might be interested by Cloud Run.
In the following examples, we will assume your Gotenberg API is available at http://localhost:3000.
We provide clients in various languages for easing the interactions with the API.
$ go get -u github.com/thecodingmachine/gotenberg-go-client/v6
Unless your project already has a PSR7 HttpClient, install php-http/guzzle6-adapter:
$ composer require php-http/guzzle6-adapter
Then the PHP client:
$ composer require thecodingmachine/gotenberg-php-client
You may customize the API behaviour thanks to environment variables.
The API provides structured logging allowing you to have relevant information about what’s going on.
If a TTY is attached, the log entries are displayed in text format with colors, otherwise in JSON format.
You may customize the severity of the log entries thanks to the environment variable LOG_LEVEL.
It accepts one of the following severities: "DEBUG", "INFO" (default) and "ERROR".
By default, the API will listen on port 3000.
You may customize this value with the environment variable DEFAULT_LISTEN_PORT.
This environment variable accepts any string that can be turned into a port number.
In order to save some resources, the Gotenberg image accepts the environment variable DISABLE_GOOGLE_CHROME
for disabling Google Chrome.
It takes the strings "0" or "1" as value where 1 means true
If Google Chrome is disabled, the following conversions will not be available anymore: HTML, URL and Markdown
When performing a HTML, URL or Markdown conversion, the API might return
a 400 HTTP code with the message increase the Google Chrome rpcc buffer size.
If so, you may increase this buffer size with the environment variable DEFAULT_GOOGLE_CHROME_RPCC_BUFFER_SIZE.
It takes a string representation of an int as value (e.g. "1048576" for 1 MB).
The hard limit is 100 MB and is defined by Google Chrome itself.
The default Google Chrome rpcc buffer size may also be overridden per request thanks to the form field
googleChromeRpccBufferSize. See the rpcc buffer size section.
You may also disable LibreOffice (unoconv) with DISABLE_UNOCONV.
If LibreOffice (unoconv) is disabled, the following conversion will not be available anymore: Office
By default, the API will wait 10 seconds before it considers the conversion to be unsuccessful.
If unsucessful, it returns a 504 HTTP code.
You may customize this timeout thanks to the environment variable DEFAULT_WAIT_TIMEOUT.
It takes a string representation of a float as value (e.g "2.5" for 2.5 seconds).
The default timeout may also be overridden per request thanks to the form field
waitTimeout. See the timeout section.
By default, the value of the form field waitTimeout cannot be more than 30 seconds.
You may increase or decrease this limit thanks to the environment variable MAXIMUM_WAIT_TIMEOUT.
It takes a string representation of a float as value (e.g "2.5" for 2.5 seconds).
By default, the API will wait 10 seconds before it considers the sending of the resulting PDF to be unsuccessful.
See the webhook section.
You may customize this timeout thanks to the environment variable DEFAULT_WEBHOOK_URL_TIMEOUT.
It takes a string representation of a float as value (e.g "2.5" for 2.5 seconds).
The default timeout may also be overridden per request thanks to the form field
webhookURLTimeout. See the webhook timeout section.
By default, the value of the form field webhookURLTimeout cannot be more than 30 seconds.
You may increase or decrease this limit thanks to the environment variable MAXIMUM_WEBHOOK_URL_TIMEOUT.
It takes a string representation of a float as value (e.g "2.5" for 2.5 seconds).
By default, the value of the form field waitDelay cannot be more than 10 seconds.
See the wait delay section.
You may increase or decrease this limit thanks to the environment variable MAXIMUM_WAIT_DELAY.
It takes a string representation of a float as value (e.g "2.5" for 2.5 seconds).
Gotenberg provides the endpoint /convert/html for HTML conversions.
It accepts POST requests with a multipart/form-data Content-Type.
The only requirement is to send a file named index.html: it is the file
which will be converted to PDF.
For instance:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>My PDF</title> </head> <body> <h1>Hello world!</h1> </body> </html>
$ curl --request POST \ --url http://localhost:3000/convert/html \ --header 'Content-Type: multipart/form-data' \ --form files=@index.html \ -o result.pdf
import "github.com/thecodingmachine/gotenberg-go-client/v6" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} req, _ := gotenberg.NewHTMLRequest("index.html") dest := "result.pdf" c.Store(req, dest) }
use TheCodingMachine\Gotenberg\Client;
use TheCodingMachine\Gotenberg\DocumentFactory;
use TheCodingMachine\Gotenberg\HTMLRequest;
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
$request = new HTMLRequest($index);
$dest = "result.pdf";
$client->store($request, $dest);
You may also add a header and/or a footer in the resulting PDF.
Respectively, a file named header.html and footer.html.
Each of them has to be a complete HTML document:
<html> <head> <style> body { font-size: 8rem; margin: 4rem auto; } </style> </head> <body> <p> <span class="pageNumber"></span> of <span class="totalPages"></span> </p> </body> </html>
The following classes allow you to inject printing values:
date: formatted print datetitle: document titlepageNumber: current page numbertotalPage: total pages in the documentThere are some limitations:
index.html filefooter.html CSS properties override the ones from header.htmlbase64 encoded source (<img src="data:image/png;base64, iVBORw0K... />)background-color and color CSS properties require an additional -webkit-print-color-adjust: exact CSS property in order to work$ curl --request POST \ --url http://localhost:3000/convert/html \ --header 'Content-Type: multipart/form-data' \ --form files=@index.html \ --form files=@header.html \ --form files=@footer.html \ -o result.pdf
import "github.com/thecodingmachine/gotenberg-go-client/v6" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} req, _ := gotenberg.NewHTMLRequest("index.html") req.Header("header.html") req.Footer("footer.html") dest := "result.pdf" c.Store(req, dest) }
use TheCodingMachine\Gotenberg\Client;
use TheCodingMachine\Gotenberg\DocumentFactory;
use TheCodingMachine\Gotenberg\HTMLRequest;
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
$header = DocumentFactory::makeFromPath('header.html', 'header.html');
$footer = DocumentFactory::makeFromPath('footer.html', 'footer.html');
$request = new HTMLRequest($index);
$request->setHeader($header);
$request->setFooter($footer);
$dest = "result.pdf";
$client->store($request, $dest);
You may also send additional files. For instance: images, fonts, stylesheets and so on.
The only requirement is to make sure that their paths
are on the same level as the index.html file.
In others words, this will work:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>My PDF</title> </head> <body> <h1>Hello world!</h1> <img src="img.png"> </body> </html>
But this won’t:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>My PDF</title> </head> <body> <h1>Hello world!</h1> <img src="/foo/img.png"> </body> </html>
You may also use remote paths for Google fonts, images and so on.
If you want to install fonts directly in the Gotenberg Docker image, see to the fonts section.
$ curl --request POST \ --url http://localhost:3000/convert/html \ --header 'Content-Type: multipart/form-data' \ --form files=@index.html \ --form files=@style.css \ --form files=@img.png \ --form files=@font.woff \ -o result.pdf
import "github.com/thecodingmachine/gotenberg-go-client/v6" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} req, _ := gotenberg.NewHTMLRequest("index.html") req.Assets("font.woff", "img.gif", "style.css") dest := "result.pdf" c.Store(req, dest) }
use TheCodingMachine\Gotenberg\Client;
use TheCodingMachine\Gotenberg\DocumentFactory;
use TheCodingMachine\Gotenberg\HTMLRequest;
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
$assets = [
DocumentFactory::makeFromPath('style.css', 'style.css'),
DocumentFactory::makeFromPath('img.png', 'img.png'),
DocumentFactory::makeFromPath('font.woff', 'font.woff'),
];
$request = new HTMLRequest($index);
$request->setAssets($assets);
$dest = "result.pdf";
$client->store($request, $dest);
You may also customize the resulting PDF format.
By default, it will be rendered with A4 size, 1 inch margins and portrait orientation.
Paper size and margins have to be provided in
inches. Same for margins.
$ curl --request POST \ --url http://localhost:3000/convert/html \ --header 'Content-Type: multipart/form-data' \ --form files=@index.html \ --form paperWidth=8.27 \ --form paperHeight=11.69 \ --form marginTop=0 \ --form marginBottom=0 \ --form marginLeft=0 \ --form marginRight=0 \ --form landscape=true \ -o result.pdf
import "github.com/thecodingmachine/gotenberg-go-client/v6" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} req, _ := gotenberg.NewHTMLRequest("index.html") req.PaperSize(gotenberg.A4) req.Margins(gotenberg.NoMargins) req.Landscape(true) dest := "result.pdf" c.Store(req, dest) }
use TheCodingMachine\Gotenberg\Client;
use TheCodingMachine\Gotenberg\DocumentFactory;
use TheCodingMachine\Gotenberg\HTMLRequest;
use TheCodingMachine\Gotenberg\Request;
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
$request = new HTMLRequest($index);
$request->setPaperSize(Request::A4);
$request->setMargins(Request::NO_MARGINS);
$request->setLandscape(true);
$dest = "result.pdf";
$client->store($request, $dest);
In some cases, you may want to wait a certain amount of time to make sure the page you’re trying to generate is fully rendered. For instance, if your page relies a lot on JavaScript for rendering.
The wait delay is a duration in seconds (e.g
2.5for 2.5 seconds).
$ curl --request POST \ --url http://localhost:3000/convert/html \ --header 'Content-Type: multipart/form-data' \ --form files=@index.html \ --form waitDelay=5.5 \ -o result.pdf
import "github.com/thecodingmachine/gotenberg-go-client/v6" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} req, _ := gotenberg.NewHTMLRequest("index.html") req.WaitDelay(5.5) dest := "result.pdf" c.Store(req, dest) }
use TheCodingMachine\Gotenberg\Client;
use TheCodingMachine\Gotenberg\DocumentFactory;
use TheCodingMachine\Gotenberg\HTMLRequest;
use TheCodingMachine\Gotenberg\Request;
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
$request = new HTMLRequest($index);
$request->setWaitDelay(5.5);
$dest = "result.pdf";
$client->store($request, $dest);
The API might return a 400 HTTP code with the message increase the Google Chrome rpcc buffer size.
If so, you may increase this buffer size with a form field named googleChromeRpccBufferSize.
It takes an int as value (e.g. 1048576 for 1 MB).
The hard limit is 100 MB and is defined by Google Chrome itself.
You may also define this value globally: see the environment variables section.
$ curl --request POST \ --url http://localhost:3000/convert/html \ --header 'Content-Type: multipart/form-data' \ --form files=@index.html \ --form googleChromeRpccBufferSize=1048576 \ -o result.pdf
import "github.com/thecodingmachine/gotenberg-go-client/v6" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} req, _ := gotenberg.NewHTMLRequest("index.html") req.GoogleChromeRpccBufferSize(1048576) dest := "result.pdf" c.Store(req, dest) }
use TheCodingMachine\Gotenberg\Client;
use TheCodingMachine\Gotenberg\DocumentFactory;
use TheCodingMachine\Gotenberg\HTMLRequest;
use TheCodingMachine\Gotenberg\Request;
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
$request = new HTMLRequest($index);
$request->setGoogleChromeRpccBufferSize(1048576);
$dest = "result.pdf";
$client->store($request, $dest);
Gotenberg provides the endpoint /convert/url for remote URL conversions.
It accepts POST requests with a multipart/form-data Content-Type.
This endpoint does not accept an index.html file nor assets files but a form field
named remoteURL instead. Otherwise, URL conversions work the same as HTML conversions.
Attention: when converting a website to PDF, you should remove all margins. If not, some of the content of the page might be hidden.
$ curl --request POST \ --url http://localhost:3000/convert/url \ --header 'Content-Type: multipart/form-data' \ --form remoteURL=https://google.com \ --form marginTop=0 \ --form marginBottom=0 \ --form marginLeft=0 \ --form marginRight=0 \ -o result.pdf
import "github.com/thecodingmachine/gotenberg-go-client/v6" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} req := gotenberg.NewURLRequest("https://google.com") req.Margins(gotenberg.NoMargins) dest := "result.pdf" c.Store(req, dest) }
use TheCodingMachine\Gotenberg\Client;
use TheCodingMachine\Gotenberg\URLRequest;
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
$request = new URLRequest('https://google.com');
$request->setMargins(Request::NO_MARGINS);
$dest = "result.pdf";
$client->store($request, $dest);
Gotenberg provides the endpoint /convert/markdown for Markdown conversions.
It accepts POST requests with a multipart/form-data Content-Type.
Markdown conversions work the same as HTML conversions.
Only difference is that you have access to the Go template function toHTML
in the file index.html. This function will convert a given markdown file to HTML.
For instance:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>My PDF</title> </head> <body> {{ toHTML .DirPath "file.md" }} </body> </html>
$ curl --request POST \ --url http://localhost:3000/convert/markdown \ --header 'Content-Type: multipart/form-data' \ --form files=@index.html \ --form files=@file.md \ -o result.pdf
import "github.com/thecodingmachine/gotenberg-go-client/v6" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} req, _ := gotenberg.NewMarkdownRequest("index.html", "file.md") dest := "result.pdf" c.Store(req, dest) }
use TheCodingMachine\Gotenberg\Client;
use TheCodingMachine\Gotenberg\DocumentFactory;
use TheCodingMachine\Gotenberg\MarkdownRequest;
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
$markdowns = [
DocumentFactory::makeFromPath('file.md', 'file.md'),
];
$request = new MarkdownRequest($index, $markdowns);
$dest = "result.pdf";
$client->store($request, $dest);
Gotenberg provides the endpoint /convert/office for Office document conversions.
It accepts POST requests with a multipart/form-data Content-Type.
You may send one or more Office documents. Following file extensions are accepted:
.txt.rtf.fodt.doc.docx.odt.xls.xlsx.ods.ppt.pptx.odpAll files will be merged into a single resulting PDF.
Attention: Gotenberg merges the PDF files alphabetically.
$ curl --request POST \ --url http://localhost:3000/convert/office \ --header 'Content-Type: multipart/form-data' \ --form files=@document.docx \ --form files=@document2.docx \ -o result.pdf
import "github.com/thecodingmachine/gotenberg-go-client/v6" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} req, _ := gotenberg.NewOfficeRequest("document.docx", "document2.docx") dest := "result.pdf" c.Store(req, dest) }
use TheCodingMachine\Gotenberg\Client;
use TheCodingMachine\Gotenberg\DocumentFactory;
use TheCodingMachine\Gotenberg\OfficeRequest;
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
$files = [
DocumentFactory::makeFromPath('document.docx', 'document.docx'),
DocumentFactory::makeFromPath('document2.docx', 'document2.docx'),
];
$request = new OfficeRequest($files);
$dest = "result.pdf";
$client->store($request, $dest);
You may also customize the resulting PDF format.
By default, it will be rendered with portrait orientation.
$ curl --request POST \ --url http://localhost:3000/convert/office \ --header 'Content-Type: multipart/form-data' \ --form files=@document.docx \ --form landscape=true \ -o result.pdf
import "github.com/thecodingmachine/gotenberg-go-client/v6" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} req, _ := gotenberg.NewOfficeRequest("document.docx") req.Landscape(true) dest := "result.pdf" c.Store(req, dest) }
use TheCodingMachine\Gotenberg\Client;
use TheCodingMachine\Gotenberg\DocumentFactory;
use TheCodingMachine\Gotenberg\OfficeRequest;
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
$files = [
DocumentFactory::makeFromPath('document.docx', 'document.docx'),
];
$request = new OfficeRequest($files);
$request->setLandscape(true);
$dest = "result.pdf";
$client->store($request, $dest);
Gotenberg provides the endpoint /merge for merging PDFs.
It accepts POST requests with a multipart/form-data Content-Type.
Nothing fancy here: you may send one or more PDF files and the API will merge them and return the resulting PDF file.
Attention: Gotenberg merges the PDF files alphabetically.
$ curl --request POST \ --url http://localhost:3000/merge \ --header 'Content-Type: multipart/form-data' \ --form files=@file.pdf \ --form files=@file2.pdf \ -o result.pdf
import "github.com/thecodingmachine/gotenberg-go-client/v6" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} req, _ := gotenberg.NewMergeRequest("file.pdf", "file2.pdf") dest := "result.pdf" c.Store(req, dest) }
use TheCodingMachine\Gotenberg\Client;
use TheCodingMachine\Gotenberg\DocumentFactory;
use TheCodingMachine\Gotenberg\MergeRequest;
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
$files = [
DocumentFactory::makeFromPath('file.pdf', 'file.pdf'),
DocumentFactory::makeFromPath('file2.pdf', 'file2.pdf'),
];
$request = new MergeRequest($files);
$dest = "result.pdf";
$client->store($request, $dest);
All endpoints accept a form field named waitTimeout.
The API will wait the given seconds before it considers the conversion to be unsucessful.
If unsucessful, it returns a 504 HTTP code.
It takes a float as value (e.g 2.5 for 2.5 seconds).
You may also define this value globally: see the environment variables section.
$ curl --request POST \ --url http://localhost:3000/convert/html \ --header 'Content-Type: multipart/form-data' \ --form files=@index.html \ --form waitTimeout=2.5
import "github.com/thecodingmachine/gotenberg-go-client/v6" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} req, _ := gotenberg.NewHTMLRequest("index.html") req.WaitTimeout(2.5) resp, _ := c.Post(req) }
use TheCodingMachine\Gotenberg\Client;
use TheCodingMachine\Gotenberg\DocumentFactory;
use TheCodingMachine\Gotenberg\HTMLRequest;
use TheCodingMachine\Gotenberg\Request;
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
$request = new HTMLRequest($index);
$request->setWaitTimeout(2.5);
$dest = "result.pdf";
$client->store($request, $dest);
All endpoints accept a form field named webhookURL.
If provided, the API will send the resulting PDF file in a POST request with the application/pdf Content-Type
to given URL.
By doing so, your requests to the API will be over before the conversions are actually done!
$ curl --request POST \ --url http://localhost:3000/convert/html \ --header 'Content-Type: multipart/form-data' \ --form files=@index.html \ --form webhookURL='http://myapp.com/webhook/'
import "github.com/thecodingmachine/gotenberg-go-client/v6" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} req, _ := gotenberg.NewHTMLRequest("index.html") req.WebhookURL("http://myapp.com/webhook/") resp, _ := c.Post(req) }
use TheCodingMachine\Gotenberg\Client;
use TheCodingMachine\Gotenberg\DocumentFactory;
use TheCodingMachine\Gotenberg\HTMLRequest;
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
$request = new HTMLRequest($index);
$request->setWebhookURL('http://myapp.com/webhook/');
$resp = $client->post($request);
If a webhookURL is provided, you may also send a form field named webhookURLTimeout.
The API will wait the given seconds before it considers the sending of the resulting PDF to be unsucessful.
It takes a float as value (e.g 2.5 for 2.5 seconds).
You may also define this value globally: see the environment variables section.
$ curl --request POST \ --url http://localhost:3000/convert/html \ --header 'Content-Type: multipart/form-data' \ --form files=@index.html \ --form webhookURL='http://myapp.com/webhook/' \ --form webhookURLTimeout=2.5
import "github.com/thecodingmachine/gotenberg-go-client/v6" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} req, _ := gotenberg.NewHTMLRequest("index.html") req.WebhookURL("http://myapp.com/webhook/") req.WebhookURLTimeout(2.5) resp, _ := c.Post(req) }
use TheCodingMachine\Gotenberg\Client;
use TheCodingMachine\Gotenberg\DocumentFactory;
use TheCodingMachine\Gotenberg\HTMLRequest;
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
$request = new HTMLRequest($index);
$request->setWebhookURL('http://myapp.com/webhook/');
$request->setWebhookURLTimeout(2.5);
$resp = $client->post($request);
All endpoints accept a form field named resultFilename.
If provided, the API will return the resulting PDF file with the given filename. Otherwise a random filename is used.
Attention: this feature does not work if the form field
webhookURLis given.
$ curl --request POST \ --url http://localhost:3000/convert/html \ --header 'Content-Type: multipart/form-data' \ --form files=@index.html \ --form resultFilename='foo.pdf'
import "github.com/thecodingmachine/gotenberg-go-client/v6" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} req, _ := gotenberg.NewHTMLRequest("index.html") req.ResultFilename("foo.pdf") resp, _ := c.Post(req) }
use TheCodingMachine\Gotenberg\Client;
use TheCodingMachine\Gotenberg\DocumentFactory;
use TheCodingMachine\Gotenberg\HTMLRequest;
use TheCodingMachine\Gotenberg\Request;
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
$request = new HTMLRequest($index);
$request->setResultFilename('foo.pdf');
$resp = $client->post($request);
The API uses under the hood intricate programs.
Gotenberg tries to abstract as much complexity as possible but it can only do it to a certain extent.
For instance, Office and Merge endpoints will start respectively as many LibreOffice (unoconv) and PDTk instances as there are requests. The limitation here is the available memory and CPU usage.
On another hand, for the HTML, URL and Markdown endpoints, the API does only 6 conversions in parallel. Indeed, Google Chrome misbehaves if there are too many concurrent conversions.
The more concurrent requests, the more 504 HTTP codes the API will return.
See our load testing use case for more details about the API behaviour under heavy load.
You may increase the conversion timeout. In other words, you accept that a conversion takes more time if the API is under heavy load.
See timeout section.
The API being stateless, you may scale it as much as you want.
For instance, using the following Docker Compose file:
version: '3' services: # your others services gotenberg: image: thecodingmachine/gotenberg:6
You may now launch your services using:
$ docker-compose up --scale gotenberg=your_number_of_instances
When requesting the Gotenberg service with your client(s), Docker will automatically redirect a request to a Gotenberg container according to the round-robin strategy.
Gotenberg provides the endpoint /ping for checking the API availability with
a simple GET request.
Currently this endpoint does nothing special. A better way to monitor Gotenberg would be by checking the memory usage.
Also, as the API uses under the hood intricate programs, you should restart your Gotenberg instances from time to time to ensure a nominal behaviour.
By default, a handful of fonts are installed. Asian characters are also supported out of the box.
If you wish to use more fonts, you will have to create your own image:
FROM thecodingmachine/gotenberg:6 USER root RUN apt-get -y install yourfonts USER gotenberg