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
🔍 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.
Tired to perform mkdir command in container
đź› 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 usingchown -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
.
Successfully able to perform mkdir commands
After fixing the issue and seeing the CSV export finally work, I felt like I just won a championship! 🏆
đź“Ś 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
andls -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.