Install Nuxt.js + Strapi
- Install node.js

Node.js versions get updated frequently. Always check the official Node.js website for the latest LTS version.
cmd /c "curl -L -o %TEMP%\node-lts.msi https://nodejs.org/dist/v22.11.0/node-v22.11.0-x64.msi && start /wait msiexec /i %TEMP%\node-lts.msi /passive && del %TEMP%\node-lts.msi"
- Source: https://nodejs.org/dist
- Create Project Folders
Run the following command to create separate frontend and backend directories:
mkdir frontend backend
After running the command, your project structure should look like this:
myproject/
├── frontend/ # Frontend code (Nuxt.js)
├── backend/ # Backend code (Strapi, Directus or other backend framework)
Nuxt Launcher
Download nuxt_launcher.sh then drop it into the nuxt folder
sudo chmod +x nuxt_launcher.sh && sudo ./nuxt_launcher.sh
Install Nuxt.js
To create a new Nuxt.js project with preset answers (skipping the interactive prompts) and without TailwindCSS (recommended to install separately as a plugin), use:
npx nuxi@latest init frontend --package-manager npm --no-tailwind --git
Install plugins
Nuxt tailwindcss
npx nuxi@latest module add tailwindcss
Nuxt i18n
npx nuxi@latest module add @nuxtjs/i18n
Nuxt Icon
npx nuxi module add icon
- Source: https://nuxt.com/modules/icon
Nuxt Scripts
npx nuxi@latest module add scripts
Nuxt SEO
Nuxt Robots
npx nuxi module add robots
Nuxt Sitemap
npx nuxi module add @nuxtjs/sitemap
Nuxt OG Image
npx nuxi module add og-image
Nuxt Schemaorg
npx nuxi module add schema-org
Nuxt Link Checker
npx nuxi module add link-checker
Nuxt SEO Utils
npx nuxi module add nuxt-seo-utils
Nuxt Site Config
npx nuxi module add site-config
FRONTEND - NUXT 3
dockerfile.dev
# Use Node.js LTS version
FROM node:22
# Set working directory
WORKDIR /app
# Copy package.json and package-lock.json
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy the rest of the application code
COPY . .
# Expose the development server port
EXPOSE 3000
# Start the development server
CMD ["npm", "run", "dev"]
dockerfile.prod
# Stage 1: Build the application
FROM node:22.11.0-alpine as builder
# Create directories for the builder and app
RUN mkdir -p /usr/src/app /usr/src/builder
# Set working directory for the builder
WORKDIR /usr/src/builder
# Copy package.json and package-lock.json
COPY package*.json ./
# Install all dependencies (including dev dependencies)
RUN npm install
# Copy the rest of the application code
COPY . .
# Build the application
RUN npm run build
# Copy the built files to the app directory
RUN cp -r /usr/src/builder/.output /usr/src/app
# Stage 2: Serve the application
FROM node:22.11.0-alpine
# Set working directory for the app
WORKDIR /usr/src/app
# Copy built files from the builder stage
COPY --from=builder /usr/src/app/.output /usr/src/app/.output
# Install only production dependencies
COPY package*.json ./
RUN npm install --omit=dev
# Expose the production server port
EXPOSE 3000
# Start the production server
CMD ["node", "/usr/src/app/.output/server/index.mjs"]
BACKEND - Strapi
cd myproject
Install mail plugin
npm install @strapi/provider-email-nodemailer
dockerfile.dev
FROM node:20-alpine
# Installing libvips-dev for sharp Compatibility
RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev nasm bash vips-dev git
ARG NODE_ENV=development
ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/
COPY package.json package-lock.json ./
RUN npm install -g node-gyp
RUN npm config set fetch-retry-maxtimeout 600000 -g && npm install
ENV PATH=/opt/node_modules/.bin:$PATH
WORKDIR /opt/app
COPY . .
RUN chown -R node:node /opt/app
USER node
RUN ["npm", "run", "build"]
EXPOSE 1337
CMD ["npm", "run", "develop"]
dockerfile.prod
# Creating multi-stage build for production
FROM node:20-alpine as build
RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev vips-dev git > /dev/null 2>&1
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/
COPY package.json package-lock.json ./
RUN npm install -g node-gyp
RUN npm config set fetch-retry-maxtimeout 600000 -g && npm install --only=production
ENV PATH=/opt/node_modules/.bin:$PATH
WORKDIR /opt/app
COPY . .
RUN npm run build
# Creating final production image
FROM node:20-alpine
RUN apk add --no-cache vips-dev
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/
COPY --from=build /opt/node_modules ./node_modules
WORKDIR /opt/app
COPY --from=build /opt/app ./
ENV PATH=/opt/node_modules/.bin:$PATH
RUN chown -R node:node /opt/app
USER node
EXPOSE 1337
CMD ["npm", "run", "start"]
env
nano .env
# .env.example
# This file provides a template for creating a .env file with environment variables
# for the Docker Compose setup in the project. Copy this file to .env
# and fill in the appropriate values for your environment. Do not commit the .env
# file to version control.
# Frontend - Development
FRONTEND_DEV_TZ=Europe/Amsterdam # Timezone for the frontend development container
FRONTEND_DEV_NODE_ENV=development # Node environment (e.g., development)
FRONTEND_DEV_NUXT_PUBLIC_SITE_URL=http://0.0.0.0:3000 # Public URL for the frontend site in development
FRONTEND_DEV_NUXT_PUBLIC_STRAPI_URL=http://backend:1337 # URL for the Strapi backend in development
FRONTEND_DEV_NUXT_PUBLIC_TURNSTILE_SITE_KEY=3x00000000000000000000FF # Cloudflare Turnstile site key for development (get from https://developers.cloudflare.com/turnstile)
FRONTEND_DEV_NUXT_TURNSTILE_SECRET_KEY= # Cloudflare Turnstile secret key for development (leave empty or get from Cloudflare)
FRONTEND_DEV_API_DISCORD_WEBHOOK_URL= # Discord webhook URL for API notifications in development (optional)
FRONTEND_DEV_NUXT_PUBLIC_SCRIPTS_MATOMO_ANALYTICS_CLOUD_ID= # Matomo Analytics Cloud ID for development (get from Matomo dashboard)
FRONTEND_DEV_NUXT_PUBLIC_SCRIPTS_GOOGLE_ANALYTICS_ID= # Google Analytics ID for development (get from Google Analytics dashboard)
FRONTEND_DEV_USE_CLOUDFLARE_IP=true # Use Cloudflare's IPs to get the real user IP
# Frontend - Staging
FRONTEND_STAGE_TZ=Europe/Amsterdam # Timezone for the frontend staging container
FRONTEND_STAGE_NODE_ENV=production # Node environment (e.g., production)
FRONTEND_STAGE_NUXT_PUBLIC_SITE_URL=https://staging.example.com # Public URL for the frontend site in staging
FRONTEND_STAGE_NUXT_PUBLIC_STRAPI_URL=https://backend.example.com # URL for the Strapi backend in staging
FRONTEND_STAGE_NUXT_PUBLIC_TURNSTILE_SITE_KEY= # Cloudflare Turnstile site key for staging (get from https://dash.cloudflare.com)
FRONTEND_STAGE_NUXT_TURNSTILE_SECRET_KEY= # Cloudflare Turnstile secret key for staging (get from Cloudflare)
FRONTEND_STAGE_NUXT_PUBLIC_PDF_TOKEN= # Token for PDF generation in staging (generate a secure token)
FRONTEND_STAGE_API_DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/... # Discord webhook URL for API notifications in staging
FRONTEND_STAGE_NUXT_PUBLIC_SCRIPTS_MATOMO_ANALYTICS_CLOUD_ID= # Matomo Analytics Cloud ID for staging (get from Matomo dashboard)
FRONTEND_STAGE_NUXT_PUBLIC_SCRIPTS_GOOGLE_ANALYTICS_ID= # Google Analytics ID for staging (get from Google Analytics dashboard)
FRONTEND_STAGE_USE_CLOUDFLARE_IP=true # Use Cloudflare's IPs to get the real user IP
# Frontend - Production
FRONTEND_PROD_TZ=Europe/Amsterdam # Timezone for the frontend production container
FRONTEND_PROD_NODE_ENV=production # Node environment (e.g., production)
FRONTEND_PROD_NUXT_PUBLIC_SITE_URL=https://example.com # Public URL for the frontend site in production
FRONTEND_PROD_NUXT_PUBLIC_STRAPI_URL=https://backend.example.com # URL for the Strapi backend in production
FRONTEND_PROD_NUXT_PUBLIC_TURNSTILE_SITE_KEY= # Cloudflare Turnstile site key for production (get from https://dash.cloudflare.com)
FRONTEND_PROD_NUXT_TURNSTILE_SECRET_KEY= # Cloudflare Turnstile secret key for production (get from Cloudflare)
FRONTEND_PROD_NUXT_PUBLIC_PDF_TOKEN= # Token for PDF generation in production (generate a secure token)
FRONTEND_PROD_API_DISCORD_WEBHOOK_URL= # Discord webhook URL for API notifications in production
FRONTEND_PROD_NUXT_PUBLIC_SCRIPTS_MATOMO_ANALYTICS_CLOUD_ID= # Matomo Analytics Cloud ID for production (get from Matomo dashboard)
FRONTEND_PROD_NUXT_PUBLIC_SCRIPTS_GOOGLE_ANALYTICS_ID= # Google Analytics ID for production (get from Google Analytics dashboard)
FRONTEND_PROD_USE_CLOUDFLARE_IP=true # Use Cloudflare's IPs to get the real user IP
# Backend - Development
BACKEND_DEV_HOST=0.0.0.0 # Host for Strapi server in development
BACKEND_DEV_PORT=1337 # Port for Strapi server in development
BACKEND_DEV_DATABASE_CLIENT=postgres # Database client (e.g., postgres)
BACKEND_DEV_DATABASE_HOST=db # Database host (e.g., db for Docker Compose service name)
BACKEND_DEV_DATABASE_PORT=5432 # Database port
BACKEND_DEV_DATABASE_NAME=strapi # Database name
BACKEND_DEV_DATABASE_USERNAME=strapi # Database username
BACKEND_DEV_DATABASE_PASSWORD=your_secure_password # Database password (set a secure password)
BACKEND_DEV_DATABASE_SSL=false # Enable SSL for database connection
BACKEND_DEV_JWT_SECRET=your_jwt_secret # JWT secret for Strapi authentication (generate a secure random string)
BACKEND_DEV_ADMIN_JWT_SECRET=your_admin_jwt_secret # Admin JWT secret for Strapi admin panel (generate a secure random string)
BACKEND_DEV_APP_KEYS=your_app_key_1,your_app_key_2 # App keys for Strapi (generate two secure random strings, comma-separated)
BACKEND_DEV_TRANSFER_TOKEN_SALT=your_transfer_token_salt # Transfer token salt for Strapi (generate a secure random string)
BACKEND_DEV_API_TOKEN_SALT=your_api_token_salt # API token salt for Strapi (generate a secure random string)
BACKEND_DEV_NODE_ENV=development # Node environment for backend development
# Backend - Production/Staging
BACKEND_PROD_HOST=0.0.0.0 # Host for Strapi server in production/staging
BACKEND_PROD_PORT=1337 # Port for Strapi server in production/staging
BACKEND_PROD_DATABASE_CLIENT=postgres # Database client (e.g., postgres)
BACKEND_PROD_DATABASE_HOST=db # Database host (e.g., db for Docker Compose service name)
BACKEND_PROD_DATABASE_PORT=5432 # Database port
BACKEND_PROD_DATABASE_NAME=strapi # Database name
BACKEND_PROD_DATABASE_USERNAME=strapi # Database username
BACKEND_PROD_DATABASE_PASSWORD=your_secure_password # Database password (set a secure password)
BACKEND_PROD_DATABASE_SSL=false # Enable SSL for database connection
BACKEND_PROD_JWT_SECRET=your_jwt_secret # JWT secret for Strapi authentication (generate a secure random string)
BACKEND_PROD_ADMIN_JWT_SECRET=your_admin_jwt_secret # Admin JWT secret for Strapi admin panel (generate a secure random string)
BACKEND_PROD_APP_KEYS=your_app_key_1,your_app_key_2 # App keys for Strapi (generate two secure random strings, comma-separated)
BACKEND_PROD_TRANSFER_TOKEN_SALT=your_transfer_token_salt # Transfer token salt for Strapi (generate a secure random string)
BACKEND_PROD_API_TOKEN_SALT=your_api_token_salt # API token salt for Strapi (generate a secure random string)
BACKEND_PROD_NODE_ENV=production # Node environment for backend production/staging
# SMTP Configuration (shared across all services)
SMTP_HOST=mail.example.com # SMTP server hostname
SMTP_PORT=465 # Port (465 for implicit TLS, 587 for STARTTLS)
[email protected] # SMTP username
SMTP_PASSWORD=your_smtp_password # SMTP password
SMTP_AUTH_TYPE=login # Auth type ('login' or 'oauth2')
SMTP_AUTH_METHOD=PLAIN # Preferred auth method (e.g., PLAIN, LOGIN)
SMTP_SECURE=true # True for implicit TLS (465), false for STARTTLS (587)
SMTP_TLS_SERVERNAME= # Hostname for TLS validation if host is IP (optional)
SMTP_TLS_REJECT_UNAUTHORIZED=true # Reject invalid/self-signed certs
SMTP_TLS_IGNORE=false # Skip TLS if supported (rarely used)
SMTP_TLS_REQUIRE=false # Force STARTTLS even if not advertised
SMTP_CLIENT_NAME= # Client hostname for server ID (optional)
SMTP_LOCAL_ADDRESS= # Local interface to bind (optional)
SMTP_CONNECTION_TIMEOUT=120000 # Connection timeout (ms, default 2 min)
SMTP_GREETING_TIMEOUT=30000 # Greeting timeout (ms, default 30s)
SMTP_SOCKET_TIMEOUT=600000 # Inactivity timeout (ms, default 10 min)
SMTP_DNS_TIMEOUT=30000 # DNS resolution timeout (ms, default 30s)
SMTP_LOGGER=false # Enable logging (true for console)
SMTP_DEBUG=false # Log SMTP traffic (true) or events (false)
SMTP_DISABLE_FILE_ACCESS=false # Prevent file-based content
SMTP_DISABLE_URL_ACCESS=false # Prevent URL-based content
SMTP_POOL=false # Enable connection pooling
SMTP_PROXY= # Proxy URL (e.g., http://proxy:8080, optional)
[email protected] # Default 'From' address
[email protected] # Default 'Reply-To' address
# Database
DB_POSTGRES_USER=strapi # PostgreSQL user
DB_POSTGRES_PASSWORD=your_secure_password # PostgreSQL password (set a secure password)
DB_POSTGRES_DB=strapi # PostgreSQL database name
To quickly generate all the required tokens, run the following command in the terminal:
echo "JWT_SECRET=\"$(openssl rand -hex 32)\""
echo "ADMIN_JWT_SECRET=\"$(openssl rand -hex 32)\""
echo "APP_KEYS=\"$(openssl rand -hex 32),$(openssl rand -hex 32)\""
echo "TRANSFER_TOKEN_SALT=\"$(openssl rand -base64 32)\""
echo "API_TOKEN_SALT=\"$(openssl rand -base64 16)\""
docker compose
nano docker-compose.yml
services:
# Frontend - Development
frontend_dev:
profiles: ["dev"] # Use `docker compose --profile dev up --build` to start
container_name: nuxt_dev_myproject
restart: unless-stopped
build:
context: ./frontend
dockerfile: dockerfile.dev
ports:
- "3000:3000"
volumes:
- ./frontend:/app
- /app/node_modules
environment:
TZ: ${FRONTEND_DEV_TZ}
NODE_ENV: ${FRONTEND_DEV_NODE_ENV}
NUXT_PUBLIC_SITE_URL: ${FRONTEND_DEV_NUXT_PUBLIC_SITE_URL}
NUXT_PUBLIC_STRAPI_URL: ${FRONTEND_DEV_NUXT_PUBLIC_STRAPI_URL}
NUXT_PUBLIC_TURNSTILE_SITE_KEY: ${FRONTEND_DEV_NUXT_PUBLIC_TURNSTILE_SITE_KEY}
NUXT_TURNSTILE_SECRET_KEY: ${FRONTEND_DEV_NUXT_TURNSTILE_SECRET_KEY}
API_DISCORD_WEBHOOK_URL: ${FRONTEND_DEV_API_DISCORD_WEBHOOK_URL}
NUXT_PUBLIC_SCRIPTS_MATOMO_ANALYTICS_CLOUD_ID: ${FRONTEND_DEV_NUXT_PUBLIC_SCRIPTS_MATOMO_ANALYTICS_CLOUD_ID}
NUXT_PUBLIC_SCRIPTS_GOOGLE_ANALYTICS_ID: ${FRONTEND_DEV_NUXT_PUBLIC_SCRIPTS_GOOGLE_ANALYTICS_ID}
USE_CLOUDFLARE_IP: ${FRONTEND_DEV_USE_CLOUDFLARE_IP}
depends_on:
- backend_dev
# Frontend - Staging
frontend_stage:
profiles: ["stage"] # Use `docker compose --profile stage up --build` to start
container_name: nuxt_stage_myproject
restart: unless-stopped
build:
context: ./frontend
dockerfile: dockerfile.prod
ports:
- "8171:3000"
volumes:
- ./config/frontend:/etc/config
environment:
TZ: ${FRONTEND_STAGE_TZ}
NODE_ENV: ${FRONTEND_STAGE_NODE_ENV}
NUXT_PUBLIC_SITE_URL: ${FRONTEND_STAGE_NUXT_PUBLIC_SITE_URL}
NUXT_PUBLIC_STRAPI_URL: ${FRONTEND_STAGE_NUXT_PUBLIC_STRAPI_URL}
NUXT_PUBLIC_TURNSTILE_SITE_KEY: ${FRONTEND_STAGE_NUXT_PUBLIC_TURNSTILE_SITE_KEY}
NUXT_TURNSTILE_SECRET_KEY: ${FRONTEND_STAGE_NUXT_TURNSTILE_SECRET_KEY}
NUXT_PUBLIC_PDF_TOKEN: ${FRONTEND_STAGE_NUXT_PUBLIC_PDF_TOKEN}
API_DISCORD_WEBHOOK_URL: ${FRONTEND_STAGE_API_DISCORD_WEBHOOK_URL}
NUXT_PUBLIC_SCRIPTS_MATOMO_ANALYTICS_CLOUD_ID: ${FRONTEND_STAGE_NUXT_PUBLIC_SCRIPTS_MATOMO_ANALYTICS_CLOUD_ID}
NUXT_PUBLIC_SCRIPTS_GOOGLE_ANALYTICS_ID: ${FRONTEND_STAGE_NUXT_PUBLIC_SCRIPTS_GOOGLE_ANALYTICS_ID}
USE_CLOUDFLARE_IP: ${FRONTEND_STAGE_USE_CLOUDFLARE_IP}
SMTP_HOST: ${SMTP_HOST}
SMTP_PORT: ${SMTP_PORT}
SMTP_USERNAME: ${SMTP_USERNAME}
SMTP_PASSWORD: ${SMTP_PASSWORD}
SMTP_AUTH_TYPE: ${SMTP_AUTH_TYPE}
SMTP_AUTH_METHOD: ${SMTP_AUTH_METHOD}
SMTP_SECURE: ${SMTP_SECURE}
SMTP_TLS_SERVERNAME: ${SMTP_TLS_SERVERNAME}
SMTP_TLS_REJECT_UNAUTHORIZED: ${SMTP_TLS_REJECT_UNAUTHORIZED}
SMTP_TLS_IGNORE: ${SMTP_TLS_IGNORE}
SMTP_TLS_REQUIRE: ${SMTP_TLS_REQUIRE}
SMTP_CLIENT_NAME: ${SMTP_CLIENT_NAME}
SMTP_LOCAL_ADDRESS: ${SMTP_LOCAL_ADDRESS}
SMTP_CONNECTION_TIMEOUT: ${SMTP_CONNECTION_TIMEOUT}
SMTP_GREETING_TIMEOUT: ${SMTP_GREETING_TIMEOUT}
SMTP_SOCKET_TIMEOUT: ${SMTP_SOCKET_TIMEOUT}
SMTP_DNS_TIMEOUT: ${SMTP_DNS_TIMEOUT}
SMTP_LOGGER: ${SMTP_LOGGER}
SMTP_DEBUG: ${SMTP_DEBUG}
SMTP_DISABLE_FILE_ACCESS: ${SMTP_DISABLE_FILE_ACCESS}
SMTP_DISABLE_URL_ACCESS: ${SMTP_DISABLE_URL_ACCESS}
SMTP_POOL: ${SMTP_POOL}
SMTP_PROXY: ${SMTP_PROXY}
SMTP_FROM: ${SMTP_FROM}
SMTP_REPLY_TO: ${SMTP_REPLY_TO}
depends_on:
- backend_prod
# Frontend - Production
frontend_prod:
profiles: ["prod"] # Use `docker compose --profile prod up --build` to start
container_name: nuxt_prod_myproject
restart: unless-stopped
build:
context: ./frontend
dockerfile: dockerfile.prod
ports:
- "8170:3000"
volumes:
- ./config/frontend:/etc/config
environment:
TZ: ${FRONTEND_PROD_TZ}
NODE_ENV: ${FRONTEND_PROD_NODE_ENV}
NUXT_PUBLIC_SITE_URL: ${FRONTEND_PROD_NUXT_PUBLIC_SITE_URL}
NUXT_PUBLIC_STRAPI_URL: ${FRONTEND_PROD_NUXT_PUBLIC_STRAPI_URL}
NUXT_PUBLIC_TURNSTILE_SITE_KEY: ${FRONTEND_PROD_NUXT_PUBLIC_TURNSTILE_SITE_KEY}
NUXT_TURNSTILE_SECRET_KEY: ${FRONTEND_PROD_NUXT_TURNSTILE_SECRET_KEY}
NUXT_PUBLIC_PDF_TOKEN: ${FRONTEND_PROD_NUXT_PUBLIC_PDF_TOKEN}
API_DISCORD_WEBHOOK_URL: ${FRONTEND_PROD_API_DISCORD_WEBHOOK_URL}
NUXT_PUBLIC_SCRIPTS_MATOMO_ANALYTICS_CLOUD_ID: ${FRONTEND_PROD_NUXT_PUBLIC_SCRIPTS_MATOMO_ANALYTICS_CLOUD_ID}
NUXT_PUBLIC_SCRIPTS_GOOGLE_ANALYTICS_ID: ${FRONTEND_PROD_NUXT_PUBLIC_SCRIPTS_GOOGLE_ANALYTICS_ID}
USE_CLOUDFLARE_IP: ${FRONTEND_PROD_USE_CLOUDFLARE_IP}
SMTP_HOST: ${SMTP_HOST}
SMTP_PORT: ${SMTP_PORT}
SMTP_USERNAME: ${SMTP_USERNAME}
SMTP_PASSWORD: ${SMTP_PASSWORD}
SMTP_AUTH_TYPE: ${SMTP_AUTH_TYPE}
SMTP_AUTH_METHOD: ${SMTP_AUTH_METHOD}
SMTP_SECURE: ${SMTP_SECURE}
SMTP_TLS_SERVERNAME: ${SMTP_TLS_SERVERNAME}
SMTP_TLS_REJECT_UNAUTHORIZED: ${SMTP_TLS_REJECT_UNAUTHORIZED}
SMTP_TLS_IGNORE: ${SMTP_TLS_IGNORE}
SMTP_TLS_REQUIRE: ${SMTP_TLS_REQUIRE}
SMTP_CLIENT_NAME: ${SMTP_CLIENT_NAME}
SMTP_LOCAL_ADDRESS: ${SMTP_LOCAL_ADDRESS}
SMTP_CONNECTION_TIMEOUT: ${SMTP_CONNECTION_TIMEOUT}
SMTP_GREETING_TIMEOUT: ${SMTP_GREETING_TIMEOUT}
SMTP_SOCKET_TIMEOUT: ${SMTP_SOCKET_TIMEOUT}
SMTP_DNS_TIMEOUT: ${SMTP_DNS_TIMEOUT}
SMTP_LOGGER: ${SMTP_LOGGER}
SMTP_DEBUG: ${SMTP_DEBUG}
SMTP_DISABLE_FILE_ACCESS: ${SMTP_DISABLE_FILE_ACCESS}
SMTP_DISABLE_URL_ACCESS: ${SMTP_DISABLE_URL_ACCESS}
SMTP_POOL: ${SMTP_POOL}
SMTP_PROXY: ${SMTP_PROXY}
SMTP_FROM: ${SMTP_FROM}
SMTP_REPLY_TO: ${SMTP_REPLY_TO}
depends_on:
- backend_prod
# Backend - Strapi
backend_dev:
profiles: ["dev"]
container_name: strapi_backend
restart: unless-stopped
build:
context: ./backend
dockerfile: dockerfile.dev
environment:
HOST: ${BACKEND_DEV_HOST}
PORT: ${BACKEND_DEV_PORT}
DATABASE_CLIENT: ${BACKEND_DEV_DATABASE_CLIENT}
DATABASE_HOST: ${BACKEND_DEV_DATABASE_HOST}
DATABASE_PORT: ${BACKEND_DEV_DATABASE_PORT}
DATABASE_NAME: ${BACKEND_DEV_DATABASE_NAME}
DATABASE_USERNAME: ${BACKEND_DEV_DATABASE_USERNAME}
DATABASE_PASSWORD: ${BACKEND_DEV_DATABASE_PASSWORD}
DATABASE_SSL: ${BACKEND_DEV_DATABASE_SSL}
JWT_SECRET: ${BACKEND_DEV_JWT_SECRET}
ADMIN_JWT_SECRET: ${BACKEND_DEV_ADMIN_JWT_SECRET}
APP_KEYS: ${BACKEND_DEV_APP_KEYS}
TRANSFER_TOKEN_SALT: ${BACKEND_DEV_TRANSFER_TOKEN_SALT}
API_TOKEN_SALT: ${BACKEND_DEV_API_TOKEN_SALT}
NODE_ENV: ${BACKEND_DEV_NODE_ENV}
SMTP_HOST: ${SMTP_HOST}
SMTP_PORT: ${SMTP_PORT}
SMTP_USERNAME: ${SMTP_USERNAME}
SMTP_PASSWORD: ${SMTP_PASSWORD}
SMTP_AUTH_TYPE: ${SMTP_AUTH_TYPE}
SMTP_AUTH_METHOD: ${SMTP_AUTH_METHOD}
SMTP_SECURE: ${SMTP_SECURE}
SMTP_TLS_SERVERNAME: ${SMTP_TLS_SERVERNAME}
SMTP_TLS_REJECT_UNAUTHORIZED: ${SMTP_TLS_REJECT_UNAUTHORIZED}
SMTP_TLS_IGNORE: ${SMTP_TLS_IGNORE}
SMTP_TLS_REQUIRE: ${SMTP_TLS_REQUIRE}
SMTP_CLIENT_NAME: ${SMTP_CLIENT_NAME}
SMTP_LOCAL_ADDRESS: ${SMTP_LOCAL_ADDRESS}
SMTP_CONNECTION_TIMEOUT: ${SMTP_CONNECTION_TIMEOUT}
SMTP_GREETING_TIMEOUT: ${SMTP_GREETING_TIMEOUT}
SMTP_SOCKET_TIMEOUT: ${SMTP_SOCKET_TIMEOUT}
SMTP_DNS_TIMEOUT: ${SMTP_DNS_TIMEOUT}
SMTP_LOGGER: ${SMTP_LOGGER}
SMTP_DEBUG: ${SMTP_DEBUG}
SMTP_DISABLE_FILE_ACCESS: ${SMTP_DISABLE_FILE_ACCESS}
SMTP_DISABLE_URL_ACCESS: ${SMTP_DISABLE_URL_ACCESS}
SMTP_POOL: ${SMTP_POOL}
SMTP_PROXY: ${SMTP_PROXY}
SMTP_FROM: ${SMTP_FROM}
SMTP_REPLY_TO: ${SMTP_REPLY_TO}
volumes:
- ./backend/public/uploads:/opt/app/public/uploads
- ./backend/config:/opt/app/config
- ./backend/src:/opt/app/src
- ./backend/package.json:/opt/package.json
# - ./backend/yarn.lock:/opt/yarn.lock
# - ./backend/.env:/opt/app/.env
ports:
- "1447:1337"
depends_on:
- db
backend_prod:
profiles: ["prod", "stage"]
container_name: strapi_backend
restart: unless-stopped
build:
context: ./backend
dockerfile: dockerfile.dev
environment:
HOST: ${BACKEND_PROD_HOST}
PORT: ${BACKEND_PROD_PORT}
DATABASE_CLIENT: ${BACKEND_PROD_DATABASE_CLIENT}
DATABASE_HOST: ${BACKEND_PROD_DATABASE_HOST}
DATABASE_PORT: ${BACKEND_PROD_DATABASE_PORT}
DATABASE_NAME: ${BACKEND_PROD_DATABASE_NAME}
DATABASE_USERNAME: ${BACKEND_PROD_DATABASE_USERNAME}
DATABASE_PASSWORD: ${BACKEND_PROD_DATABASE_PASSWORD}
DATABASE_SSL: ${BACKEND_PROD_DATABASE_SSL}
JWT_SECRET: ${BACKEND_PROD_JWT_SECRET}
ADMIN_JWT_SECRET: ${BACKEND_PROD_ADMIN_JWT_SECRET}
APP_KEYS: ${BACKEND_PROD_APP_KEYS}
TRANSFER_TOKEN_SALT: ${BACKEND_PROD_TRANSFER_TOKEN_SALT}
API_TOKEN_SALT: ${BACKEND_PROD_API_TOKEN_SALT}
NODE_ENV: ${BACKEND_PROD_NODE_ENV}
SMTP_HOST: ${SMTP_HOST}
SMTP_PORT: ${SMTP_PORT}
SMTP_USERNAME: ${SMTP_USERNAME}
SMTP_PASSWORD: ${SMTP_PASSWORD}
SMTP_AUTH_TYPE: ${SMTP_AUTH_TYPE}
SMTP_AUTH_METHOD: ${SMTP_AUTH_METHOD}
SMTP_SECURE: ${SMTP_SECURE}
SMTP_TLS_SERVERNAME: ${SMTP_TLS_SERVERNAME}
SMTP_TLS_REJECT_UNAUTHORIZED: ${SMTP_TLS_REJECT_UNAUTHORIZED}
SMTP_TLS_IGNORE: ${SMTP_TLS_IGNORE}
SMTP_TLS_REQUIRE: ${SMTP_TLS_REQUIRE}
SMTP_CLIENT_NAME: ${SMTP_CLIENT_NAME}
SMTP_LOCAL_ADDRESS: ${SMTP_LOCAL_ADDRESS}
SMTP_CONNECTION_TIMEOUT: ${SMTP_CONNECTION_TIMEOUT}
SMTP_GREETING_TIMEOUT: ${SMTP_GREETING_TIMEOUT}
SMTP_SOCKET_TIMEOUT: ${SMTP_SOCKET_TIMEOUT}
SMTP_DNS_TIMEOUT: ${SMTP_DNS_TIMEOUT}
SMTP_LOGGER: ${SMTP_LOGGER}
SMTP_DEBUG: ${SMTP_DEBUG}
SMTP_DISABLE_FILE_ACCESS: ${SMTP_DISABLE_FILE_ACCESS}
SMTP_DISABLE_URL_ACCESS: ${SMTP_DISABLE_URL_ACCESS}
SMTP_POOL: ${SMTP_POOL}
SMTP_PROXY: ${SMTP_PROXY}
SMTP_FROM: ${SMTP_FROM}
SMTP_REPLY_TO: ${SMTP_REPLY_TO}
ports:
- "8178:1337"
volumes:
- ./backend/public/uploads:/opt/app/public/uploads
- ./backend/config:/opt/app/config
- ./backend/src:/opt/app/src
- ./backend/package.json:/opt/package.json
db:
image: postgres:14-alpine
container_name: strapi_postgresql
restart: unless-stopped
volumes:
- ./backend/db:/var/lib/postgresql/data
environment:
POSTGRES_USER: ${DB_POSTGRES_USER}
POSTGRES_PASSWORD: ${DB_POSTGRES_PASSWORD}
POSTGRES_DB: ${DB_POSTGRES_DB}
If both profiles are enabled use the following command to run a service
Development container
docker compose --profile dev up -d --build
Production container
docker compose --profile prod up -d --build
If one of the profiles are disabled then use the following command to run the disabled profile by default
docker compose up -d
Configure strapi in nuxt
nano nuxt.config.ts
strapi: {
// Strapi URL with fallback
url: process.env.NUXT_PUBLIC_STRAPI_URL || "http://localhost:1330",
admin: (process.env.NUXT_PUBLIC_STRAPI_URL || "http://localhost:1330") + '/admin',
cookie: {
path: "/",
sameSite: true,
secure: process.env.NODE_ENV === "production",
maxAge: 60 * 60 * 24 * 7, // 1 week
}
},
BACKEND - Directus
Directus is a alternative backend to Strapi. If Strapi is not being used then try Directus
cd myproject
docker compose
nano docker-compose.yml
version: "3.8"
services:
db:
image: postgis/postgis:latest
container_name: directus_postgresql
restart: unless-stopped
# Required when running on platform other than amd64, like Apple M1/M2:
# platform: linux/amd64
volumes:
- ./backend/db:/var/lib/postgresql/data
environment:
POSTGRES_USER: "directus"
POSTGRES_PASSWORD: "directus"
POSTGRES_DB: "directus"
healthcheck:
test: ["CMD", "pg_isready", "--host=localhost", "--username=directus"]
interval: 10s
timeout: 5s
retries: 5
start_interval: 5s
start_period: 30s
cache:
image: redis:6
container_name: directus_redis
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "[ $$(redis-cli ping) = 'PONG' ]"]
interval: 10s
timeout: 5s
retries: 5
start_interval: 5s
start_period: 30s
directus:
image: directus/directus:latest
container_name: directus
restart: unless-stopped
ports:
- 8177:8055
volumes:
- ./backend/uploads:/directus/uploads
- ./backend/extensions:/directus/extensions
depends_on:
db:
condition: service_healthy
cache:
condition: service_healthy
environment:
# Make sure to set this in production
# (see https://docs.directus.io/self-hosted/config-options#general)
PUBLIC_URL: "https://backend.DOMAIN.COM"
ADMIN_EMAIL: "[email protected]"
ADMIN_PASSWORD: "admin"
SECRET: "wvNtegcb2HlDFABlxSz9e9mYpC17bzQDqM6x1XF9k"
DB_CLIENT: "pg"
DB_HOST: "db"
DB_PORT: "5432"
DB_DATABASE: "directus"
DB_USER: "directus"
DB_PASSWORD: "directus"
CACHE_ENABLED: "true"
CACHE_AUTO_PURGE: "true"
CACHE_STORE: "redis"
REDIS: "redis://cache:6379"
docker compose up -d
The following tutorial will show a alternative backend method to use with nuxt.js using Prisma as an ORM (Object-Relational Mapper) and Supabase as a Backend Service