Skip to content

feat: add tzdata to Docker container #871

Description

@avoidwork

Summary

Add tzdata (timezone data) to the Docker container to ensure correct timezone handling for scheduled tasks, logs, and system processes.

Motivation

Minimal Docker base images (Alpine, slim variants) ship without timezone data. Without tzdata, the container defaults to UTC, which causes:

  • Incorrect timestamps in logs for non-UTC users
  • Misaligned cron schedules in the scheduler
  • Confusing behavior when users expect local time

Proposed Solution

  1. Install tzdata in the Dockerfile's package installation step
  2. Set a default TZ environment variable (e.g., America/Toronto for the Ottawa-based project)
  3. Allow runtime override via docker run -e TZ

Dockerfile changes:

# Alpine-based:
RUN apk add --no-cache tzdata
ENV TZ=America/Toronto

# Debian-based (if applicable):
# RUN apt-get update && apt-get install -y tzdata && rm -rf /var/lib/apt/lists/*
# ENV TZ=America/Toronto

Alternatives Considered

  • Copy /usr/share/zoneinfo manually — adds image size without value; tzdata package is the standard approach
  • Use Node.js Intl timezone support only — insufficient for system-level tools (cron, logs, scheduler)

OpenSpec Note

This project uses OpenSpec for feature development. If this request is approved, I will:

  1. Run /opsx:propose to generate a full proposal with specs and tasks
  2. Iterate on the design before any code is written
  3. Follow the task-driven implementation workflow

Additional Context

  • OS: Linux 7.0.14-12-pve
  • Node.js: v25.8.1
  • madz version: 1.52.0

Audit Findings (for Issue #871)

  • Dockerfile:20 — Alpine package install line: apk add --no-cache python3 ruby curl bash jq unzip wget ca-certificates git github-cli file zip xz lz4 diffutils tree rsync openssh-server openssh-client cronie ripgrep. tzdata needs to be added here.
  • Dockerfile — No ENV TZ is set anywhere. The container will default to UTC.
  • docker-entrypoint.sh — No timezone configuration or TZ env var handling found. Worth checking if the entrypoint sets or respects TZ.

Fix Steps

  1. Add tzdata to the Dockerfile — Append tzdata to the apk add line on line 20 of Dockerfile:

    RUN apk update && \
        apk add --no-cache python3 ruby curl bash jq unzip wget ca-certificates git github-cli file zip xz lz4 diffutils tree rsync openssh-server openssh-client cronie ripgrep tzdata && \
  2. Set the TZ environment variable — Add ENV TZ=America/Toronto after the ENV HOME=/home/madz line (around line 31), so the default timezone matches the project's Ottawa location. Allow runtime override via docker run -e TZ.

  3. Verify the entrypoint — Check docker-entrypoint.sh to confirm it doesn't override TZ and that the container respects the env var at runtime.

  4. Test the build — Run npm run docker:release:all (or the equivalent Docker build command) and verify the resulting image has timezone data:

    docker run --rm <image> date
    docker run --rm -e TZ=America/New_York <image> date
  5. Verify — Run npm run test and npm run coverage to confirm no regressions.

Updated Fix Steps

  1. Add tzdata to the Dockerfile — Append tzdata to the apk add line on line 20 of Dockerfile:

    RUN apk update && \
        apk add --no-cache python3 ruby curl bash jq unzip wget ca-certificates git github-cli file zip xz lz4 diffutils tree rsync openssh-server openssh-client cronie ripgrep tzdata && \
  2. Remove hardcoded TZ (if any) — Do NOT set ENV TZ=... in the Dockerfile. Let the container default to UTC, which is the Linux standard.

  3. Document the override — Add a note in the README or docker-compose example showing how to override:

    docker run -e TZ=America/Toronto madz:latest
  4. Verify the entrypoint — Check docker-entrypoint.sh to confirm it doesn't override TZ and that the container respects the env var at runtime.

  5. Test the build — Run the Docker build and verify timezone handling:

    docker run --rm <image> date           # Should show UTC
    docker run --rm -e TZ=America/Toronto <image> date  # Should show EDT/EST
  6. Verify — Run npm run test and npm run coverage to confirm no regressions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions