Need help building and deploying monorepo on railway

For some reason I can't connect the github repo. So I tried using the Railway CLI. But the problem with that is it needs me to link. I tried the railway.toml file but I don't think I have the syntax down. So for now, here's my project structure with monorepo, and some context. Frontend depends on the API dir, for important methods to interact with the Backend. So I need to have the full project on there. But on Railway, I have two services.
├── API
│ ├── Types
│ ├── package.json
│ ├── source
│ │ ├── BaseMethods.ts
│ │ ├── GetMethods.ts
│ │ └── index.ts
│ └── tsconfig.json
├── Backend
│ ├── Dockerfile
│ ├── database
│ │ ├── Database.ts
│ │ ├── Middleware
│ │ └── Models
│ ├── index.ts
│ ├── library
│ │ ├── Decorators
│ │ │ ├── Catchable.ts
│ │ │ ├── Checkable.ts
│ │ │ └── DBCatchable.ts
│ │ ├── Errors
│ │ │ ├── Database.ts
│ │ │ ├── Email.ts
│ │ │ └── Params.ts
│ │ ├── Globals
│ │ │ ├── Assets.ts
│ │ │ └── Globals.ts
│ │ ├── Interfaces
│ │ │ ├── Errors.ts
│ │ │ ├── HandlerController.ts
│ │ │ └── RequestRouter.ts
│ │ ├── Types.ts
│ │ └── Utilities
│ │ ├── ErrorUtils.ts
│ │ ├── LoggerUtils.ts
│ │ ├── MiscUtils.ts
│ │ ├── NumberUtils.ts
│ │ └── StringUtils.ts
│ ├── nodemon.json
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── server
│ │ ├── Routes
│ │ │ ├── Get.ts
│ │ │ ├── Post.ts
│ │ │ └── Put.ts
│ │ ├── Server.ts
│ │ └── ValidRoutes.ts
│ ├── source
│ │ ├── Controllers
│ │ │ ├── GetController.ts
│ │ │ ├── PostController.ts
│ │ │ └── PutController.ts
│ │ ├── Handlers
│ │ │ ├── GetHandlers
│ │ │ │ └── HelloWorld.ts
│ │ │ ├── PostHandlers
│ │ │ └── PutHandlers
│ │ └── Middleware
│ │ └── Email.ts
│ ├── start-watch.ts
│ └── tsconfig.json
├── Frontend
│ ├── Dockerfile
│ ├── README.md
│ ├── entrypoint.sh
│ ├── eslint.config.js
│ ├── index.html
│ ├── nginx.conf.template
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── postcss.config.js
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── App.tsx
│ │ ├── assets
│ │ │ └── react.svg
│ │ ├── index.css
│ │ ├── main.tsx
│ │ └── vite-env.d.ts
│ ├── tailwind.config.js
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── LICENSE
├── README.md
├── package.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
└── tsconfig.json
├── API
│ ├── Types
│ ├── package.json
│ ├── source
│ │ ├── BaseMethods.ts
│ │ ├── GetMethods.ts
│ │ └── index.ts
│ └── tsconfig.json
├── Backend
│ ├── Dockerfile
│ ├── database
│ │ ├── Database.ts
│ │ ├── Middleware
│ │ └── Models
│ ├── index.ts
│ ├── library
│ │ ├── Decorators
│ │ │ ├── Catchable.ts
│ │ │ ├── Checkable.ts
│ │ │ └── DBCatchable.ts
│ │ ├── Errors
│ │ │ ├── Database.ts
│ │ │ ├── Email.ts
│ │ │ └── Params.ts
│ │ ├── Globals
│ │ │ ├── Assets.ts
│ │ │ └── Globals.ts
│ │ ├── Interfaces
│ │ │ ├── Errors.ts
│ │ │ ├── HandlerController.ts
│ │ │ └── RequestRouter.ts
│ │ ├── Types.ts
│ │ └── Utilities
│ │ ├── ErrorUtils.ts
│ │ ├── LoggerUtils.ts
│ │ ├── MiscUtils.ts
│ │ ├── NumberUtils.ts
│ │ └── StringUtils.ts
│ ├── nodemon.json
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── server
│ │ ├── Routes
│ │ │ ├── Get.ts
│ │ │ ├── Post.ts
│ │ │ └── Put.ts
│ │ ├── Server.ts
│ │ └── ValidRoutes.ts
│ ├── source
│ │ ├── Controllers
│ │ │ ├── GetController.ts
│ │ │ ├── PostController.ts
│ │ │ └── PutController.ts
│ │ ├── Handlers
│ │ │ ├── GetHandlers
│ │ │ │ └── HelloWorld.ts
│ │ │ ├── PostHandlers
│ │ │ └── PutHandlers
│ │ └── Middleware
│ │ └── Email.ts
│ ├── start-watch.ts
│ └── tsconfig.json
├── Frontend
│ ├── Dockerfile
│ ├── README.md
│ ├── entrypoint.sh
│ ├── eslint.config.js
│ ├── index.html
│ ├── nginx.conf.template
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── postcss.config.js
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── App.tsx
│ │ ├── assets
│ │ │ └── react.svg
│ │ ├── index.css
│ │ ├── main.tsx
│ │ └── vite-env.d.ts
│ ├── tailwind.config.js
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── LICENSE
├── README.md
├── package.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
└── tsconfig.json
No description
77 Replies
Percy
Percy5w ago
Project ID: 6895348a-16e1-4f9a-b3ad-f8846dc4a9db
materwelon
materwelonOP5w ago
Project ID: 6895348a-16e1-4f9a-b3ad-f8846dc4a9db Backend/Dockerfile
# Stage 1: Build the Backend
FROM node:22-alpine AS builder

# Set working directory
WORKDIR /app

# Install pnpm globally
RUN npm install -g pnpm

# Copy root package.json, pnpm-workspace.yaml, and pnpm-lock.yaml
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./

# Install all dependencies
RUN pnpm install

# Copy all workspace packages (includes API, Backend, Frontend)
COPY . .

# Build the Backend
RUN pnpm --filter backend run build

# Stage 2: Create the Production Image
FROM node:22-alpine

# Set working directory
WORKDIR /app

# Install pnpm globally
RUN npm install -g pnpm

# Copy root package.json and pnpm-lock.yaml
COPY package.json pnpm-lock.yaml ./

# Install production dependencies for Backend
RUN pnpm install --prod --filter backend

# Copy the built Backend code from the builder stage
COPY --from=builder /app/Backend/dist ./Backend/dist

# Expose the port that the app runs on
EXPOSE 4000

# Start the application
CMD ["pnpm", "--filter", "backend", "start"]
# Stage 1: Build the Backend
FROM node:22-alpine AS builder

# Set working directory
WORKDIR /app

# Install pnpm globally
RUN npm install -g pnpm

# Copy root package.json, pnpm-workspace.yaml, and pnpm-lock.yaml
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./

# Install all dependencies
RUN pnpm install

# Copy all workspace packages (includes API, Backend, Frontend)
COPY . .

# Build the Backend
RUN pnpm --filter backend run build

# Stage 2: Create the Production Image
FROM node:22-alpine

# Set working directory
WORKDIR /app

# Install pnpm globally
RUN npm install -g pnpm

# Copy root package.json and pnpm-lock.yaml
COPY package.json pnpm-lock.yaml ./

# Install production dependencies for Backend
RUN pnpm install --prod --filter backend

# Copy the built Backend code from the builder stage
COPY --from=builder /app/Backend/dist ./Backend/dist

# Expose the port that the app runs on
EXPOSE 4000

# Start the application
CMD ["pnpm", "--filter", "backend", "start"]
Frontend/Dockerfile
# Stage 1: Build the Frontend
FROM node:22-alpine AS builder

# Set working directory
WORKDIR /app

# Install pnpm globally
RUN npm install -g pnpm

# Copy root package.json, pnpm-workspace.yaml, and pnpm-lock.yaml
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./

# Install all dependencies
RUN pnpm install

# Copy all workspace packages (includes API, Backend, Frontend)
COPY . .

# Build the Frontend
RUN pnpm --filter frontend run build

# Stage 2: Serve with Nginx
FROM nginx:alpine

# Install gettext for envsubst (environment variable substitution)
RUN apk add --no-cache gettext

# Copy custom Nginx configuration template
COPY Frontend/nginx.conf.template /etc/nginx/nginx.conf.template

# Copy entrypoint script
COPY Frontend/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

# Remove default Nginx static assets
RUN rm -rf /usr/share/nginx/html/*

# Copy built Frontend code from builder
COPY --from=builder /app/Frontend/dist /usr/share/nginx/html

# Expose port 80
EXPOSE 80

# Set entrypoint to handle dynamic configuration and start Nginx
ENTRYPOINT ["/entrypoint.sh"]
# Stage 1: Build the Frontend
FROM node:22-alpine AS builder

# Set working directory
WORKDIR /app

# Install pnpm globally
RUN npm install -g pnpm

# Copy root package.json, pnpm-workspace.yaml, and pnpm-lock.yaml
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./

# Install all dependencies
RUN pnpm install

# Copy all workspace packages (includes API, Backend, Frontend)
COPY . .

# Build the Frontend
RUN pnpm --filter frontend run build

# Stage 2: Serve with Nginx
FROM nginx:alpine

# Install gettext for envsubst (environment variable substitution)
RUN apk add --no-cache gettext

# Copy custom Nginx configuration template
COPY Frontend/nginx.conf.template /etc/nginx/nginx.conf.template

# Copy entrypoint script
COPY Frontend/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

# Remove default Nginx static assets
RUN rm -rf /usr/share/nginx/html/*

# Copy built Frontend code from builder
COPY --from=builder /app/Frontend/dist /usr/share/nginx/html

# Expose port 80
EXPOSE 80

# Set entrypoint to handle dynamic configuration and start Nginx
ENTRYPOINT ["/entrypoint.sh"]
Brody
Brody5w ago
send me the nginx config please
materwelon
materwelonOP5w ago
user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

sendfile on;
keepalive_timeout 65;

server {
listen 80;
server_name localhost;

root /usr/share/nginx/html;
index index.html;

location / {
try_files $uri $uri/ /index.html;
}

# Cache control for static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires 1y;
add_header Cache-Control "public, max-age=31536000";
}

# Proxy API requests to Backend
location /api/ {
proxy_pass $API_URL;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

sendfile on;
keepalive_timeout 65;

server {
listen 80;
server_name localhost;

root /usr/share/nginx/html;
index index.html;

location / {
try_files $uri $uri/ /index.html;
}

# Cache control for static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires 1y;
add_header Cache-Control "public, max-age=31536000";
}

# Proxy API requests to Backend
location /api/ {
proxy_pass $API_URL;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
Brody
Brody5w ago
any reason you are proxying requests? vs just having the frontend call the backends domain?
materwelon
materwelonOP5w ago
it can't find the Dockerfile most of the times. And I'm reluctant to specify a path because then it'll ignore the API folder? I'm not sure. I don't understand nginx, unfortunately. This nginx code was written by someone else in the team, and I don't think they understand it either. We're new to complex full stack deployments. Would love to get some guidance (we're in a hackathon :sodead: time's running out)
Brody
Brody5w ago
what's the frontend written in?
materwelon
materwelonOP5w ago
frontend vite+react, typescript backend typescript express
Brody
Brody5w ago
let's fix the lower hanging issues first, remove the proxy stuff and change your frontend code to use an environment variable for the backend host that it will make fetch requests to
materwelon
materwelonOP5w ago
the url for the backend is $API_URL. I'll remove all proxy? but where to I set the API_URL then? It's the one that railway provides, in our case, backend-newrr.railway.app or smth
Brody
Brody5w ago
please see this message for guidance
materwelon
materwelonOP5w ago
okay, let me update it and send it over :thumbsup:
user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

sendfile on;
keepalive_timeout 65;

server {
listen 80;
server_name localhost;

root /usr/share/nginx/html;
index index.html;

location / {
try_files $uri $uri/ /index.html;
}

location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires 1y;
add_header Cache-Control "public, max-age=31536000";
}

}
}
user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

sendfile on;
keepalive_timeout 65;

server {
listen 80;
server_name localhost;

root /usr/share/nginx/html;
index index.html;

location / {
try_files $uri $uri/ /index.html;
}

location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires 1y;
add_header Cache-Control "public, max-age=31536000";
}

}
}
Also, do lmk if you prefer that I don't ping you in replies I didn't really understand using the API url in nginx in the first place. I'm already using that in the frontend via a static class that loads the env and added that in CORS as well.
Brody
Brody5w ago
show me some sample code from your frontend that would make an API request to the backend
materwelon
materwelonOP5w ago
import { BaseMethods } from './BaseMethods';
import axios from 'axios';

export class GetMethods extends BaseMethods {
constructor(baseUrl: string) {
super(baseUrl);
}

public async checkHealth(): Promise<string> {
const response = await axios.get<string>(`${this.baseUrl}/health`);
return response.data;
}
}
import { BaseMethods } from './BaseMethods';
import axios from 'axios';

export class GetMethods extends BaseMethods {
constructor(baseUrl: string) {
super(baseUrl);
}

public async checkHealth(): Promise<string> {
const response = await axios.get<string>(`${this.baseUrl}/health`);
return response.data;
}
}
So frontend would create an instance of this class like so
const GetApi = new GetMethods(Globals.API_URL);
const GetApi = new GetMethods(Globals.API_URL);
then use the methods
await GetApi.checkHealth();
await GetApi.checkHealth();
Brody
Brody5w ago
show me how API_URL is defined please
materwelon
materwelonOP5w ago
This works, tested locally. Endpoint also works, tested via Postman.
import dotenv from 'dotenv';

export class Globals {
public static ENV = process.env.NODE_ENV || 'development';

private constructor() {}

static {
Globals.initialize();
}

private static initialize() {
dotenv.config({ path: `.env.${Globals.ENV}` });
}
// CONSTANTS

// PRIVATE CONSTANTS | VARIABLES
public static readonly DB_NAME = process.env.DB_NAME || '';
public static readonly MONGO_URI = process.env.MONGODB_URI || '';
public static readonly V_EMAIL = process.env.V_EMAIL || '';
public static readonly V_PASSWORD = process.env.V_PASSWORD || '';
public static readonly PORT = process.env.PORT || 3000;
public static readonly API_URL = process.env.API_URL || '';

// VARIABLE ACCESSORS BASED ON ENVIRONMENT
}
import dotenv from 'dotenv';

export class Globals {
public static ENV = process.env.NODE_ENV || 'development';

private constructor() {}

static {
Globals.initialize();
}

private static initialize() {
dotenv.config({ path: `.env.${Globals.ENV}` });
}
// CONSTANTS

// PRIVATE CONSTANTS | VARIABLES
public static readonly DB_NAME = process.env.DB_NAME || '';
public static readonly MONGO_URI = process.env.MONGODB_URI || '';
public static readonly V_EMAIL = process.env.V_EMAIL || '';
public static readonly V_PASSWORD = process.env.V_PASSWORD || '';
public static readonly PORT = process.env.PORT || 3000;
public static readonly API_URL = process.env.API_URL || '';

// VARIABLE ACCESSORS BASED ON ENVIRONMENT
}
Brody
Brody5w ago
is this frontend code?
materwelon
materwelonOP5w ago
yeah, it's a file in the Frontend.
Brody
Brody5w ago
why is a file in the frontend referencing the mongo uri?
materwelon
materwelonOP5w ago
i'm supposed to delete that line :D_lol: frontend will only have API_URL and maybe port, depends on the person writing the frontend i only work on the backend
Brody
Brody5w ago
lol why was it ever there?
materwelon
materwelonOP5w ago
cuz copied this file from the Backend
Brody
Brody5w ago
fair enough you are missing the needed variables in your Dockerfiles
materwelon
materwelonOP5w ago
but Railway isn't detecting the dockerfile at all. And since we can't connect via github (because we don't own the project, it's part of the hackathon group), we don't know how to get it up and running
Brody
Brody5w ago
we'll get to that, remember, low hanging issues first
materwelon
materwelonOP5w ago
hm. ye
materwelon
materwelonOP5w ago
i made the nginx changes as you suggested oh wait. ooo. So instead of having the Dockerfiles inside the dirs of Frontend and Backend, I keep it in root dir and add these build time variables in the Dockerfile? so Dockerfile.frontend Dockerfile.backend in the root dir? This is because I need it to use the full monorepo each time, because of that API directory (which is a package, using pnpm workspace) If so, I know I can refernce the correct Dockerfile via railway env variables. But what about the service? I can't connect to github so I have to use the CLI. But with the CLI, it needs me to link a service, either backend or frontend. Soooo, yeah. I'm not sure what Dockerfile you need me to update. Best to first get the Backend to work. So I add both Dockerfile and service? But what's the point of adding a Dockerfile env in the Dockerfile itself? you see how confused I am lmao and thank you for bearing with me
Brody
Brody5w ago
you dont need to move anything, please dont go jumping to conclusions here, remember low hanging issues first me dumping everything you need to do at once is not helpful, so its going to be one thing at a time
materwelon
materwelonOP5w ago
so for now, what do you need me to add to the Backend's Dockerfile? env for the service?
Brody
Brody5w ago
as the docs say, you need to add ARG lines
materwelon
materwelonOP5w ago
# Stage 1: Build the Backend
FROM node:22-alpine AS builder

ARG RAILWAY_ENVIRONMENT=staging
ARG RAILWAY_SERVICE_NAME=backend
RUN echo $RAILWAY_SERVICE_NAME
# Stage 1: Build the Backend
FROM node:22-alpine AS builder

ARG RAILWAY_ENVIRONMENT=staging
ARG RAILWAY_SERVICE_NAME=backend
RUN echo $RAILWAY_SERVICE_NAME
Brody
Brody5w ago
you dont need to ping reply me btw
materwelon
materwelonOP5w ago
will keep that in mind for future messages :thumbsup:
Brody
Brody5w ago
1. dont specify the value 2. you dont need to echo it, that was purely for demonstration 3. i'm sure your backend needs more than those two variables 4. set the variables in the service variables
materwelon
materwelonOP5w ago
ah wait nvm. got it. I'm supposed to set them on the dashboard. brb
Brody
Brody5w ago
that too
materwelon
materwelonOP5w ago
that too ah :sodead: what am I missing. okay lemmi do this first then will show u
Brody
Brody5w ago
updated
materwelon
materwelonOP5w ago
I think I understand what the args are now. and railway already has the environment name and service name. So I don't need to create them again on the dash. And no, I don't need any more args during build for the backend. For the other variables, I already created them on the backend.
No description
Brody
Brody5w ago
lets see the backend Dockerfile
materwelon
materwelonOP5w ago
sec
# Stage 1: Build the Backend
FROM node:22-alpine AS builder

ARG RAILWAY_ENVIRONMENT
ARG RAILWAY_SERVICE_NAME

# Set working directory
WORKDIR /app

# Install pnpm globally
RUN npm install -g pnpm

# Copy root package.json, pnpm-workspace.yaml, and pnpm-lock.yaml
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./

# Install all dependencies
RUN pnpm install

# Copy all workspace packages (includes API, Backend, Frontend)
COPY . .

# Build the Backend
RUN pnpm --filter backend run build

# Stage 2: Create the Production Image
FROM node:22-alpine

# Set working directory
WORKDIR /app

# Install pnpm globally
RUN npm install -g pnpm

# Copy root package.json and pnpm-lock.yaml
COPY package.json pnpm-lock.yaml ./

# Install production dependencies for Backend
RUN pnpm install --prod --filter backend

# Copy the built Backend code from the builder stage
COPY --from=builder /app/Backend/dist ./Backend/dist

# Expose the port that the app runs on
EXPOSE 4000

# Start the application
CMD ["pnpm", "--filter", "backend", "start"]
# Stage 1: Build the Backend
FROM node:22-alpine AS builder

ARG RAILWAY_ENVIRONMENT
ARG RAILWAY_SERVICE_NAME

# Set working directory
WORKDIR /app

# Install pnpm globally
RUN npm install -g pnpm

# Copy root package.json, pnpm-workspace.yaml, and pnpm-lock.yaml
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./

# Install all dependencies
RUN pnpm install

# Copy all workspace packages (includes API, Backend, Frontend)
COPY . .

# Build the Backend
RUN pnpm --filter backend run build

# Stage 2: Create the Production Image
FROM node:22-alpine

# Set working directory
WORKDIR /app

# Install pnpm globally
RUN npm install -g pnpm

# Copy root package.json and pnpm-lock.yaml
COPY package.json pnpm-lock.yaml ./

# Install production dependencies for Backend
RUN pnpm install --prod --filter backend

# Copy the built Backend code from the builder stage
COPY --from=builder /app/Backend/dist ./Backend/dist

# Expose the port that the app runs on
EXPOSE 4000

# Start the application
CMD ["pnpm", "--filter", "backend", "start"]
I assume I have to update the Backend stuff I'm using below? instead of hardcoding it?
Brody
Brody5w ago
are you sure you dont need to use some other variables during build?
materwelon
materwelonOP5w ago
nop nothing that relates to my backend atleast
Brody
Brody5w ago
how do you know you dont need environment variables during build
materwelon
materwelonOP5w ago
because I've made a similar backend for a separate project before (was less complex), but I didn't need those other variables during build time. I'm not "setting up" anything during build time, except building the Backend code. the start command does everything else and my ENVs are only ever referenced by the code on requests
Brody
Brody5w ago
sounds good, just making sure show me the frontend service variables in railway please
materwelon
materwelonOP5w ago
sec
materwelon
materwelonOP5w ago
No description
Brody
Brody5w ago
cool, show me the dockerfile please
materwelon
materwelonOP5w ago
it's here apologies late response
Brody
Brody5w ago
i know, but it needed to be updated so i asked to see it after you have made the changes
Brody
Brody5w ago
please read this docs section
materwelon
materwelonOP5w ago
updated Frontend/Dockerfile and added
RAILWAY_DOCKERFILE_PATH=/Frontend/Dockerfile
RAILWAY_DOCKERFILE_PATH=/Frontend/Dockerfile
updated Backend/Dockerfile and added
RAILWAY_DOCKERFILE_PATH=/Backend/Dockerfile
RAILWAY_DOCKERFILE_PATH=/Backend/Dockerfile
ENV* ENV before both
Brody
Brody5w ago
again, please do not try to skip ahead
materwelon
materwelonOP5w ago
wait but this is part of the variables at build time guide the first instruction
Brody
Brody5w ago
I linked a specific header, not the entire page
materwelon
materwelonOP5w ago
I already completed that stuff. I only need service and environment at build time
Brody
Brody5w ago
for your frontend you need more than that
materwelon
materwelonOP5w ago
uhhhh. the API_URL? that's not needed at build time
Brody
Brody5w ago
yes it is, this is a static site
materwelon
materwelonOP5w ago
API_URL is from the backend though and I'll only need that when someone interacts with the frontend
Brody
Brody5w ago
the frontend needs that variable to know what url to make requests to. the frontend is a static site. thus that variable is needed during build.
materwelon
materwelonOP5w ago
# Stage 1: Build the Frontend
FROM node:22-alpine AS builder

ARG API_URL
ARG RAILWAY_ENVIRONMENT
ARG RAILWAY_SERVICE_NAME

# Set working directory
WORKDIR /app
# Stage 1: Build the Frontend
FROM node:22-alpine AS builder

ARG API_URL
ARG RAILWAY_ENVIRONMENT
ARG RAILWAY_SERVICE_NAME

# Set working directory
WORKDIR /app
looks like this now
Brody
Brody5w ago
does your frontend even use those railway specific environment variables?
materwelon
materwelonOP5w ago
it'll need it for the build because it's a monorepo
Brody
Brody5w ago
how so
materwelon
materwelonOP5w ago
oh well, i shouldnt step ahead. It doesnt need it in the current state
Brody
Brody5w ago
how is vite going to access API_URL if you don't have the correct prefix?
materwelon
materwelonOP5w ago
the website isn't fetching any data from the backend when it starts btw. atleast right now. So API_URL isn't needed either, really. yeah, it doesnt there are no backend enpoints that send anything to the website during build it's all frontend
Brody
Brody5w ago
it doesn't need to be during build it's a static site done with vite, correct?
materwelon
materwelonOP5w ago
yes it's static during build time oh btw, got perms for github and connected it to the railway project. well, service. have not deployed it needs fixing :D_lol: i should probs test locally with docker first
Brody
Brody5w ago
show me the frontend Dockerfile please
materwelon
materwelonOP5w ago
back finally :Pray:
# Stage 1: Build the Frontend
FROM node:22-alpine AS builder

ARG API_URL
ARG RAILWAY_ENVIRONMENT
ARG RAILWAY_SERVICE_NAME

# Set working directory
WORKDIR /app

# Install pnpm globally
RUN npm install -g pnpm

# Copy root package.json, pnpm-workspace.yaml, and pnpm-lock.yaml
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./

# Install all dependencies
RUN pnpm install

# Copy all workspace packages (includes API, Backend, Frontend)
COPY . .

# Build the Frontend
RUN pnpm --filter frontend run build

# Stage 2: Serve with Nginx
FROM nginx:alpine

# Install gettext for envsubst (environment variable substitution)
RUN apk add --no-cache gettext

# Copy custom Nginx configuration template
COPY Frontend/nginx.conf.template /etc/nginx/nginx.conf.template

# Copy entrypoint script
COPY Frontend/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

# Remove default Nginx static assets
RUN rm -rf /usr/share/nginx/html/*

# Copy built Frontend code from builder
COPY --from=builder /app/Frontend/dist /usr/share/nginx/html

# Expose port 80
EXPOSE 80

# Set entrypoint to handle dynamic configuration and start Nginx
ENTRYPOINT ["/entrypoint.sh"]
# Stage 1: Build the Frontend
FROM node:22-alpine AS builder

ARG API_URL
ARG RAILWAY_ENVIRONMENT
ARG RAILWAY_SERVICE_NAME

# Set working directory
WORKDIR /app

# Install pnpm globally
RUN npm install -g pnpm

# Copy root package.json, pnpm-workspace.yaml, and pnpm-lock.yaml
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./

# Install all dependencies
RUN pnpm install

# Copy all workspace packages (includes API, Backend, Frontend)
COPY . .

# Build the Frontend
RUN pnpm --filter frontend run build

# Stage 2: Serve with Nginx
FROM nginx:alpine

# Install gettext for envsubst (environment variable substitution)
RUN apk add --no-cache gettext

# Copy custom Nginx configuration template
COPY Frontend/nginx.conf.template /etc/nginx/nginx.conf.template

# Copy entrypoint script
COPY Frontend/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

# Remove default Nginx static assets
RUN rm -rf /usr/share/nginx/html/*

# Copy built Frontend code from builder
COPY --from=builder /app/Frontend/dist /usr/share/nginx/html

# Expose port 80
EXPOSE 80

# Set entrypoint to handle dynamic configuration and start Nginx
ENTRYPOINT ["/entrypoint.sh"]
Brody
Brody5w ago
vite will only load variables that are prefixed with VITE_
materwelon
materwelonOP5w ago
decided to use two repos instead of one :yescat: we won the hackathon tho! thanks for trying to help Brody :smil:
Want results from more Discord servers?
Add your server