skip to Main Content

I’m trying to run NestJS app inside a container on VM on Google Cloud via GitHub Actions.

Locally everything is running correctly, however on VM I receive below permission errors:

error TS5033: Could not write file '/usr/src/app/dist/users/enums/role.enum.js': EACCES: permission denied, mkdir '/usr/src/app/dist'.

error TS5033: Could not write file '/usr/src/app/dist/users/enums/role.enum.js.map': EACCES: permission denied, mkdir '/usr/src/app/dist'.

error TS5033: Could not write file '/usr/src/app/dist/users/users.module.d.ts': EACCES: permission denied, mkdir '/usr/src/app/dist'.

error TS5033: Could not write file '/usr/src/app/dist/users/users.module.js': EACCES: permission denied, mkdir '/usr/src/app/dist'.

error TS5033: Could not write file '/usr/src/app/dist/users/users.module.js.map': EACCES: permission denied, mkdir '/usr/src/app/dist'.

error TS5033: Could not write file '/usr/src/app/dist/users/users.resolver.d.ts': EACCES: permission denied, mkdir '/usr/src/app/dist'.

error TS5033: Could not write file '/usr/src/app/dist/users/users.resolver.js': EACCES: permission denied, mkdir '/usr/src/app/dist'.

error TS5033: Could not write file '/usr/src/app/dist/users/users.resolver.js.map': EACCES: permission denied, mkdir '/usr/src/app/dist'.

error TS5033: Could not write file '/usr/src/app/dist/users/users.service.d.ts': EACCES: permission denied, mkdir '/usr/src/app/dist'.

error TS5033: Could not write file '/usr/src/app/dist/users/users.service.js': EACCES: permission denied, mkdir '/usr/src/app/dist'.

error TS5033: Could not write file '/usr/src/app/dist/users/users.service.js.map': EACCES: permission denied, mkdir '/usr/src/app/dist'.

[6:19:10 PM] Found 154 errors. Watching for file changes.

My Dockerfile:

###################
# BUILD FOR LOCAL DEVELOPMENT
###################

FROM node:18 As development

WORKDIR /usr/src/app

COPY --chown=node:node package*.json ./

RUN npm ci

COPY --chown=node:node . .

USER node

###################
# BUILD FOR PRODUCTION
###################

FROM node:18 As build

WORKDIR /usr/src/app

COPY --chown=node:node package*.json ./

COPY --chown=node:node --from=development /usr/src/app/node_modules ./node_modules

COPY --chown=node:node . .

RUN npm run build

ENV NODE_ENV production

RUN npm ci --only=production && npm cache clean --force

USER node

###################
# PRODUCTION
###################

FROM node:18 As production

COPY --chown=node:node --from=build /usr/src/app/node_modules ./node_modules
COPY --chown=node:node --from=build /usr/src/app/dist ./dist

CMD [ "node", "dist/main.js" ]

docker-compose:

services:
  api:
    restart: always
    build:
      dockerfile: Dockerfile
      context: .
      target: development
    env_file:
    - .env
    command: npm run start:dev
    ports:
      - 3000:3000
    depends_on:
      - postgres

  postgres:
    image: postgres
    restart: always
    ports:
      - "5435:5432"
    environment:
      POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
      
  pgadmin:
    image: dpage/pgadmin4
    restart: always
    container_name: pgadmin4
    environment:
      - PGADMIN_DEFAULT_EMAIL=${PGADMIN_DEFAULT_EMAIL}
      - PGADMIN_DEFAULT_PASSWORD=${PGADMIN_DEFAULT_PASSWORD}
    ports:
      - '5050:80'
    depends_on:
      - postgres
  
  redis:
    image: redis
    ports:
      - "6379:6379"
    restart: always
    environment:
      - REDIS_PASSWORD=${REDIS_PASSWORD}
    command: redis-server --requirepass ${REDIS_PASSWORD}

CI:

name: deployment

on:
  push:
    branches: [ "test" ]
  pull_request:
    branches: [ "test" ]

jobs:

  deploy:

    runs-on: self-hosted

    steps:
    - name: Clone repository 
      uses: actions/checkout@v4
      with:
        ref: ${{ github.event.pull_request.head.ref }}
    - run: echo "🖥️ The workflow is now ready to test your code on the runner."
    - name: List files in the repository
      run: |
        ls ${{ github.workspace }}
    - run: cp .env.example .env
    - run: npm install
    - name: deploy
      run: docker compose -f ci.docker-compose.yml up --detach --force-recreate

As you can see I’m using only development part from the Dockerfile.

I was using different statements in Dockerfile and docker-compose: chown, mkdir dist, etc., however unsuccessfully.

Edit:
I restructured Dockerfile:

FROM node:18

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

RUN npm run build

EXPOSE 3000

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

and docker compose:

services:
  api:
    build:
      dockerfile: Dockerfile
      context: .
    restart: always
    ports:
      - '3000:3000'
    env_file:
      - .env
    depends_on:
      - postgres
    volumes:
      - .:/app/src

  postgres:
    image: postgres
    restart: always
    ports:
      - "5432:5432"
    environment:
      POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
      
  pgadmin:
    image: dpage/pgadmin4
    restart: always
    container_name: pgadmin4
    environment:
      - PGADMIN_DEFAULT_EMAIL=${PGADMIN_DEFAULT_EMAIL}
      - PGADMIN_DEFAULT_PASSWORD=${PGADMIN_DEFAULT_PASSWORD}
    ports:
      - '5050:80'
    depends_on:
      - postgres
  
  redis:
    image: redis
    ports:
      - "6379:6379"
    restart: always
    environment:
      - REDIS_PASSWORD=${REDIS_PASSWORD}
    command: redis-server --requirepass ${REDIS_PASSWORD}

I don’t know what was wrong with previous configuration, but works alright with this one.

2

Answers


  1. try this, I hope it works.
    check your dist directory’s owner, if it was root change it to non-root user $USER or delete your directory and rebuild it without sudo permission.

    Login or Signup to reply.
  2. I guess this is because user "node" does not have the permission to mkdir "dist" and modify files in it.

    If I were you, I will connect to the container’s file system and check the owner. This is the most reliable way to find the real reason.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search