Should be able to deploy
This commit is contained in:
17
.env.template
Normal file
17
.env.template
Normal 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}
|
||||||
@@ -41,12 +41,14 @@ func main() {
|
|||||||
environ := os.Getenv("ENVIRONMENT")
|
environ := os.Getenv("ENVIRONMENT")
|
||||||
|
|
||||||
port := os.Getenv("BACKEND_DOCKER_PORT")
|
port := os.Getenv("BACKEND_DOCKER_PORT")
|
||||||
|
hostname := os.Getenv("DATABASE_HOSTNAME")
|
||||||
if environ == "DEV" {
|
if environ == "DEV" {
|
||||||
port = os.Getenv("BACKEND_PORT")
|
port = os.Getenv("BACKEND_PORT")
|
||||||
|
hostname = "localhost"
|
||||||
}
|
}
|
||||||
|
|
||||||
dsn := core.DSN{
|
dsn := core.DSN{
|
||||||
Hostname: "localhost",
|
Hostname: hostname,
|
||||||
Port: os.Getenv("POSTGRES_PORT"),
|
Port: os.Getenv("POSTGRES_PORT"),
|
||||||
DBName: os.Getenv("POSTGRES_DB"),
|
DBName: os.Getenv("POSTGRES_DB"),
|
||||||
User: os.Getenv("POSTGRES_USER"),
|
User: os.Getenv("POSTGRES_USER"),
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
services:
|
services:
|
||||||
latosa-escrima.fr-frontend:
|
latosa-escrima.fr-frontend:
|
||||||
container_name: latosa-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
|
env_file: .env
|
||||||
ports:
|
ports:
|
||||||
- ${FRONTEND_PORT}:${FRONTEND_DOCKER_PORT}
|
- ${FRONTEND_PORT}:${FRONTEND_DOCKER_PORT}
|
||||||
@@ -9,7 +14,10 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- le-network
|
- le-network
|
||||||
latosa-escrima.fr-backend:
|
latosa-escrima.fr-backend:
|
||||||
|
restart: always
|
||||||
container_name: latosa-backend
|
container_name: latosa-backend
|
||||||
|
depends_on:
|
||||||
|
- psql
|
||||||
build:
|
build:
|
||||||
context: ./backend/
|
context: ./backend/
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
@@ -35,3 +43,4 @@ volumes:
|
|||||||
|
|
||||||
networks:
|
networks:
|
||||||
le-network:
|
le-network:
|
||||||
|
driver: bridge
|
||||||
|
|||||||
@@ -1,24 +1,62 @@
|
|||||||
# Use Deno image
|
# syntax=docker.io/docker/dockerfile:1
|
||||||
FROM denoland/deno:alpine
|
|
||||||
|
|
||||||
# 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
|
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 . .
|
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
|
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 addgroup --system --gid 1001 nodejs
|
||||||
RUN deno task build
|
RUN adduser --system --uid 1001 nextjs
|
||||||
|
|
||||||
# Move everything to the standalone
|
COPY --from=builder /app/public ./public
|
||||||
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
|
# 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
|
USER nextjs
|
||||||
CMD ["deno", "run", "--allow-env", "--allow-read", "--allow-sys", "--allow-net", ".next/standalone/server.cjs"]
|
|
||||||
|
# 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
25
frontend/Dockerfile.old
Normal 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"]
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
export default async function About() {
|
export default async function About() {
|
||||||
const res = await fetch("api");
|
|
||||||
console.log(res);
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -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;
|
|
||||||
@@ -1 +1 @@
|
|||||||
export const API_URL = `http://localhost:${process.env.NEXT_PUBLIC_BACKEND_PORT}`;
|
export const API_URL = process.env.NEXT_PUBLIC_API_URL ?? "";
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import IUser from "./interfaces/IUser";
|
|||||||
|
|
||||||
export async function middleware(request: NextRequest) {
|
export async function middleware(request: NextRequest) {
|
||||||
const sessionCookie = request.cookies.get("auth_token")?.value;
|
const sessionCookie = request.cookies.get("auth_token")?.value;
|
||||||
|
// console.log(sessionCookie);
|
||||||
if (!sessionCookie) {
|
if (!sessionCookie) {
|
||||||
return NextResponse.redirect(
|
return NextResponse.redirect(
|
||||||
new URL(
|
new URL(
|
||||||
@@ -15,18 +16,22 @@ export async function middleware(request: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
console.log(API_URL);
|
||||||
const res = await fetch(`${API_URL}/users/me`, {
|
const res = await fetch(`${API_URL}/users/me`, {
|
||||||
headers: { Authorization: `Bearer ${sessionCookie}` },
|
headers: { Authorization: `Bearer ${sessionCookie}` },
|
||||||
});
|
});
|
||||||
const js: ApiResponse<IUser> = await res.json();
|
const js: ApiResponse<IUser> = await res.json();
|
||||||
if (js.status === "Error")
|
if (js.status === "Error") {
|
||||||
|
console.log(js.message);
|
||||||
return NextResponse.redirect(
|
return NextResponse.redirect(
|
||||||
new URL(
|
new URL(
|
||||||
`/login?redirectTo=${encodeURIComponent(request.url)}`,
|
`/login?redirectTo=${encodeURIComponent(request.url)}`,
|
||||||
request.url,
|
request.url,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
console.log(e);
|
||||||
return NextResponse.redirect(
|
return NextResponse.redirect(
|
||||||
new URL(
|
new URL(
|
||||||
`/login?redirectTo=${encodeURIComponent(request.url)}`,
|
`/login?redirectTo=${encodeURIComponent(request.url)}`,
|
||||||
|
|||||||
@@ -1,8 +1,17 @@
|
|||||||
import type { NextConfig } from "next";
|
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 = {
|
const nextConfig: NextConfig = {
|
||||||
/* config options here */
|
/* config options here */
|
||||||
output: "standalone",
|
output: "standalone",
|
||||||
|
// webpack: (config) => {
|
||||||
|
// config.resolve.alias["@"] = path.resolve(__dirname, "./");
|
||||||
|
// return config;
|
||||||
|
// },
|
||||||
images: {
|
images: {
|
||||||
remotePatterns: [
|
remotePatterns: [
|
||||||
{
|
{
|
||||||
@@ -13,6 +22,7 @@ const nextConfig: NextConfig = {
|
|||||||
},
|
},
|
||||||
env: {
|
env: {
|
||||||
NEXT_PUBLIC_BACKEND_PORT: process.env.BACKEND_PORT,
|
NEXT_PUBLIC_BACKEND_PORT: process.env.BACKEND_PORT,
|
||||||
|
NEXT_PUBLIC_API_URL: apiUrl,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
84
init.py
Normal file
84
init.py
Normal 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()
|
||||||
4
init.sh
4
init.sh
@@ -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
|
|
||||||
11
nginx.conf
11
nginx.conf
@@ -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
20
nginx/default.conf
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
20
nginx/default.conf.template
Normal file
20
nginx/default.conf.template
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user