I have a nextjs app and a dotnet8 app running in docker with one docker-compose file. Here are my files:
The nextjs/Dockerfile:
FROM node:20.15.0-alpine3.20 AS base
FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY --from=ext_path somefile somefile
COPY package*.json ./
RUN mkdir node_modules
RUN npm install --no-audit --omit=dev
RUN npm install sharp
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY --from=deps /app/.env.local ./.env.local
COPY . .
ENV NEXT_TELEMETRY_DISABLED 1
RUN npm run build
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
ENV NEXT_TELEMETRY_DISABLED 1
COPY --from=deps /app/.env.local ./.env.local
COPY --from=ext_path somefile somefile
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/next.config.mjs ./next.config.mjs
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
RUN mkdir -p ./public/v1/uploads
RUN chown nextjs:nodejs ./public/v1/uploads
USER nextjs
EXPOSE 80
ENV PORT 80
ENV HOSTNAME "0.0.0.0"
CMD ["node", "server.js"]
And the dotnet8/Dockerfile:
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine AS base
WORKDIR /app
EXPOSE 80
ENV ASPNETCORE_URLS=http://+:80
USER app
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build
ARG configuration=Release
COPY ["MyApp.sln", "MyApp.sln"]
COPY ["MyApp/MyApp.csproj", "MyApp/"]
RUN dotnet restore "MyApp.sln"
COPY MyApp/ MyApp/
WORKDIR "/MyApp"
FROM build AS publish
ARG configuration=Release
RUN dotnet publish "MyApp.csproj" -c $configuration -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyApp.dll"]
The production/docker.env file:
SRV_NAME=myproject
DOCKER_ENV=production
RUNTIME_ENV=production
WEB_EXPOSE_PORT=4000
API_EXPOSE_PORT=4100
UPLOAD_MOUNT_PATH=/var/lib/MyApp/web/public/v1/uploads
And finally the docker-compose.yml file:
networks:
default:
name: ${SRV_NAME}_default
external: false
infra:
name: infra
external: true
driver: bridge
services:
my-web:
container_name: ${SRV_NAME}-web
image: jd/my-web:latest
hostname: ${SRV_NAME}-web
depends_on:
- my-api
build:
context: ./nextjs
dockerfile: ./Dockerfile
network: host
args:
NODE_ENV: ${RUNTIME_ENV}
additional_contexts:
ext_path: ./${DOCKER_ENV}/ # This is just for reading some additional resources.
volumes:
- ${UPLOAD_MOUNT_PATH}:/app/public/v1/uploads:rw
environment:
- NODE_ENV=${RUNTIME_ENV}
ports:
- ${WEB_EXPOSE_PORT}:80
networks:
default:
infra:
my-api:
container_name: ${SRV_NAME}-api
image: jd/my-api:latest
hostname: ${SRV_NAME}-api
build:
context: ./dotnet8
dockerfile: ./MyApp/Dockerfile
volumes:
- ${UPLOAD_MOUNT_PATH}:/app/public/v1/uploads:rw
ports:
- ${API_EXPOSE_PORT}:80
networks:
default:
infra:
So, I’m trying to save an uploaded file from nextjs app. But I’m getting this error:
Error: EACCES: permission denied, open '/app/public/v1/uploads/639ceeac-65f3-4726-8a31-9e55e603ff9b.png'
at async open (node:internal/fs/promises:639:25)
at async writeFile (node:internal/fs/promises:1219:14)
at async c (/app/.next/server/chunks/106.js:1:21544)
at async /app/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:16:418
at async rP (/app/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:15:7978)
at async r9 (/app/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:18:1139)
at async doRender (/app/node_modules/next/dist/server/base-server.js:1438:30)
at async cacheEntry.responseCache.get.routeKind (/app/node_modules/next/dist/server/base-server.js:1599:28)
at async NextNodeServer.renderToResponseWithComponentsImpl (/app/node_modules/next/dist/server/base-server.js:1507:28)
at async NextNodeServer.renderPageComponent (/app/node_modules/next/dist/server/base-server.js:1931:24) {
errno: -13,
code: 'EACCES',
syscall: 'open',
path: '/app/public/v1/uploads/639ceeac-65f3-4726-8a31-9e55e603ff9b.png'
}
So have you any idea what’s wrong here? And how to solve the problem? Thanks in advance.