Skip to main content

Command Palette

Search for a command to run...

Fixing Frozen Timestamps in Docker & Spring: A Lesson in Bean Lifecycle

Updated
2 min read

The Issue


I discovered a bug where the dates in the user activity stream tab—which summarizes the last three days of activity—were stuck at the exact time the Docker container was started.

Troubleshooting


Attempt 1: Syncing Container Time with Local Server Time

Initially, I tried to synchronize the container's localtime with the host server's localtime. When the issue occurred, I ran the date command on the server, and it correctly displayed KST. However, the time inside the container was still being output in UTC. My Docker Compose configuration was set to mount /etc/localtime:/etc/localtime.

Attempt 2: Syncing via Timezone File

After some research, I found feedback suggesting that syncing via /etc/timezone is often more reliable than using /etc/localtime. I applied this change immediately, but the container output remained in UTC.

Attempt 3: Installing tzdata in the Dockerfile

To ensure the container could handle time dynamically, I modified the Dockerfile to install the tzdata package. I configured it to copy the zoneinfo of the desired timezone to the container's /etc/localtime and overwrite /etc/timezone with the specific TZ value.

Dockerfile

ENV TZ=Asia/Seoul
RUN apk add --no-cache tzdata && \
    cp /usr/share/zoneinfo/$TZ /etc/localtime && \
    echo $TZ > /etc/timezone

After starting the container with this new image, the internal system time finally matched the server time.

Re-evaluating the Root Cause


Despite fixing the system time, the API was still returning a fixed timestamp. I kept wondering, "How can LocalDateTime, which is supposed to fetch the system time, be a constant value?"

The fact that even the nanoseconds were identical was the smoking gun. It suddenly dawned on me: when defining a DateUtil class for global use, I had declared the date variables as static final.

Feeling a bit foolish, I removed the final keywords and tried registering the class as a Spring @Component (Bean). But of course, the value was still fixed—the instance variable held the value initialized when the singleton bean was first created. It was a lapse in judgment during debugging. After some self-reflection, I refactored the code to either use a standard class or initialize the time at the exact point of execution.

After running all test cases and deploying to the dev server, I confirmed the API works perfectly.

Retrospective


I'm documenting this to remind myself to be more deliberate during development. Following the recent login issue, I really need to break the habit of reflexively registering everything as a Bean without considering its lifecycle.