A Comprehensive Overview of a Node.js TypeScript Project with DevOps: Structure, Code, and Configuration
Explore the essential components of building a robust Node.js TypeScript project integrated with DevOps practices. This guide provides a detailed breakdown of the project structure, complete with code snippets and configurations for each file and directory, empowering you to streamline development, testing, and deployment processes effectively. Whether you're a beginner or an experienced developer, this comprehensive overview will enhance your understanding of creating scalable applications in a modern development environment.
Project Structure
๐ node-typescript-project-with-devops/
โโโ ๐ node_modules # Node.js modules
โโโ ๐ .gitignore # Specifies files and directories to be ignored by Git
โโโ ๐ .dockerignore # Specifies files and directories to be ignored by Docker
โโโ ๐ .env # Environment variables file
โโโ ๐ example.env # Example environment variables file
โโโ ๐ uploads # Folder for uploaded files
โ โโโ ...
โโโ ๐ src
โ โโโ ๐ server.ts # Main entry point for the application
โ โโโ ๐ bin # Contains binaries or executable files
โ โ โโโ ๐ www # Start script for the server
โ โโโ ๐ config # Configuration files
โ โ โโโ ๐ redis.config # Redis configuration
โ โ โโโ ๐ mongo.config # MongoDB configuration
โ โ โโโ ๐ postgres.config # PostgreSQL configuration
โ โ โโโ ๐ nginx.conf # Nginx configuration file
โ โโโ ๐ controllers # Controller files
โ โ โโโ ๐ customer.ts # Customer-related controller
โ โ โโโ ๐ product.ts # Product-related controller
โ โ โโโ ...
โ โโโ ๐ middleware # Middleware files
โ โ โโโ ๐ auth.ts # Authentication middleware
โ โ โโโ ๐ logger.ts # Logger middleware
โ โ โโโ ...
โ โโโ ๐ models # Model files
โ โ โโโ ๐ customer.ts # Customer model
โ โ โโโ ๐ product.ts # Product model
โ โ โโโ ...
โ โโโ ๐ routes # Route files
โ โ โโโ ๐ api.ts # API routes
โ โ โโโ ๐ auth.ts # Authentication routes
โ โ โโโ ...
โ โโโ ๐ tests # Test files
โ โ โโโ ๐ unit # Unit tests
โ โ โโโ ๐ integration # Integration tests
โ โ โโโ ๐ e2e # End-to-end tests
โ โ โโโ ...
โ โโโ ๐ utils # Utility files
โ โโโ ๐ validation.ts # Validation utilities
โ โโโ ๐ helpers.ts # Helper functions
โ โโโ ...
โโโ ๐ Dockerfile # Dockerfile for building the Node.js app image
โโโ ๐ docker-compose.yml # Docker Compose configuration
โโโ ๐ nodemon.json # Nodemon configuration for development
โโโ ๐ package.json # Project dependencies and scripts
โโโ ๐ ansible # Ansible directory
โ โโโ ๐ deploy.yml # Ansible playbook for deployment
โ โโโ ๐ roles # Ansible roles (if any)
โ โโโ ...
โโโ ๐ helm # Helm chart directory
โโโ ๐ your-helm-chart/
โ โโโ ๐ charts # Charts for dependencies
โ โโโ ๐ templates # Template files for Kubernetes resources
โ โ โโโ ๐ deployment.yaml # Deployment configuration for Node.js app
โ โ โโโ ๐ service.yaml # Service configuration for exposing the Node.js app
โ โ โโโ ๐ ingress.yaml # Ingress configuration for Nginx
โ โ โโโ ๐ configmap.yaml # ConfigMap for environment variables
โ โโโ ๐ Chart.yaml # Metadata for your Helm chart
โ โโโ ๐ values.yaml # Default values for your templates
โโโ ๐ jenkins # Jenkins directory for pipeline configuration
โ โโโ ๐ Jenkinsfile # Declarative pipeline for Jenkins
โ โโโ ๐ jenkins-config.groovy # Configuration script for Jenkins setup
โ โโโ ๐ jobs # Jenkins job configuration files
โ โโโ ๐ build-node-app.xml # Jenkins job for building Node.js app
โ โโโ ๐ deploy-node-app.xml # Jenkins job for deploying Node.js app
Detailed File and Code Examples
1. .gitignore
node_modules/
dist/
.env
npm-debug.log
.DS_Store
uploads/
2. .dockerignore
node_modules
npm-debug.log
.git
.gitignore
Dockerfile
docker-compose.yml
3. .env
NODE_ENV=production
PORT=3000
MONGO_URI=mongodb://localhost:27017/mydatabase
REDIS_URL=redis://localhost:6379
POSTGRES_URI=postgresql://user:password@localhost:5432/mydatabase
JWT_SECRET=mysecret
4. example.env
NODE_ENV=development
PORT=3000
MONGO_URI=mongodb://localhost:27017/mydatabase
REDIS_URL=redis://localhost:6379
POSTGRES_URI=postgresql://user:password@localhost:5432/mydatabase
JWT_SECRET=mysecret
5. src/server.ts
import express from 'express';
import mongoose from 'mongoose';
import { json } from 'body-parser';
import { routes } from './routes/api';
import { connectRedis } from './config/redis.config';
import { connectMongo } from './config/mongo.config';
const app = express();
const PORT = process.env.PORT || 3000;
app.use(json());
app.use('/api', routes);
// MongoDB and Redis connection
connectMongo();
connectRedis();
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
6. src/bin/www
#!/usr/bin/env node
import app from '../server';
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server started on port ${PORT}`);
});
7. src/config/redis.config
import Redis from 'ioredis';
const redis = new Redis(process.env.REDIS_URL);
export const connectRedis = () => {
redis.on('connect', () => {
console.log('Connected to Redis');
});
redis.on('error', (err) => {
console.error('Redis error:', err);
});
};
8. src/config/mongo.config
import mongoose from 'mongoose';
export const connectMongo = async () => {
try {
await mongoose.connect(process.env.MONGO_URI);
console.log('Connected to MongoDB');
} catch (error) {
console.error('MongoDB connection error:', error);
}
};
9. src/config/postgres.config
// PostgreSQL configuration
// You can set up Sequelize or pg-promise here
10. src/config/nginx.conf
server {
listen 80;
location / {
proxy_pass http://localhost:3000; # Adjust according to your Node.js server
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
11. src/controllers/customer.ts
import { Request, Response } from 'express';
export const getCustomers = (req: Request, res: Response) => {
// Logic to get customers
};
export const createCustomer = (req: Request, res: Response) => {
// Logic to create a customer
};
12. src/controllers/product.ts
import { Request, Response } from 'express';
export const getProducts = (req: Request, res: Response) => {
// Logic to get products
};
export const createProduct = (req: Request, res: Response) => {
// Logic to create a product
};
13. src/middleware/auth.ts
import { Request, Response, NextFunction } from 'express';
export const authMiddleware = (req: Request, res: Response, next: NextFunction) => {
// Authentication logic
next();
};
14. src/middleware/logger.ts
import { Request, Response, NextFunction } from 'express';
export const loggerMiddleware = (req: Request, res: Response, next: NextFunction) => {
console.log(`${req.method} ${req.url}`);
next();
};
15. src/models/customer.ts
import mongoose, { Schema, Document } from 'mongoose';
export interface ICustomer extends Document {
name: string;
email: string;
}
const CustomerSchema: Schema = new Schema({
name: { type: String, required: true },
email: { type: String, required: true },
});
export const Customer = mongoose
.model<ICustomer>('Customer', CustomerSchema);
16. src/models/product.ts
import mongoose, { Schema, Document } from 'mongoose';
export interface IProduct extends Document {
title: string;
price: number;
}
const ProductSchema: Schema = new Schema({
title: { type: String, required: true },
price: { type: Number, required: true },
});
export const Product = mongoose.model<IProduct>('Product', ProductSchema);
17. src/routes/api.ts
import { Router } from 'express';
import { getCustomers, createCustomer } from '../controllers/customer';
import { getProducts, createProduct } from '../controllers/product';
const router = Router();
router.get('/customers', getCustomers);
router.post('/customers', createCustomer);
router.get('/products', getProducts);
router.post('/products', createProduct);
export const routes = router;
18. src/tests/unit/customer.test.ts
import { getCustomers } from '../../controllers/customer';
import { Request, Response } from 'express';
describe('Customer Controller', () => {
it('should get customers', () => {
const req = {} as Request;
const res = {
send: jest.fn(),
} as unknown as Response;
getCustomers(req, res);
expect(res.send).toHaveBeenCalled();
});
});
19. Dockerfile
# Use an official Node.js runtime as a parent image
FROM node:14
# Set the working directory
WORKDIR /usr/src/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 application port
EXPOSE 3000
# Command to run the application
CMD [ "npm", "start" ]
20. docker-compose.yml
version: '3.8'
services:
node-app:
build: .
ports:
- '3000:3000'
environment:
NODE_ENV: development
MONGO_URI: mongodb://mongo:27017/mydatabase
REDIS_URL: redis://redis:6379
POSTGRES_URI: postgresql://user:password@postgres:5432/mydatabase
depends_on:
- mongo
- redis
- postgres
mongo:
image: mongo
restart: always
ports:
- '27017:27017'
redis:
image: redis
restart: always
ports:
- '6379:6379'
postgres:
image: postgres
restart: always
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: mydatabase
ports:
- '5432:5432'
21. nodemon.json
{
"watch": ["src"],
"ext": "ts",
"exec": "ts-node src/server.ts"
}
22. package.json
{
"name": "node-typescript-project-with-devops",
"version": "1.0.0",
"scripts": {
"start": "ts-node src/server.ts",
"dev": "nodemon",
"test": "jest"
},
"dependencies": {
"express": "^4.17.1",
"mongoose": "^5.10.9",
"ioredis": "^4.17.3",
"dotenv": "^8.2.0",
"pg": "^8.5.1"
},
"devDependencies": {
"@types/express": "^4.17.11",
"@types/jest": "^26.0.0",
"jest": "^26.6.0",
"ts-jest": "^26.4.0",
"typescript": "^4.0.3",
"nodemon": "^2.0.4",
"ts-node": "^9.1.1"
}
}
23. ansible/deploy.yml
---
- hosts: all
tasks:
- name: Ensure Node.js is installed
apt:
name: nodejs
state: present
- name: Copy application files
copy:
src: /path/to/your/local/project/
dest: /path/to/remote/server/
- name: Install dependencies
command: npm install
args:
chdir: /path/to/remote/server/
24. helm/your-helm-chart/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-app
spec:
replicas: 2
selector:
matchLabels:
app: node-app
template:
metadata:
labels:
app: node-app
spec:
containers:
- name: node-app
image: your-node-app-image
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: "production"
- name: MONGO_URI
value: "mongodb://mongo:27017/mydatabase"
- name: REDIS_URL
value: "redis://redis:6379"
- name: POSTGRES_URI
value: "postgresql://user:password@postgres:5432/mydatabase"
25. helm/your-helm-chart/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: node-app
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 3000
selector:
app: node-app
26. jenkins/Jenkinsfile
pipeline {
agent any
stages {
stage('Build') {
steps {
script {
docker.build("your-node-app-image")
}
}
}
stage('Deploy') {
steps {
script {
sh 'docker-compose up -d'
}
}
}
}
}
27. jenkins/jenkins-config.groovy
// Jenkins configuration script for initial setup
Additional Configuration and Usage
-
Run the Application:
- Use
npm start
ornpm run dev
to start the application in development mode with Nodemon.
- Use
-
Docker:
- Build the Docker image with
docker build -t your-node-app-image .
- Run
docker-compose up
to start all services defined indocker-compose.yml
.
- Build the Docker image with
-
Ansible:
- Execute the Ansible playbook with
ansible-playbook deploy.yml
.
- Execute the Ansible playbook with
-
Helm:
- Package and deploy your Helm chart using
helm install your-helm-chart
.
- Package and deploy your Helm chart using
-
Jenkins:
- Set up your Jenkins server and create a pipeline using the
Jenkinsfile
provided.
- Set up your Jenkins server and create a pipeline using the
-
Testing:
- Run tests using
npm test
.
- Run tests using
This structure and configuration allow for a solid foundation for a Node.js TypeScript project with DevOps best practices, making it easier to develop, test, and deploy your application efficiently. If you have any specific requirements or changes, feel free to change this structure is't Bible :)
Happy coding...
Top comments (0)