Post

The Dockerfile Mistake That Broke CSV Exports in Our Production App!

The Dockerfile Mistake That Broke CSV Exports in Our Production App!

🚀 The Incident

It was a normal day—until a user reported an issue. They were trying to export a report, but instead of downloading a CSV, they got this error:

1
2
3
4
5
6
{
  "errors": [
    { "errorCode": "EACCES: permission denied" },
    { "errorReason": "mkdir './csv_exports/'" }
  ]
}

At first glance, it seemed like a basic permission issue. But when I dug deeper, I realized my recent Dockerfile changes were the culprit.

When a user exports a CSV, the app first writes it inside the pod(container) before uploading it to the cloud. These Dockerfile changes broke write permissions, causing the failure

Facepalm Baby GIF


🔍 The Root Cause

I had recently improved our Docker security by switching from running the container as root to a non-root user (app). My initial Dockerfile looked like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
FROM node:18-slim AS client

WORKDIR /webapp/

COPY . .

RUN npm i 

FROM node:18-slim

RUN groupadd app-group && \
    useradd -g app-group -s /bin/bash -m app

WORKDIR /webapp

COPY --chown=app:app-group --from=client /webapp /webapp

USER app

Looks fine, right? Wrong.

The issue?

I had changed the ownership of /webapp inside the multi-stage build using --chown=app:app-group.
However, only the subdirectories inside /webapp got updated, while the parent /webapp folder was still owned by root.

When the app tried to create the csv_exports/ directory inside /webapp/, it failed due to permission errors. 🚨

Essentially, my non-root app user could read everything, but couldn’t write to the necessary directory.

Before

Tired to perform mkdir command in container

Before-1

đź›  The Fix

After debugging inside the container using ls -ld /webapp, I realized I needed to change ownership of the entire /webapp directory before switching to app.

âś… Corrected Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
FROM node:18-slim AS client

WORKDIR /webapp/

COPY . .

RUN npm i 

FROM node:18-slim

RUN groupadd app-group && \
    useradd -g app-group -s /bin/bash -m app

WORKDIR /webapp

RUN mkdir -p /webapp && chown -R app:app-group /webapp

COPY --chown=app:app-group --from=client /webapp /webapp

USER app

🔑 Key Fixes:

  • Created /webapp explicitly and changed its ownership using chown -R app:app-group /webapp.
  • Ensured the entire directory, including its parent, was owned by the correct user before switching.
  • Verified permissions inside the running container with ls -ld /webapp.

After

Successfully able to perform mkdir commands

After-1

After fixing the issue and seeing the CSV export finally work, I felt like I just won a championship! 🏆

Facepalm Baby GIF

đź“Ś Lessons Learned

  • Multi-stage builds --chown don’t always apply to parent directories.
  • Manually setting directory ownership inside Dockerfiles is a must when switching from root to a non-root user.
  • Debug inside the container using ls -l and ls -ld /parentfolder to verify ownership before deploying.

🚀 The Takeaway

If you’re switching to a non-root user in Docker, double-check folder ownership—especially for write-heavy operations like file exports!
This small mistake cost us valuable debugging time, but now it’s a lesson learned.

This post is licensed under CC BY 4.0 by the author.