feat(Dockerfile): manage system time zone (#1465)

* displays timezone in debug information

* fixes cs

* fixes debug_test.go
This commit is contained in:
David
2026-02-13 16:59:23 +08:00
committed by GitHub
parent 1195c37508
commit 37757315d0
6 changed files with 133 additions and 0 deletions

View File

@@ -10,6 +10,7 @@ build: ## Build the Gotenberg's Docker image
-t $(DOCKER_REGISTRY)/$(DOCKER_REPOSITORY):$(GOTENBERG_VERSION) \ -t $(DOCKER_REGISTRY)/$(DOCKER_REPOSITORY):$(GOTENBERG_VERSION) \
-f $(DOCKERFILE) $(DOCKER_BUILD_CONTEXT) -f $(DOCKERFILE) $(DOCKER_BUILD_CONTEXT)
TZ=UTC
GOTENBERG_HIDE_BANNER=false GOTENBERG_HIDE_BANNER=false
GOTENBERG_GRACEFUL_SHUTDOWN_DURATION=30s GOTENBERG_GRACEFUL_SHUTDOWN_DURATION=30s
GOTENBERG_BUILD_DEBUG_DATA=true GOTENBERG_BUILD_DEBUG_DATA=true
@@ -86,6 +87,7 @@ run: ## Start a Gotenberg container
-p $(API_PORT):$(API_PORT) \ -p $(API_PORT):$(API_PORT) \
-e GOTENBERG_API_BASIC_AUTH_USERNAME=$(GOTENBERG_API_BASIC_AUTH_USERNAME) \ -e GOTENBERG_API_BASIC_AUTH_USERNAME=$(GOTENBERG_API_BASIC_AUTH_USERNAME) \
-e GOTENBERG_API_BASIC_AUTH_PASSWORD=$(GOTENBERG_API_BASIC_AUTH_PASSWORD) \ -e GOTENBERG_API_BASIC_AUTH_PASSWORD=$(GOTENBERG_API_BASIC_AUTH_PASSWORD) \
-e TZ=$(TZ) \
$(DOCKER_REGISTRY)/$(DOCKER_REPOSITORY):$(GOTENBERG_VERSION) \ $(DOCKER_REGISTRY)/$(DOCKER_REPOSITORY):$(GOTENBERG_VERSION) \
gotenberg \ gotenberg \
--gotenberg-hide-banner=$(GOTENBERG_HIDE_BANNER) \ --gotenberg-hide-banner=$(GOTENBERG_HIDE_BANNER) \

View File

@@ -79,6 +79,9 @@ RUN jlink \
# ---------------------------------------------- # ----------------------------------------------
FROM debian:13-slim AS base-image-stage FROM debian:13-slim AS base-image-stage
ARG TIMEZONE=UTC
ENV TZ=$TIMEZONE
COPY --from=custom-jre-stage /custom-jre /opt/java COPY --from=custom-jre-stage /custom-jre /opt/java
ENV PATH="/opt/java/bin:${PATH}" ENV PATH="/opt/java/bin:${PATH}"

View File

@@ -4,6 +4,7 @@ import (
"runtime" "runtime"
"sort" "sort"
"sync" "sync"
"time"
flag "github.com/spf13/pflag" flag "github.com/spf13/pflag"
) )
@@ -11,6 +12,7 @@ import (
// DebugInfo gathers data for debugging. // DebugInfo gathers data for debugging.
type DebugInfo struct { type DebugInfo struct {
Version string `json:"version"` Version string `json:"version"`
Timezone string `json:"timezone"`
Architecture string `json:"architecture"` Architecture string `json:"architecture"`
Modules []string `json:"modules"` Modules []string `json:"modules"`
ModulesAdditionalData map[string]map[string]interface{} `json:"modules_additional_data"` ModulesAdditionalData map[string]map[string]interface{} `json:"modules_additional_data"`
@@ -24,6 +26,7 @@ func BuildDebug(ctx *Context) {
debug = &DebugInfo{ debug = &DebugInfo{
Version: Version, Version: Version,
Timezone: time.Now().Location().String(),
Architecture: runtime.GOARCH, Architecture: runtime.GOARCH,
Modules: make([]string, len(ctx.moduleInstances)), Modules: make([]string, len(ctx.moduleInstances)),
ModulesAdditionalData: make(map[string]map[string]interface{}), ModulesAdditionalData: make(map[string]map[string]interface{}),

View File

@@ -13,6 +13,8 @@ func TestBuildDebug(t *testing.T) {
t.Errorf("Debug() should return empty debug data") t.Errorf("Debug() should return empty debug data")
} }
t.Setenv("TZ", "UTC")
fs := flag.NewFlagSet("gotenberg", flag.ExitOnError) fs := flag.NewFlagSet("gotenberg", flag.ExitOnError)
fs.String("foo", "bar", "Set foo") fs.String("foo", "bar", "Set foo")
ctx := NewContext(ParsedFlags{ ctx := NewContext(ParsedFlags{
@@ -51,6 +53,7 @@ func TestBuildDebug(t *testing.T) {
expect := DebugInfo{ expect := DebugInfo{
Version: Version, Version: Version,
Timezone: "UTC",
Architecture: runtime.GOARCH, Architecture: runtime.GOARCH,
Modules: []string{ Modules: []string{
"bar", "bar",

View File

@@ -16,6 +16,126 @@ Feature: /debug
""" """
{ {
"version": "{version}", "version": "{version}",
"timezone": "UTC",
"architecture": "ignore",
"modules": [
"api",
"chromium",
"exiftool",
"libreoffice",
"libreoffice-api",
"libreoffice-pdfengine",
"logging",
"pdfcpu",
"pdfengines",
"pdftk",
"prometheus",
"qpdf",
"webhook"
],
"modules_additional_data": {
"chromium": {
"version": "ignore"
},
"exiftool": {
"version": "ignore"
},
"libreoffice-api": {
"version": "ignore"
},
"pdfcpu": {
"version": "ignore"
},
"pdftk": {
"version": "ignore"
},
"qpdf": {
"version": "ignore"
}
},
"flags": {
"api-bind-ip": "",
"api-body-limit": "",
"api-disable-download-from": "false",
"api-disable-health-check-logging": "false",
"api-download-from-allow-list": "",
"api-download-from-deny-list": "",
"api-download-from-max-retry": "4",
"api-enable-basic-auth": "false",
"api-enable-debug-route": "true",
"api-port": "3000",
"api-port-from-env": "",
"api-root-path": "/",
"api-start-timeout": "30s",
"api-timeout": "30s",
"api-tls-cert-file": "",
"api-tls-key-file": "",
"api-trace-header": "Gotenberg-Trace",
"chromium-allow-file-access-from-files": "false",
"chromium-allow-insecure-localhost": "false",
"chromium-allow-list": "",
"chromium-auto-start": "false",
"chromium-clear-cache": "false",
"chromium-clear-cookies": "false",
"chromium-deny-list": "^file:(?!//\\/tmp/).*",
"chromium-disable-javascript": "false",
"chromium-disable-routes": "false",
"chromium-disable-web-security": "false",
"chromium-host-resolver-rules": "",
"chromium-ignore-certificate-errors": "false",
"chromium-incognito": "false",
"chromium-max-queue-size": "0",
"chromium-proxy-server": "",
"chromium-restart-after": "10",
"chromium-start-timeout": "20s",
"gotenberg-build-debug-data": "true",
"gotenberg-graceful-shutdown-duration": "30s",
"libreoffice-auto-start": "false",
"libreoffice-disable-routes": "false",
"libreoffice-max-queue-size": "0",
"libreoffice-restart-after": "10",
"libreoffice-start-timeout": "20s",
"log-fields-prefix": "",
"log-format": "auto",
"log-level": "info",
"pdfengines-convert-engines": "[libreoffice-pdfengine]",
"pdfengines-disable-routes": "false",
"pdfengines-engines": "[]",
"pdfengines-flatten-engines": "[qpdf]",
"pdfengines-merge-engines": "[qpdf,pdfcpu,pdftk]",
"pdfengines-read-metadata-engines": "[exiftool]",
"pdfengines-split-engines": "[pdfcpu,qpdf,pdftk]",
"pdfengines-write-metadata-engines": "[exiftool]",
"prometheus-collect-interval": "1s",
"prometheus-disable-collect": "false",
"prometheus-disable-route-logging": "false",
"prometheus-namespace": "gotenberg",
"prometheus-metrics-path": "/prometheus/metrics",
"webhook-allow-list": "",
"webhook-client-timeout": "30s",
"webhook-deny-list": "",
"webhook-disable": "false",
"webhook-error-allow-list": "",
"webhook-error-deny-list": "",
"webhook-max-retry": "4",
"webhook-retry-max-wait": "30s",
"webhook-retry-min-wait": "1s"
}
}
"""
Scenario: GET /debug (Environment based timezone)
Given I have a Gotenberg container with the following environment variable(s):
| API_ENABLE_DEBUG_ROUTE | true |
| TZ | America/New_York |
When I make a "GET" request to Gotenberg at the "/debug" endpoint
Then the response status code should be 200
Then the response header "Content-Type" should be "application/json"
Then the response body should match JSON:
"""
{
"version": "{version}",
"timezone": "America/New_York",
"architecture": "ignore", "architecture": "ignore",
"modules": [ "modules": [
"api", "api",
@@ -134,6 +254,7 @@ Feature: /debug
""" """
{ {
"version": "", "version": "",
"timezone": "",
"architecture": "", "architecture": "",
"modules": null, "modules": null,
"modules_additional_data": null, "modules_additional_data": null,

View File

@@ -8,6 +8,7 @@
</style> </style>
</head> </head>
<body> <body>
<span class="date"></span>
<span class="title"></span> <span class="title"></span>
</body> </body>
</html> </html>