Deploying a Gutenberg instance with Docker
The Gutenberg project provides a Docker configuration to simplify the deployment on your server.
Dockerfile modifications
We intend to publish container images based on the Dockerfile in the future. If your use-case requires modifications
to the Dockerfile we encourage you to create an issue in the Gutenberg's
GitHub issue tracker. This way we can ensure that the published images
are suitable for customized setups.
Required images
Gutenberg requires configuring a PostgreSQL database, a Redis instance, and a CUPS server. All of them need to be accessible from the Django server and from the Celery worker. They can be deployed as Docker containers or as standalone instances. On top of that, three more containers are required to run Gutenberg: the Django backend server, the Celery worker for executing background tasks, and the Nginx proxy that routes incoming HTTP requests and serves static files.
In summary:
| Container name | Description |
|---|---|
gutenberg-db | PostgreSQL database for storing application data |
gutenberg-redis | Redis instance for caching and task queue |
gutenberg-backend | Django application server |
gutenberg-celery | Celery worker for background tasks |
gutenberg-proxy | Nginx for routing requests |
Configuration
To run Gutenberg in Docker, you need to create your own version of the settings:
cp backend/gutenberg/settings/docker_settings.py.example backend/gutenberg/settings/docker_settings.py
In docker_settings.py, fill in the following fields properly:
SECRET_KEY- unique random stringALLOWED_HOSTS- list of hosts that can connect to the appCSRF_TRUSTED_ORIGINS- list of trusted origins for CSRF protection
For example:
SECRET_KEY = 'n7+3u12_59wy_kzvecb^w^jrpi(m#(gl8^qe92kvclkd9!=-h)'
ALLOWED_HOSTS = ['127.0.0.1', 'localhost']
CSRF_TRUSTED_ORIGINS = [
'http://127.0.0.1:3000',
'http://localhost:3000',
]
After saving the file, you can run all the containers with:
docker compose up --build
docker-compose.yml
The docker-compose.yml file provides an example Docker Compose configuration, which references the local Dockerfile
to build the required Docker images. You might need to modify it to fit your deployment.
Two secrets need to be provided for Docker Compose: gutenberg_postgres_password and
gutenberg_django_secret_key. They should be randomly generated strings and should be kept secret.
Please make sure to never commit them in a Git repository. The openssl command can be used
to generate the secrets:
# Create a secrets directory with a `.gitignore` file
mkdir -p secrets
printf "# Avoid publishing any secrets stored in this folder\n*\n" > secrets/.gitignore
# Generate the secrets
openssl rand -base64 32 > ./secrets/postgres_password.txt
openssl rand -base64 32 > ./secrets/django_secret_key.txt
Creating a superuser account
After starting all Docker containers, the command below can be used to create a superuser account.
gutenberg-backend is the name of the container running the Django server.
docker exec -it gutenberg-backend ./manage.py createsuperuser
NGINX config files
The run_nginx target describes an NGINX Docker image with configuration required for running Gutenberg itself.
The default configuration file for NGINX, /etc/nginx/nginx.conf contains
an include directive:
http {
# ...
include /etc/nginx/conf.d/*.conf```
#...
}
Gutenberg adds a single file in the conf.d directory: /etc/nginx/conf.d/gutenberg.conf.
It defines an HTTP server which contains another include directive:
server {
# ...
include /etc/nginx/gutenberg-locations.d/*.conf;
# ...
}
The files in the gutenberg-locations.d define location
directives for different endpoints which will be available under the Gutenberg domain.
Gutenberg adds two files to this folder:
gutenberg-app.confwhich defines the handlers for the endpoints/static/,/@webapp-html/for internal use and a catch-alllocation /directive which proxies all requests to the Django application server.gutenberg-docs.confwhich defines the handlers for the/docs/endpoint which serves the mdbook documentation.
Extending the NGINX configuration
You can make use of the include directives described above to extend Gutenberg's default NGINX image with your own
config.
As an example, this is how you would add a custom /myapp/ endpoint proxied to https://example.com/myapp/:
Create a new file myapp.conf with the contents:
location /myapp/ {
proxy_pass https://example.com/myapp/;
}
And your own Dockerfile with:
# Put the name Gutenberg's default NGINX image here:
FROM run_nginx
COPY path/to/myapp.conf /etc/nginx/gutenberg-locations.d/myapp.conf
Configuring CUPS access
The CUPS_SERVERNAME setting controls how Gutenberg connects to CUPS.
It can be a path to a CUPS socket file, an IP address, or a hostname.
It will be used as the -f argument to commands provided by cups-client
(lp, cancel, etc.).
To use the CUPS server running on the host machine, you can mount the
/run/cups directory from the host machine to the Docker containers for
the backend and the Celery worker. The example docker-compose.yml file
does this. The CUPS_SERVERNAME can then be set to /run/cups/cups.sock.
warning
Docker Desktop might not allow mounting any files from the /run directory,
even if it is listed in Resources > File sharing > Virtual file shares.
Failing to bind the /run/cups/cups.sock socket will not result in an error,
Docker will silently create a new directory in that path.
This issue might be hard to overcome when using Docker Desktop, so we recommend installing the Docker engine directly.
CUPS performs permission checking when accessing CUPS via the socket file.
It requires the name and UID of the system user calling the lp command
in the Docker container to match a user on the host machine.
The run_backend and run_celery targets in the Dockerfile use the
GUTENBERG_USERNAME, GUTENBERG_UID, and GUTENBERG_GID environment
variables to set the username, UID, and GID of the user in the Docker
container. If they are not specified, the default username
gutenberg-docker is used and the UID and GID are set to 659.
The same group and user need to be created on the host machine. This can be achieved using the commands:
sudo groupadd --system --gid 659 gutenberg-docker
sudo useradd --system --groups lp,lpadmin gutenberg-docker --uid 659 --gid 659
tip
If the Gutenberg user is not configured correctly, attempting to print a document might result in an error like:
lp: Unauthorized
In such cases it can be helpful to inspect the host's CUPS server error logs:
less +G /var/log/cups/error_log