skip to Main Content

UPDATED

Next to the src folder, I created another folder called public and placed an image file inside this folder. I modified the main.ts file like this:

1) app.useStaticAssets(join(__dirname, '..', 'public'));

2) app.useStaticAssets(join(__dirname, '/../public')); 

3) app.useStaticAssets(join(__dirname, '..', 'public'), {
    index: false,
    prefix: '/public/',
});

The image file is named pic.png and my project is accessible at the following Docker address:

192.168.1.102

testing a simpleurl and api:

http://192.168.1.102/api/test

response:

{"response":"200"}

enter image description here

For this project, a prefix is defined as follows:

app.setGlobalPrefix('api');

Now when I try to display the image file with the following address, it gives a 404 error and I couldn’t solve it:

1) http://192.168.1.102/pic.png
2) http://192.168.1.102/public/pic.png

Error:

1) {"message":"Cannot GET /pic.png","error":"Not Found","statusCode":404}
2) {"message":"Cannot GET /public/pic.png","error":"Not Found","statusCode":404}

The entire main.ts file looks like this:

import {NestFactory} from '@nestjs/core';
import {AppModule} from './modules/app/app.module';
import {ValidationPipe} from '@nestjs/common';
import {ConfigService} from '@nestjs/config';

import {FreezePipe} from "./common/pipes/freeze-pipe";
import {HttpExceptionFilter} from "./common/filters/http-exception.filter";
import { join } from 'path';
import { NestExpressApplication } from '@nestjs/platform-express';

async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);

const allowedOrigins: string[] = [
'http://192.168.1.102'
];


app.useStaticAssets(join(__dirname, '..', 'public'));

/*app.useStaticAssets(join(__dirname, '/../public')); 

app.useStaticAssets(join(__dirname, '..', 'public'), {
    index: false,
    prefix: '/public/',
});*/

app.setGlobalPrefix('api');

const configService = app.get(ConfigService);

app.enableCors({
    origin: (origin, callback) => {
        if (allowedOrigins.indexOf(origin) !== -1 || !origin) {
            callback(null, true);
        } else {
            callback(new Error('Not allowed by CORS'));
        }
    },
    optionsSuccessStatus: 200,
    credentials: true,
});
await app.listen(3000);
}

bootstrap().then(r => console.log('... SERVER STARTED NOW ...'));

docker-compose.yaml content:

networks:
  host:
    name: myapp
    external: true
  lan_access:
    driver: bridge

services:
  myapp:
    build:
      context: .
      dockerfile: src/modules/app/Dockerfile
      target: development
    command: npm run start:dev myapp
    env_file:
      - .env
    volumes:
      - .:/usr/src/app
      - /usr/src/app/node_modules
    networks:
      - default
    depends_on:
      - database
      - redis
    ports:
      - '80:3000'

  redis:
    image: redis
    restart: always
    command: /bin/sh -c "redis-server --requirepass $$REDIS_PASSWORD"
    env_file:
      - .env
    ports:
      - 6379:6379
    environment:
      - ALLOW_EMPTY_PASSWORD=yes
    volumes:
      - ./redis/data:/data

  database:
    image: mysql:latest
    restart: always
    command: --default-authentication-plugin=mysql_native_password
    env_file:
      - .env
    environment:
      MYSQL_HOST: 'database'
      MYSQL_DATABASE: 'myapp'
      MYSQL_PASSWORD: 'root'
      MYSQL_ROOT_PASSWORD: 'root'
    ports:
      - '3306:3306'
    expose:
      - '3306'
    volumes:
      - myapp-db:/var/lib/mysql

  phpmyadmin:
    image: phpmyadmin:latest
    restart: always
    ports:
      - 8080:80
    environment:
      - PMA_ARBITRARY=1
volumes:
  myapp-db:

and Dockerfile:

# Development stage
FROM node:alpine As development

WORKDIR /usr/src/app

COPY package*.json ./
# COPY prisma ../../prisma/

RUN npm install -g pnpm
RUN pnpm install --save

COPY ../.. .
COPY ../../../sysctl.conf /etc/sysctl.d/

RUN pnpm run build

# Production stage
FROM node:alpine as production

ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}

WORKDIR /usr/src/app

COPY package*.json ./
# COPY prisma ../../prisma/

RUN pnpm install -g pnpm
RUN pnpm install --only=production

COPY ../.. .
COPY ../../../sysctl.conf /etc/sysctl.d/

COPY --from=development /usr/src/app/dist ./dist
COPY --chown=node:node --from=builder /usr/src/app/prisma /prisma


CMD ["node", "dist/src/myapp/main"]

2

Answers


  1. In your configuration, you set the prefix for your public assets as public. However, you are trying to access them as /uploads.

    So, if you do not want to change your main.ts file, you should access http://192.168.1.102/public/pic.png and it should work.

    If you want to have uploads in your URL, you can modify the configuration to:

    app.useStaticAssets(path.join(__dirname, '..', 'public'), {
      index: false,
      prefix: '/uploads',
    });
    

    And now, http://192.168.1.102/uploads/pic.png should work.

    Side note:

    You need to cast app to the correct type to get correct typing in typescript.

    const app = await NestFactory.create<NestExpressApplication>(AppModule);
    
    Login or Signup to reply.
  2. For me removing the '..' string works, seems like i was basically setting a path at app/public instead of app/dist/public

    so this is what i did:

    app.useStaticAssets(join(__dirname, 'public'), {
        index: false,
        prefix: '/public/',
    }); 
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search