├── .eslintrc.json ├── app ├── globals.css ├── favicon.ico ├── layout.tsx ├── page.tsx └── create │ └── page.tsx ├── next.config.js ├── postcss.config.js ├── lib ├── database │ ├── task.model.ts │ └── connect.ts └── action.ts ├── tailwind.config.ts ├── public ├── vercel.svg └── next.svg ├── Dockerfile ├── package.json ├── tsconfig.json ├── .dockerignore └── compose.yaml /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; -------------------------------------------------------------------------------- /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mustafa-Hassan2001/next-docker/HEAD/app/favicon.ico -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {} 3 | 4 | module.exports = nextConfig 5 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /lib/database/task.model.ts: -------------------------------------------------------------------------------- 1 | import { Schema, model, models } from 'mongoose'; 2 | 3 | const TaskSchema = new Schema({ 4 | title: String, 5 | description: String, 6 | status: String, 7 | }); 8 | 9 | const Task = models.Task || model('Task', TaskSchema); 10 | 11 | export default Task; -------------------------------------------------------------------------------- /lib/database/connect.ts: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | let isConnected = false; 4 | 5 | async function dbConnect() { 6 | if (isConnected) return; 7 | 8 | try { 9 | await mongoose.connect(process.env.DB_URL as string); 10 | isConnected = true; 11 | } catch (err) { 12 | console.log(err); 13 | } 14 | } 15 | 16 | export default dbConnect; 17 | -------------------------------------------------------------------------------- /app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from 'next' 2 | import { Inter } from 'next/font/google' 3 | import './globals.css' 4 | 5 | const inter = Inter({ subsets: ['latin'] }) 6 | 7 | export const metadata: Metadata = { 8 | title: 'Create Next App', 9 | description: 'Generated by create next app', 10 | } 11 | 12 | export default function RootLayout({ 13 | children, 14 | }: { 15 | children: React.ReactNode 16 | }) { 17 | return ( 18 | 19 | {children} 20 | 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from 'tailwindcss' 2 | 3 | const config: Config = { 4 | content: [ 5 | './pages/**/*.{js,ts,jsx,tsx,mdx}', 6 | './components/**/*.{js,ts,jsx,tsx,mdx}', 7 | './app/**/*.{js,ts,jsx,tsx,mdx}', 8 | ], 9 | theme: { 10 | extend: { 11 | backgroundImage: { 12 | 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', 13 | 'gradient-conic': 14 | 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', 15 | }, 16 | }, 17 | }, 18 | plugins: [], 19 | } 20 | export default config 21 | -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # inherit from a existing image to add the functionality 2 | FROM node:20-alpine3.18 3 | 4 | # RUN addgroup app && adduser -S -G app app 5 | # USER app 6 | 7 | # Set the working directory and assign ownership to the non-root user 8 | WORKDIR /app 9 | 10 | # Copy the package.json and package-lock.json files into the image. 11 | COPY package*.json ./ 12 | 13 | # Install the dependencies. 14 | RUN npm install 15 | 16 | # Copy the rest of the source files into the image. 17 | COPY . . 18 | 19 | # Expose the port that the application listens on. 20 | EXPOSE 3000 21 | 22 | # Run the application. 23 | CMD npm run dev 24 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "next-docker", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "mongoose": "^8.0.3", 13 | "next": "14.0.4", 14 | "react": "^18", 15 | "react-dom": "^18" 16 | }, 17 | "devDependencies": { 18 | "@types/node": "^20", 19 | "@types/react": "^18", 20 | "@types/react-dom": "^18", 21 | "autoprefixer": "^10.0.1", 22 | "eslint": "^8", 23 | "eslint-config-next": "14.0.4", 24 | "postcss": "^8", 25 | "tailwindcss": "^3.3.0", 26 | "typescript": "^5" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /lib/action.ts: -------------------------------------------------------------------------------- 1 | "use server"; 2 | 3 | import dbConnect from "./database/connect"; 4 | import Task from "./database/task.model"; 5 | 6 | export async function getTasks() { 7 | await dbConnect(); 8 | 9 | try { 10 | const tasks = await Task.find({}); 11 | return tasks; 12 | } catch (err) { 13 | console.log(err); 14 | } 15 | } 16 | 17 | export async function createTask(params: { 18 | task: string; 19 | description: string; 20 | status: string; 21 | }) { 22 | await dbConnect(); 23 | 24 | const { task, description, status } = params; 25 | 26 | try { 27 | const newTask = await Task.create({ task, description, status }); 28 | return newTask; 29 | } catch (err) { 30 | console.log(err); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # Include any files or directories that you don't want to be copied to your 2 | # container here (e.g., local build artifacts, temporary files, etc.). 3 | # 4 | # For more help, visit the .dockerignore file reference guide at 5 | # https://docs.docker.com/engine/reference/builder/#dockerignore-file 6 | 7 | **/.classpath 8 | **/.dockerignore 9 | **/.env 10 | **/.git 11 | **/.gitignore 12 | **/.project 13 | **/.settings 14 | **/.toolstarget 15 | **/.vs 16 | **/.vscode 17 | **/.next 18 | **/.cache 19 | **/*.*proj.user 20 | **/*.dbmdl 21 | **/*.jfm 22 | **/charts 23 | **/docker-compose* 24 | **/compose* 25 | **/Dockerfile* 26 | **/node_modules 27 | **/npm-debug.log 28 | **/obj 29 | **/secrets.dev.yaml 30 | **/values.dev.yaml 31 | **/build 32 | **/dist 33 | LICENSE 34 | README.md 35 | -------------------------------------------------------------------------------- /public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | services: 4 | frontend: 5 | # uncomment the following line if you want to run a local instance of MongoDB 6 | # depends_on: 7 | # - db 8 | build: 9 | context: . 10 | dockerfile: Dockerfile 11 | 12 | # do port mapping so that we can access the app from the browser 13 | ports: 14 | - 3000:3000 15 | 16 | # use docker compose to watch for changes and rebuild the container 17 | develop: 18 | watch: 19 | - path: ./package.json 20 | action: rebuild 21 | - path: ./next.config.js 22 | action: rebuild 23 | - path: ./package-lock.json 24 | action: rebuild 25 | - path: . 26 | target: /app 27 | action: sync 28 | 29 | # define the environment variables 30 | environment: 31 | # we're using MongoDB atlas so we need to pass in the connection string 32 | DB_URL: mongodb+srv://sujata:rnZzJjIDr3bIDymV@cluster0.hnn88vs.mongodb.net/ 33 | 34 | # we're using MongoDB atlas so we don't need to run a local instance of MongoDB 35 | # but if you want to run a local instance, you can do it this way 36 | # db: 37 | # image: mongo 38 | # ports: 39 | # - 27017:27017 40 | # environment: 41 | # - MONGO_INITDB_ROOT_USERNAME=sujata 42 | # - MONGO_INITDB_ROOT_PASSWORD=rnZzJjIDr3bIDymV 43 | # volumes: 44 | # - tasked:/data/db 45 | 46 | volumes: 47 | tasked: 48 | -------------------------------------------------------------------------------- /app/page.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | import { getTasks } from "@/lib/action"; 3 | 4 | async function Home() { 5 | const allTasks = await getTasks(); 6 | 7 | if (!allTasks) { 8 | return ( 9 |
10 |
11 |

Registred Tasks

12 |
13 |

No tasks found.

14 |
15 |
16 |
17 | ); 18 | } 19 | 20 | return ( 21 |
22 |
23 |
24 |

Registred Tasks

25 | 26 | Create Task 27 | 28 |
29 | 30 |
31 | {allTasks?.length > 0 && 32 | allTasks.map((task) => ( 33 |
38 |
39 |

40 | {task.title} 41 |

42 |

43 | {task.description} 44 |

45 |
46 |
47 | 48 | {task.status} 49 | 50 |
51 |
52 | ))} 53 |
54 |
55 |
56 | ); 57 | } 58 | 59 | export default Home; 60 | -------------------------------------------------------------------------------- /app/create/page.tsx: -------------------------------------------------------------------------------- 1 | import { createTask } from "@/lib/action"; 2 | 3 | function Create() { 4 | async function handleSubmit(formData: FormData) { 5 | "use server"; 6 | 7 | const newTask = { 8 | title: formData.get("title") as string, 9 | description: formData.get("description") as string, 10 | status: formData.get("status") as string, 11 | }; 12 | 13 | await createTask(newTask); 14 | } 15 | 16 | return ( 17 |
18 |
19 |
24 |
25 |

26 | Project Details 27 |

28 |

29 | Enter the details of your new project. 30 |

31 |
32 |
33 |
34 | 40 | 45 |
46 |
47 | 53 | 58 |
59 |
60 | 66 | 71 |
72 |
73 |
74 | 80 |
81 |
82 |
83 |
84 | ); 85 | } 86 | 87 | export default Create; 88 | --------------------------------------------------------------------------------