Skip to content

Commit c2b6812

Browse files
Merge pull request #93 from solo-io/charlesthebird/readOnlyFilesystemFix
Charlesthebird/read only filesystem fix
2 parents b6c8a8c + 3ba5bc3 commit c2b6812

File tree

15 files changed

+871
-21
lines changed

15 files changed

+871
-21
lines changed

.dockerignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
**/node_modules/*
22
*.local
3-
dist
3+
dist
4+
.DS_Store

Dockerfile

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,36 @@
1-
FROM node:18.16.0
1+
###############
2+
# #
3+
# Build Stage #
4+
# #
5+
###############
6+
7+
FROM node:18.16.0 AS build_stage
8+
9+
# Install global dependencies.
10+
RUN apt-get update && apt-get install -y build-essential
11+
12+
# Copy all project files.
13+
WORKDIR /app
14+
COPY ./projects projects
15+
COPY ./scripts scripts
16+
17+
# Run the startup script, without starting the server.
18+
# This script:
19+
# - Installs dependencies.
20+
# - Builds the UI.
21+
# - Moves the UI build folder to the server project.
22+
# - Inserts an EJS view engine variable into the UI build,
23+
# so that the server can send the live environment variables
24+
# along with the UI when the build is served.
25+
RUN START_SERVER=false sh ./scripts/startup.sh
26+
27+
###############
28+
# #
29+
# Serve Stage #
30+
# #
31+
###############
32+
33+
FROM node:18.16.0 AS serve_stage
234

335
ENV VITE_PORTAL_SERVER_URL=$VITE_PORTAL_SERVER_URL \
436
VITE_CLIENT_ID=$VITE_CLIENT_ID \
@@ -15,19 +47,15 @@ ENV VITE_PORTAL_SERVER_URL=$VITE_PORTAL_SERVER_URL \
1547
VITE_LOGO_IMAGE_URL=$VITE_LOGO_IMAGE_URL \
1648
VITE_COMPANY_NAME=$VITE_COMPANY_NAME
1749

18-
# Copy files for build
50+
# Copy the server files, (this includes the UI build).
1951
WORKDIR /app
20-
COPY ./projects projects
21-
WORKDIR /app/projects/ui
22-
23-
# Install global dependencies and set up for runtime
24-
RUN apt-get update && apt-get install -y build-essential
25-
RUN yarn install
26-
EXPOSE 4000
52+
COPY --from=build_stage /app/projects/server .
2753

28-
# Build the app and pass in the environment variables, then start it.
29-
# The build can't happen in 2 stages (build and runtime),
30-
# since these variables will change when the image is deployed.
54+
# Pass through the environment variables, and then start the server.
55+
# These variables will change when the image is deployed.
56+
# This needs to be `node ./bin/www` instead of `yarn start because
57+
# running yarn causes a yarn cache file to change, which doesn't work
58+
# in read-only environments.
3159
ENTRYPOINT VITE_PORTAL_SERVER_URL=$VITE_PORTAL_SERVER_URL \
3260
VITE_CLIENT_ID=$VITE_CLIENT_ID \
3361
VITE_TOKEN_ENDPOINT=$VITE_TOKEN_ENDPOINT \
@@ -42,4 +70,4 @@ ENTRYPOINT VITE_PORTAL_SERVER_URL=$VITE_PORTAL_SERVER_URL \
4270
VITE_APIS_IMAGE_URL=$VITE_APIS_IMAGE_URL \
4371
VITE_LOGO_IMAGE_URL=$VITE_LOGO_IMAGE_URL \
4472
VITE_COMPANY_NAME=$VITE_COMPANY_NAME \
45-
yarn build && yarn run vite preview --port 4000 --host
73+
node ./bin/www
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
changelog:
2+
- type: FIX
3+
issueLink: https://github.com/solo-io/gloo-mesh-enterprise/issues/18336
4+
description: >-
5+
Adds a server with a view engine to the project, which only is used to
6+
serve the UI and insert configuration from environment variables.
7+
Also fixes a yarn audit issue with axios.

projects/server/app.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
var express = require("express");
2+
var path = require("path");
3+
4+
// Express and view engine setup
5+
var app = express();
6+
app.set("views", path.join(__dirname, "public", "dist"));
7+
app.set("view engine", "ejs");
8+
9+
// The environment variables that we will pass through to the React app.
10+
var variablesInit = `
11+
const insertedEnvironmentVariables = ${JSON.stringify(
12+
Object.fromEntries(
13+
Object.entries(process.env).filter(([key, _value]) =>
14+
key.startsWith("VITE_")
15+
)
16+
)
17+
)};
18+
`;
19+
20+
// This renders the index.ejs file
21+
app.get("/", (_req, res) => {
22+
res.render("index.ejs", { VariablesInit: variablesInit });
23+
});
24+
25+
// This serves all static assets.
26+
app.use(express.static(__dirname + "/public/dist"));
27+
28+
// Any fallthrough routes go to index.ejs.
29+
app.get("*", (_req, res) => {
30+
res.render("index.ejs", { VariablesInit: variablesInit });
31+
});
32+
33+
module.exports = app;

projects/server/bin/www

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/**
2+
* This file was pulled from the Express generator's pug template, and does the following:
3+
* - Creates an http server on the requested port, using the Express app from `../app.js`.
4+
* - Adds some logging messages for different statuses.
5+
*/
6+
7+
/**
8+
* Module dependencies.
9+
*/
10+
11+
var app = require("../app");
12+
var http = require("http");
13+
14+
/**
15+
* Get port from environment and store in Express.
16+
*/
17+
18+
var port = normalizePort(process.env.PORT || "4000");
19+
app.set("port", port);
20+
21+
/**
22+
* Create HTTP server.
23+
*/
24+
25+
var server = http.createServer(app);
26+
27+
/**
28+
* Listen on provided port, on all network interfaces.
29+
*/
30+
31+
server.listen(port);
32+
server.on("error", onError);
33+
server.on("listening", onListening);
34+
35+
/**
36+
* Normalize a port into a number, string, or false.
37+
*/
38+
39+
function normalizePort(val) {
40+
var port = parseInt(val, 10);
41+
42+
if (isNaN(port)) {
43+
// named pipe
44+
return val;
45+
}
46+
47+
if (port >= 0) {
48+
// port number
49+
return port;
50+
}
51+
52+
return false;
53+
}
54+
55+
/**
56+
* Event listener for HTTP server "error" event.
57+
*/
58+
59+
function onError(error) {
60+
if (error.syscall !== "listen") {
61+
throw error;
62+
}
63+
64+
var bind = typeof port === "string" ? "Pipe " + port : "Port " + port;
65+
66+
// handle specific listen errors with friendly messages
67+
switch (error.code) {
68+
case "EACCES":
69+
console.error(bind + " requires elevated privileges");
70+
process.exit(1);
71+
break;
72+
case "EADDRINUSE":
73+
console.error(bind + " is already in use");
74+
process.exit(1);
75+
break;
76+
default:
77+
throw error;
78+
}
79+
}
80+
81+
/**
82+
* Event listener for HTTP server "listening" event.
83+
*/
84+
85+
function onListening() {
86+
var addr = server.address();
87+
var bind = typeof addr === "string" ? "pipe " + addr : "port " + addr.port;
88+
console.log("Listening on " + bind);
89+
}

projects/server/package.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "server",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "./bin/www",
6+
"scripts": {
7+
"start": "node ./bin/www"
8+
},
9+
"dependencies": {
10+
"ejs": "^3.1.10",
11+
"express": "^4.19.2",
12+
"http": "^0.0.1-security",
13+
"path": "^0.12.7"
14+
}
15+
}

0 commit comments

Comments
 (0)