79716238

Date: 2025-07-27 08:08:37
Score: 1.5
Natty:
Report link

I have fixed this issue, but @Hans Killian has answered, i want to extend on his answer:

1. Secrets in docker containers are supposed to be stored in a root path inside a the directories run/secret, meaning it should not be in any other local directory (in my case it was /app )

2. The environment variable PROD is set to 1 inside the multi-container file compose.yml , however, i believe this set the PROD in runtime and not build time.

Here is the final version of the image Dockerfile



# First Stage is used to install the dependencies from the host machine app to the image /app directory
FROM node:22-alpine AS initiate
ENV PROD = '1'
# set the environment variable PROD to 1, which is used to determine if the app is

# set the working directory in the container to /app
WORKDIR /app
# copy package.json from the host machine to the /app directory in the image
COPY package*.json ./

RUN --mount=type=secret,id=CONNECTION_STRING \
    --mount=type=secret,id=EMAIL_SERVER_HOST \
    --mount=type=secret,id=EMAIL_SERVER_USER \
    --mount=type=secret,id=EMAIL_SERVER_PASSWORD \
    --mount=type=secret,id=EMAIL_SERVER_PORT \
    --mount=type=secret,id=EMAIL_FROM \
     --mount=type=secret,id=NEXTAUTH_URL \
    --mount=type=secret,id=NEXTAUTH_SECRET \
    export CONNECTION_STRING="$(cat /run/secrets/CONNECTION_STRING)" && \
    export EMAIL_SERVER_HOST="$(cat /run/secrets/EMAIL_SERVER_HOST)" && \
    export EMAIL_SERVER_USER="$(cat /run/secrets/EMAIL_SERVER_USER)" && \
    export EMAIL_SERVER_PASSWORD="$(cat /run/secrets/EMAIL_SERVER_PASSWORD)" && \
    export EMAIL_FROM="$(cat /run/secrets/EMAIL_FROM)" && \
    export NEXTAUTH_URL="$(cat /run/secrets/NEXTAUTH_URL)" && \
    export EMAIL_SERVER_PORT="$(cat /run/secrets/EMAIL_SERVER_PORT)" && \
    export NEXTAUTH_SECRET="$(cat /run/secrets/NEXTAUTH_SECRET)" && \
    npm ci




# 2nd Stage is used to build the app
FROM initiate AS build
COPY --from=initiate /app/node_modules ./node_modules
COPY . .
# copy the rest of application from the host machine to the /app directory in the image to build the app
RUN --mount=type=secret,id=CONNECTION_STRING \
    --mount=type=secret,id=EMAIL_SERVER_HOST \
    --mount=type=secret,id=EMAIL_SERVER_USER \
    --mount=type=secret,id=EMAIL_SERVER_PASSWORD \
    --mount=type=secret,id=EMAIL_SERVER_PORT \
    --mount=type=secret,id=EMAIL_FROM \
    --mount=type=secret,id=NEXTAUTH_URL \
    --mount=type=secret,id=NEXTAUTH_SECRET \
    export CONNECTION_STRING="$(cat /run/secrets/CONNECTION_STRING)" && \
    export EMAIL_SERVER_HOST="$(cat /run/secrets/EMAIL_SERVER_HOST)" && \
    export EMAIL_SERVER_USER="$(cat /run/secrets/EMAIL_SERVER_USER)" && \
    export EMAIL_SERVER_PASSWORD="$(cat /run/secrets/EMAIL_SERVER_PASSWORD)" && \
    export EMAIL_FROM="$(cat /run/secrets/EMAIL_FROM)" && \
    export NEXTAUTH_URL="$(cat /run/secrets/NEXTAUTH_URL)" && \
    export NEXTAUTH_SECRET="$(cat /run/secrets/NEXTAUTH_SECRET)" && \
    export EMAIL_SERVER_PORT="$(cat /run/secrets/EMAIL_SERVER_PORT)" && \
    npm run build


# 3rd Stage is used to run the app
FROM initiate AS run

RUN addgroup --system --gid 1001 nonroot
RUN adduser --system --uid 1001 runner
# Create a non-root user to run the app and assign it to the nonroot group
USER runner
# Switch to the user runner

COPY --from=build /app/public ./public
COPY --from=build --chown=runner:nonroot /app/.next/standalone ./
COPY --from=build --chown=runner:nonroot /app/.next/static ./.next/static

EXPOSE 3000

CMD ["npm","run","start"]

# finally, run the app in production mode

here is how I set the secrets inside my app:

const getVars = async ()=>{
  if((process!.env!.PROD!)=='0'){
    return {
      host: process.env!.EMAIL_SERVER_HOST!,
      port: process.env!.EMAIL_SERVER_PORT!,
      user: process.env!.EMAIL_SERVER_USER!,
      pass: process.env!.EMAIL_SERVER_PASSWORD!,
      from:process.env!.EMAIL_FROM!

    }
  }
return{
   host: await readFile('/run/secrets/EMAIL_SERVER_HOST',{encoding:'utf-8'}),
  port: await readFile('/run/secrets/EMAIL_SERVER_PORT',{encoding:'utf-8'}),
  user:await readFile('/run/secrets/EMAIL_SERVER_USER',{encoding:'utf-8'}),
  pass:await readFile('/run/secrets/EMAIL_SERVER_PASSWORD',{encoding:'utf-8'}),
  from:await readFile('/run/secrets/EMAIL_FROM',{encoding:'utf-8'}) as unknown as string
}
  
}

as you see the paths provided as arguments to readFile API started with /, meaning it is an absolute path to the container root, that where secrets are stored.

Reasons:
  • RegEx Blacklisted phrase (1): i want
  • Long answer (-1):
  • Has code block (-0.5):
  • User mentioned (1): @Hans
  • Self-answer (0.5):
  • Low reputation (0.5):
Posted by: Ghazi