Next.JS app in ECS does not load env variables nor credentials

253 Views Asked by At

I am migrating from Vercel to AWS, and I'm trying to run my app with ECS using ECR. The problem es that the environment variables defined in the ECS are not found in runtime, and if I run a query to an AWS Service, it doesn't recognize the role neither. If I set the environment variables in the github actions workflow and include RUN printenv > .env.production before the RUN npm run build in my Dockerfile, it does find the environment variables, and of course I do not like the solution.

My Dockerfile is something like this:

FROM node:18-alpine AS base

FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app

COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
  if [ -f package-lock.json ]; then npm ci; \
  elif [ -f yarn.lock ]; then yarn --frozen-lockfile; \
  elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \
  else echo "Lockfile not found." && exit 1; \
  fi

FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

ARG NODE_ENV
ENV NODE_ENV=${NODE_ENV}
ENV NEXT_TELEMETRY_DISABLED 1

RUN printenv > .env.production

RUN npm run build

FROM base AS runner
WORKDIR /app

RUN apk add --no-cache curl

ENV NODE_ENV production
ENV NEXT_TELEMETRY_DISABLED 1

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

COPY --from=builder /app/public ./public

# Set the correct permission for prerender cache
RUN mkdir .next
RUN chown nextjs:nodejs .next

# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 3000

ENV PORT 3000

CMD ["node", "server.js"]

This solves the environment variables problem, but I couldn't find a solution for the permissions, as of course I don't want to add the access keys in this way. The error is "Could not load credentials from any providers", so is not a problem that the policy does not have a permission, it does not inherit the role from the ECS.

1

There are 1 best solutions below

0
Motomine On BEST ANSWER

After a few tries, I found out that my problem was because the nextjs output was set as standalone as nextjs documentaciones recommends. But this is for apps that are 100% statics, in my case where I use environments that are configured in ECS or where I have api routes that need to use the assume role it was useless.

I had to remove the output from next.config.js, and add more files / folders in my Dockerfile so they are copied to the container in ECR. My Dockerfile ended up looking something like this:

COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
  if [ -f package-lock.json ]; then npm ci; \
  elif [ -f yarn.lock ]; then yarn --frozen-lockfile; \
  elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \
  else echo "Lockfile not found." && exit 1; \
  fi

FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
COPY package*.json ./

ARG NODE_ENV
ENV NODE_ENV=${NODE_ENV}
ENV NEXT_TELEMETRY_DISABLED 1

RUN yarn install

RUN yarn build

FROM base AS runner
WORKDIR /app

RUN apk add --no-cache curl

ENV NODE_ENV production
ENV NEXT_TELEMETRY_DISABLED 1

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

COPY --from=builder /app/public ./public

RUN mkdir .next
RUN chown nextjs:nodejs .next

#Copy all necessary files for runtime, including configurations
COPY --from=builder --chown=nextjs:nodejs /app/next.config.js ./next.config.js
COPY --from=builder --chown=nextjs:nodejs /app/utils ./utils
COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next
COPY --from=builder --chown=nextjs:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=nextjs:nodejs /app/package.json ./package.json

USER nextjs

EXPOSE 3000

ENV PORT 3000

CMD ["yarn", "start"]