I have a svelte app running on my production instance, but when I access it I see a blanc HTML page. On my console I get the following error:
Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.
I have looked into other answers and google the problem but I couldn't find any solution that worked for me.
My app's pretty straightforward and it uses vite and svelte-routing.
To deploy I'm using docker-compose.
My Dockerfile:
FROM --platform=linux/amd64 node:16 as build
WORKDIR /app
COPY package.json ./
COPY package-lock.json ./
RUN npm install
COPY . ./
RUN npm run build
FROM nginx:1.19-alpine
COPY --from=build /app/dist /usr/share/nginx/html
My docker compose file (on my server):
version: '3.7'
services:
webapp-production:
image: "me/image:latest"
ports: [ "5000:80" ]
restart: "on-failure"
My default.conf (Nginx installed on the server):
server {
server_name example.com www.example.com;
location / {
proxy_pass http://localhost:5000;
include /etc/Nginx/conf.d/includes/proxy-vars.conf;
try_files $uri /index.html;
}
}
EDIT: Sometimes when I Empty cache and hard reload the app loads normally.
Thank you all in advance!
Related
I've got a Python web app that runs inside two Docker containers, one for the FastAPI backend, the other for the Vue.JS front-end (and there's besides a third one, with the Postgres Db). Now my task is to upload a file from inside the front-end client to the server, store it permanently and serve, so that I can use static URLs in my img tags.
A possible similar question is here: How to upload file outside Docker container in Flask app But it concerns an approach where the server must be restarted upon upload to reflect the changes. I need to do everything on the fly, as the app is running.
Dockerfile for front-end:
FROM node:16.14.2 as builder
WORKDIR /admin
COPY package*.json ./
COPY vite.config.js ./
RUN npm install
COPY . .
RUN npm run build
FROM nginx:1.21
COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
RUN rm -rf /usr/share/nginx/html/*
COPY --from=builder /admin/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Dockerfile for backend:
FROM tiangolo/uvicorn-gunicorn:python3.9
EXPOSE 8000
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
COPY ./requirements.txt /tmp/requirements.txt
RUN pip install --no-cache-dir -r /tmp/requirements.txt
WORKDIR /app
COPY . /app
I can certainly transfer a file (as raw bytes stream) from the front-end to the backend via Axios and receive it on the backend Python side. I can then process it however I like. But how can I store it in the location where the front-end container could read it and serve statically?
UPDATE (Use Docker Volumes)
As suggested in this question, I've tried to use a shared volume for my purpose. My COMPOSE file now looks like this:
version: "3.8"
services:
use_frontend:
container_name: 'use_frontend'
# --> ADDED <--
volumes:
- 'myshare:/etc/nginx'
- 'myshare:/usr/share/nginx/html'
build:
context: ./admin
dockerfile: Dockerfile
restart: always
depends_on:
- use_backend
ports:
- 8090:80
use_db:
container_name: use_db
image: postgres:14.2
# etc etc...
use_backend:
container_name: 'use_backend'
volumes:
# --> ADDED <--
- 'myshare:/usr/share/nginx/html'
build:
context: ./api
dockerfile: Dockerfile
restart: always
depends_on:
- use_db
# etc etc...
# --> ADDED <--
volumes:
myshare:
driver: local
The Dockerfile for use_frontend hasn't changed (must it?)
FROM node:16.14.2 as builder
WORKDIR /admin
# copy out files for npm
COPY package*.json ./
COPY vite.config.js ./
# install and build Vue.js
RUN npm install
COPY . .
RUN npm run build
# Nginx image
FROM nginx:1.21
# copy Nginx conf file to VOLUME mounted folder
COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
# clean everything in VOLUME mounted folder (app entry point)
RUN rm -rf /usr/share/nginx/html/*
# copy compiled app to to VOLUME mounted folder (app entry point)
COPY --from=builder /admin/dist /usr/share/nginx/html
# expose port 80 for HTTP access
EXPOSE 80
# run Nginx
CMD ["nginx", "-g", "daemon off;"]
The Nginx conf file hasn't changed either:
events {}
http {
server {
listen 80;
# app entry point
root /usr/share/nginx/html;
# MIME types
include /etc/nginx/mime.types;
client_max_body_size 20M;
location / {
try_files $uri /index.html;
}
# etc etc...
}
}
But after doing
docker compose build
docker compose up
I'm getting file not found errors from Nginx:
use_frontend | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
use_frontend | /docker-entrypoint.sh: Configuration complete; ready for start up
use_frontend | 2022/07/24 23:21:32 [emerg] 1#1: open() "/etc/nginx/nginx.conf" failed (2: No such file or directory)
use_frontend | nginx: [emerg] open() "/etc/nginx/nginx.conf" failed (2: No such file or directory)
What exactly am I doing wrong with the Docker volume mounting?
I'm trying to deploy a Vue js app using docker-compose and Nginx. I'm pretty beginner with Nginx and after searching through StackOverflow and blogs, the website returns blank page (containing vue's index.html page, but unable to load any js or CSS file).
Here is my config:
# docker-compose.yml
version: "3.8"
services:
web:
build: ./web
ports:
- 8080:8080
volumes:
- ./dist:/app
depends_on:
- nginx
nginx:
build: ./nginx
ports:
- 80:80
volumes:
- ./dist:/app
restart: always
# ./web/Dockerfile
FROM node:lts-alpine as build-stage
RUN npm install -g http-server
WORKDIR /app
COPY package*.json ./
RUN npm cache clean --force && npm install
COPY . .
RUN npm run build
EXPOSE 8080
CMD [ "http-server", "dist" ]
# ./nginx/Dockerfile
FROM nginx:1.21-alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d
upstream client {
server web:8080;
}
server {
listen 80;
include /etc/nginx/mime.types;
location / {
proxy_pass http://client;
root /app;
index index.html;
try_files $uri $uri/ /index.html;
include /etc/nginx/mime.types;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location ~ \.css {
add_header Content-Type text/css;
}
location ~ \.js {
add_header Content-Type application/x-javascript;
}
}
Brower console when I open the website:
And nginx log show the following error:
[error] 22#22: *12 open() "/etc/nginx/html/css/app.68c1e752.css" failed (2: No such file or directory),
What should I do to fix this issue?
What you'd typically do is have a single, multi-stage frontend image like in the Dockerize Vue.js App Real-World Example that builds your app and copies the dist contents into NGINX's webroot. You don't need separate NGINX and http-server images because NGINX is already a server (and a much better one)
# docker-compose.yml
version: "3.8"
services:
nginx:
build: ./nginx
ports:
- 80:80
restart: always
# ./nginx/Dockerfile
# build stage
FROM node:lts-alpine as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# production stage
FROM nginx:stable-alpine as production-stage
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build-stage /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Your NGINX config really only needs the try_files declaration for HTML5 History Mode.
I am trying to deploy a Vue app in the frontend and the .net core api in the backend. Using docker-compose file I have been to able to spin up the network and containers but I am struggling to have them communicate. I am pretty new to docker however, do understand that the Vue app dockerfile uses an Nginx base to feed the web app but it seems that may be affecting the network communication as the frontend container does not resolve the backend container name though it should since they are in the same virtual private network with the default bridge driver. When executing a bash shell in the frontend container and doing a curl to the backend container, I do get the correct response.
I did try to expose the backend container to the host and then use the server IP to reach it from the frontend and that does work however, I was hoping to not have to expose my api this way and wanted to make it work through the docker virtual private network if possible.
Example url I am trying in the frontend which encounters a name not resolved error: littlepiggy-api/api or littlepiggy-api:5000/api
Frontend Dockerfile
FROM node:14.18-alpine as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY ./ .
RUN npm run build
# production stage
FROM nginx:stable-alpine as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Backend Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 5000
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["LittlePiggy.Api/LittlePiggy.Api.csproj", "LittlePiggy.Api/"]
RUN dotnet restore "LittlePiggy.Api/LittlePiggy.Api.csproj"
COPY . .
WORKDIR "/src/LittlePiggy.Api"
RUN dotnet build "LittlePiggy.Api.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "LittlePiggy.Api.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "LittlePiggy.Api.dll"]
Docker-compose file
version: '3'
services:
front:
container_name: littlepiggy-front
image: josh898/angie-app-front:latest
ports:
- 80:80
networks:
- littlepiggy
depends_on:
- api
api:
container_name: littlepiggy-api
image: josh898/angie-app-backend:latest
networks:
- littlepiggy
networks:
littlepiggy:
driver: bridge
You need to configure Nginx to pass requests that match the /api route on to the backend service.
If you create a nginx configuration file like this, called nginx.conf and place it in your frontend directory
server {
listen 80;
location / {
index index.html;
root /usr/share/nginx/html;
try_files $uri $uri/ $uri.html =404;
}
location /api/ {
proxy_pass http://littlepiggy-api/;
}
}
Then copy it into your frontend container by changing your frontend Dockerfile to
FROM node:14.18-alpine as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY ./ .
RUN npm run build
# production stage
FROM nginx:stable-alpine as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Then requests to http://localhost/api/xxxx should be passed on to the backend and requests to http://localhost/index.html should be served by the Nginx container directly.
I have simple vue.js app, and I wanted to use Dockerfile to build it:
FROM node:14.14.0-stretch
WORKDIR '/app'
COPY package*.json ./
RUN npm install
COPY . ./
RUN env
RUN npm run generate
is it possible now, using docker-compose, and in compose not build it, but use already prepared image, to get from volume dist folder ? so I could copy it to nginx ?
I suggest that you wanna serve dist folder using nginx.
You should use multi stage build for this https://docs.docker.com/develop/develop-images/multistage-build/
Dockerfile
FROM node:14.14.0-stretch as build
WORKDIR '/app'
COPY package*.json ./
RUN npm install
COPY . ./
RUN env
RUN npm run generate
# create cdn stage from nginx image
FROM nginx:stable-alpine as cdn
# copy nginx config to serve files from /data/www
COPY nginx.conf /etc/nginx/nginx.conf
# copy built files from build stage to /data/www
COPY --from=build /app/dist /data/www
# nginx listen on port 80
EXPOSE 80
CMD [ "nginx" ]
nginx.conf
events {
worker_connections 1024;
}
http {
server {
location / {
root /data/www;
}
}
}
docker-compose.yml
version: '2.4'
services:
nginx-cdn:
build:
context: path/to/Dockerfile
target: cdn
ports:
- '80:80'
I have installed nginx-extras from Ubuntu bash shell in my desktop Windows 10 O.S. The is required to spin up a docker container for an ASP.NET Core 3.1 Blazor web assembly application for serving the static web pages. My nginx.conf:
events { }
http {
include mime.types;
types {
application/wasm wasm;
}
server {
listen 80;
index index.html;
location / {
root /var/www/web;
try_files $uri $uri/ /index.html =404;
}
}
}
Dockerfile:
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env
WORKDIR /app
COPY . ./
RUN dotnet publish -c Release -o output
FROM nginx:alpine
WORKDIR /var/www/web
COPY --from=build-env /app/output/wwwroot .
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
My build command was successful.
However when I wanted to create a container using the command: docker run -p 8080:80 docker-wasm-blazor It gave me an error:
[emerg] 1#1: unknown directive "events" in /etc/nginx/nginx.conf:1 nginx: [emerg] unknown directive "events" in /etc/nginx/nginx.conf:1
I am very new to nginx and containerisation, so any help will be highly appreciated. Thanks.
I had the same error. Fixed by changing the encoding of the nginx.conf file. If you create the nginx.conf file in/with visual studio (Add -> new File) it's most likely that your will get the wrong encoding (other people got the same error).
In my case the encoding was UTF-8 and I needed us-ascii encoding. The easiest was to delete my nginx.conf file and recreate it outside of visual studio (I used Sublime text but I think you can use notepad).
I sorted out the issue by excluding the custom nginx.conf file to copy over the default nginx.conf file by removing the last line from the dockerfile. Now my dockerfile looks like this:
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env
WORKDIR /app
COPY . ./
RUN dotnet publish -c Release -o output
FROM nginx
WORKDIR /usr/share/nginx/html
COPY --from=build-env /app/output/wwwroot/ .
I got the same issue and fixed it by removing the white spaces from before and after "events" and "http", so my config file become:
events{}
http{
include mime.types;
types {
application/wasm wasm;
}
server {
listen 80;
# Here, we set the location for Nginx to serve the files
# by looking for index.html
location / {
root /usr/local/webapp/nginx/html;
try_files $uri $uri/ /index.html =404;
}
}
}