Should be able to deploy

This commit is contained in:
cdricms
2025-01-18 21:13:03 +01:00
parent eb9883a1c3
commit 2046a32202
15 changed files with 248 additions and 51 deletions

17
.env.template Normal file
View File

@@ -0,0 +1,17 @@
ENVIRONMENT=${ENVIRONMENT:-PRODUCTION}
POSTGRES_USER=${POSTGRES_USER:-latosa}
POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-1234}
POSTGRES_DB=${POSTGRES_DB:-latosa}
# Docker inner port container
POSTGRES_DOCKER_PORT=${POSTGRES_DOCKER_PORT:-5432}
BACKEND_DOCKER_PORT=${BACKEND_DOCKER_PORT:-3001}
FRONTEND_DOCKER_PORT=${FRONTEND_DOCKER_PORT:-3000}
POSTGRES_PORT=${POSTGRES_PORT:-5432}
BACKEND_PORT=${BACKEND_PORT:-3001}
FRONTEND_PORT=${FRONTEND_PORT:-3000}
FRONTEND_HOSTNAME=${FRONTEND_HOSTNAME:-latosa-frontend}
BACKEND_HOSTNAME=${BACKEND_HOSTNAME:-latosa-backend}
DATABASE_HOSTNAME=${DATABASE_HOSTNAME:-latosa-database}
SERVER_NAME=${SERVER_NAME:-localhost}

View File

@@ -41,12 +41,14 @@ func main() {
environ := os.Getenv("ENVIRONMENT")
port := os.Getenv("BACKEND_DOCKER_PORT")
hostname := os.Getenv("DATABASE_HOSTNAME")
if environ == "DEV" {
port = os.Getenv("BACKEND_PORT")
hostname = "localhost"
}
dsn := core.DSN{
Hostname: "localhost",
Hostname: hostname,
Port: os.Getenv("POSTGRES_PORT"),
DBName: os.Getenv("POSTGRES_DB"),
User: os.Getenv("POSTGRES_USER"),

View File

@@ -1,7 +1,12 @@
services:
latosa-escrima.fr-frontend:
container_name: latosa-frontend
image: cems.dev:5000/latosa-escrima.fr:latest
# image: cems.dev:5000/latosa-escrima.fr:latest
build:
context: ./frontend/
dockerfile: Dockerfile
depends_on:
- latosa-escrima.fr-backend
env_file: .env
ports:
- ${FRONTEND_PORT}:${FRONTEND_DOCKER_PORT}
@@ -9,7 +14,10 @@ services:
networks:
- le-network
latosa-escrima.fr-backend:
restart: always
container_name: latosa-backend
depends_on:
- psql
build:
context: ./backend/
dockerfile: Dockerfile
@@ -35,3 +43,4 @@ volumes:
networks:
le-network:
driver: bridge

View File

@@ -1,24 +1,62 @@
# Use Deno image
FROM denoland/deno:alpine
# syntax=docker.io/docker/dockerfile:1
# Set working directory
FROM node:18-alpine AS base
# Install dependencies only when needed
FROM base AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
# Copy project files
# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \
else echo "Lockfile not found." && exit 1; \
fi
# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the build.
# ENV NEXT_TELEMETRY_DISABLED=1
RUN \
if [ -f yarn.lock ]; then yarn run build; \
elif [ -f package-lock.json ]; then npm run build; \
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \
else echo "Lockfile not found." && exit 1; \
fi
# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN deno install
# Uncomment the following line in case you want to disable telemetry during runtime.
ENV NEXT_TELEMETRY_DISABLED=1
# Install Next.js dependencies
RUN deno task build
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
# Move everything to the standalone
RUN cp -r public .next/standalone/public
RUN cp -r .next/static .next/standalone/.next/static
RUN mv .next/standalone/server.js .next/standalone/server.cjs
COPY --from=builder /app/public ./public
RUN rm -r ./node_modules
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
# Start the Next.js app
CMD ["deno", "run", "--allow-env", "--allow-read", "--allow-sys", "--allow-net", ".next/standalone/server.cjs"]
USER nextjs
# server.js is created by next build from the standalone output
# https://nextjs.org/docs/pages/api-reference/config/next-config-js/output
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]

25
frontend/Dockerfile.old Normal file
View File

@@ -0,0 +1,25 @@
# Use Deno image
FROM node
# Set working directory
WORKDIR /app
# Copy project files
COPY . .
ENV NODE_PATH=.
ENV NODE_ENV=production
RUN npm install
# Install Next.js dependencies
RUN npm run build
# Move everything to the standalone
RUN cp -r public .next/standalone/public
RUN cp -r .next/static .next/standalone/.next/static
RUN mv .next/standalone/server.js .next/standalone/server.cjs
RUN rm -r ./node_modules
# Start the Next.js app
CMD ["node", ".next/standalone/server.cjs"]

View File

@@ -1,8 +1,6 @@
"use server";
export default async function About() {
const res = await fetch("api");
console.log(res);
return (
<div>
<div>

View File

@@ -1,16 +0,0 @@
import { dirname } from "path";
import { fileURLToPath } from "url";
import { FlatCompat } from "@eslint/eslintrc";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
});
const eslintConfig = [
...compat.extends("next/core-web-vitals", "next/typescript"),
];
export default eslintConfig;

View File

@@ -1 +1 @@
export const API_URL = `http://localhost:${process.env.NEXT_PUBLIC_BACKEND_PORT}`;
export const API_URL = process.env.NEXT_PUBLIC_API_URL ?? "";

View File

@@ -5,6 +5,7 @@ import IUser from "./interfaces/IUser";
export async function middleware(request: NextRequest) {
const sessionCookie = request.cookies.get("auth_token")?.value;
// console.log(sessionCookie);
if (!sessionCookie) {
return NextResponse.redirect(
new URL(
@@ -15,18 +16,22 @@ export async function middleware(request: NextRequest) {
}
try {
console.log(API_URL);
const res = await fetch(`${API_URL}/users/me`, {
headers: { Authorization: `Bearer ${sessionCookie}` },
});
const js: ApiResponse<IUser> = await res.json();
if (js.status === "Error")
if (js.status === "Error") {
console.log(js.message);
return NextResponse.redirect(
new URL(
`/login?redirectTo=${encodeURIComponent(request.url)}`,
request.url,
),
);
}
} catch (e: any) {
console.log(e);
return NextResponse.redirect(
new URL(
`/login?redirectTo=${encodeURIComponent(request.url)}`,

View File

@@ -1,8 +1,17 @@
import type { NextConfig } from "next";
const apiUrl =
process.env.NODE_ENV !== "production"
? `http://localhost:${process.env.BACKEND_PORT ?? 3001}`
: `https://${process.env.SERVER_NAME}/api`;
const nextConfig: NextConfig = {
/* config options here */
output: "standalone",
// webpack: (config) => {
// config.resolve.alias["@"] = path.resolve(__dirname, "./");
// return config;
// },
images: {
remotePatterns: [
{
@@ -13,6 +22,7 @@ const nextConfig: NextConfig = {
},
env: {
NEXT_PUBLIC_BACKEND_PORT: process.env.BACKEND_PORT,
NEXT_PUBLIC_API_URL: apiUrl,
},
};

84
init.py Normal file
View File

@@ -0,0 +1,84 @@
import re
import os
# Define template and output file paths
TEMPLATE_FILE = ".env.template"
OUTPUT_FILE = ".env"
def load_template(template_path):
"""
Load the .env.template file.
"""
if not os.path.exists(template_path):
raise FileNotFoundError(f"Template file '{template_path}' not found.")
with open(template_path, 'r') as file:
return file.readlines()
def parse_variable(line):
"""
Extract the variable name and default value from a template line.
"""
match = re.match(r"(.*?)\$\{([^}]+)\}(.*)", line)
if match:
prefix, var_value, suffix = match.groups()
# Extract variable name and default value (if any)
var_name, default_value = (var_value.split(":-") + [""])[:2]
return prefix, var_name, default_value, suffix
return None, None, None, None
def prompt_variable(var_name, default_value):
"""
Prompt the user to input a value for the variable, using a default if no input is provided.
"""
user_input = input(f"Enter value for {var_name} [default: {default_value}]: ").strip()
return user_input if user_input else default_value
def generate_env(template_lines):
"""
Generate the .env file content by substituting variables from the template.
"""
output_lines = ["# Generated .env file\n"]
for line in template_lines:
# Skip comments and empty lines
if line.strip().startswith("#") or not line.strip():
output_lines.append(line)
continue
# Parse and process variables
prefix, var_name, default_value, suffix = parse_variable(line)
if var_name:
# Get the default value from the template (already handled in the parsing)
value = prompt_variable(var_name, default_value)
output_lines.append(f"{prefix}{value}{suffix}\n")
else:
# Unprocessed line (e.g., no variables)
output_lines.append(line)
return output_lines
def write_env(output_path, lines):
"""
Write the generated .env file content to the output file.
"""
with open(output_path, 'w') as file:
file.writelines(lines)
print(f".env file has been successfully created at '{output_path}'.")
def main():
try:
# Load the template file
template_lines = load_template(TEMPLATE_FILE)
# Generate the .env content
output_lines = generate_env(template_lines)
# Write the content to the .env file
write_env(OUTPUT_FILE, output_lines)
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
main()

View File

@@ -1,4 +0,0 @@
#!/usr/bin/sh
printf "ENVIRONMENT=DEV\nPOSTGRES_USER=\nPOSTGRES_PASSWORD=\nPOSTGRES_DB=\n#\nDocker\ninner\nport\ncontainer\nPOSTGRES_DOCKER_PORT=5432\nBACKEND_DOCKER_PORT=3000\nFRONTEND_DOCKER_PORT=3000\nPOSTGRES_PORT=5432\nBACKEND_PORT=3001\nFRONTEND_PORT=3000\n" > .env
ln $(pwd)/.env $(pwd)/backend
ln $(pwd)/.env $(pwd)/frontend

View File

@@ -1,11 +0,0 @@
server {
server_name TO BE SET;
location / {
proxy_pass http://localhost:FRONTEND_PORT; # Set frontend port based on what you have exposed
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;
}
}

20
nginx/default.conf Normal file
View File

@@ -0,0 +1,20 @@
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://latosa-frontend:3000; # Set frontend port based on what you have exposed
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;
}
location /api {
proxy_pass http://latosa-backend:3001; # Set frontend port based on what you have exposed
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;
}
}

View File

@@ -0,0 +1,20 @@
server {
listen 80;
server_name ${SERVER_NAME};
location / {
proxy_pass http://${FRONTEND_HOSTNAME}:${FRONTEND_PORT}; # Set frontend port based on what you have exposed
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;
}
location /api {
proxy_pass http://${BACKEND_HOSTNAME}:${BACKEND_PORT}; # Set frontend port based on what you have exposed
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;
}
}