diff --git a/docker/docker-compose.local.yml b/docker/docker-compose.local.yml new file mode 100644 index 00000000..e68aa9b0 --- /dev/null +++ b/docker/docker-compose.local.yml @@ -0,0 +1,91 @@ +version: "3.8" + +services: + app: + build: + context: . + dockerfile: packages/app/Dockerfile + container_name: #{PROJECT_NAME}#_app + restart: unless-stopped + logging: + driver: "json-file" + options: + max-size: "50m" + ports: + - "3000:3000" + + crons: + build: + context: . + dockerfile: packages/app/crons/Dockerfile + container_name: #{PROJECT_NAME}#_crons + restart: unless-stopped + logging: + driver: "json-file" + options: + max-size: "50m" + + docs: + build: + context: . + dockerfile: packages/docs/Dockerfile + container_name: #{PROJECT_NAME}#_docs + restart: unless-stopped + logging: + driver: "json-file" + options: + max-size: "50m" + ports: + - "3001:3000" + #? You can comment the volumes section if you are not using the static files + volumes: + - .:/docs/.docusaurus + + landing: + build: + context: . + dockerfile: packages/landing/Dockerfile + container_name: #{PROJECT_NAME}#_landing + restart: unless-stopped + logging: + driver: "json-file" + options: + max-size: "50m" + ports: + - "3002:3000" + + db: + image: postgres:latest + container_name: #{PROJECT_NAME}#_db + restart: unless-stopped + volumes: + - #{PROJECT_NAME}#-postgres-data:/var/lib/postgresql/data + environment: + POSTGRES_USER: ${DATABASE_USER} + POSTGRES_PASSWORD: ${DATABASE_PASS} + POSTGRES_DB: ${DATABASE_NAME} + + logging: + driver: "json-file" + options: + max-size: "50m" + ports: + - "5432:5432" + + redis: + image: redis:latest + restart: unless-stopped + container_name: #{PROJECT_NAME}#_redis + command: /bin/sh -c "redis-server --requirepass ${REDIS_PASSWORD}" + logging: + driver: "json-file" + options: + max-size: "50m" + volumes: + - #{PROJECT_NAME}#-redis-data:/data + ports: + - "6379:6379" + +volumes: + #{PROJECT_NAME}#-postgres-data: + #{PROJECT_NAME}#-redis-data: diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 2c6878d9..c58c64f5 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -65,9 +65,9 @@ services: - "5432:5432" redis: + image: redis:latest restart: unless-stopped container_name: #{PROJECT_NAME}#_redis - image: redis:latest command: /bin/sh -c "redis-server --requirepass ${REDIS_PASSWORD}" logging: driver: "json-file" diff --git a/package-lock.json b/package-lock.json index d91f03d5..750c7a40 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11898,8 +11898,7 @@ "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "dev": true + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==" }, "node_modules/abab": { "version": "2.0.6", @@ -14496,7 +14495,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.1" }, @@ -17888,7 +17886,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", - "dev": true, "dependencies": { "micromatch": "^4.0.2" } @@ -22683,7 +22680,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.1.0.tgz", "integrity": "sha512-zfA+5SuwYN2VWqN1/5HZaDzQKLJHaBVMZIIM+wuYjdptkaQsqzDdqjqf+lZZJUuJq1aanHiY8LhH8LmH+qBYJA==", - "dev": true, "dependencies": { "call-bind": "^1.0.5", "isarray": "^2.0.5", @@ -22740,7 +22736,6 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -22804,7 +22799,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", - "dev": true, "dependencies": { "graceful-fs": "^4.1.11" } @@ -29239,7 +29233,6 @@ "version": "7.4.2", "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", - "dev": true, "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" @@ -29668,7 +29661,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.0.tgz", "integrity": "sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==", - "dev": true, "dependencies": { "@yarnpkg/lockfile": "^1.1.0", "chalk": "^4.1.2", @@ -29698,7 +29690,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -29713,7 +29704,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -29729,7 +29719,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -29740,14 +29729,12 @@ "node_modules/patch-package/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/patch-package/node_modules/fs-extra": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", @@ -29762,7 +29749,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -29771,7 +29757,6 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -29783,7 +29768,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true, "engines": { "node": ">=6" } @@ -29792,7 +29776,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -36756,7 +36739,7 @@ "@aws-sdk/client-s3": "^3.454.0", "@aws-sdk/s3-presigned-post": "^3.454.0", "@formatjs/intl-localematcher": "^0.5.0", - "@hookform/resolvers": "^3.3.4", + "@hookform/resolvers": "^3.2.0", "@next-auth/prisma-adapter": "^1.0.7", "@nextui-org/react": "^2.2.9", "@prisma/client": "^5.6.0", @@ -36786,6 +36769,7 @@ "clsx": "^2.0.0", "concurrently": "^8.2.1", "cron": "^3.0.0", + "cross-env": "^7.0.3", "crypto-js": "^4.2.0", "dotenv": "^16.3.1", "eslint": "^8.55.0", @@ -36804,6 +36788,7 @@ "next-themes": "^0.2.1", "nodemailer": "^6.9.5", "otplib": "^12.0.1", + "patch-package": "^8.0.0", "prisma": "^5.8.0", "qrcode.react": "^3.1.0", "react": "^18.2.0", @@ -36829,13 +36814,11 @@ "@types/node": "^20.4.9", "@types/react": "^18.2.19", "babel-plugin-styled-components": "^2.1.4", - "cross-env": "^7.0.3", "fetch-mock": "^9.11.0", "git-conventional-commits": "^2.6.5", "isomorphic-fetch": "^3.0.0", "jest": "^29.6.2", "jest-environment-jsdom": "^29.7.0", - "patch-package": "^8.0.0", "postcss": "^8.4.29", "postinstall-postinstall": "^2.1.0", "prettier": "^3.1.0", @@ -36934,6 +36917,7 @@ "dotenv": "^16.3.1", "eslint-plugin-simple-import-sort": "^10.0.0", "inquirer": "^9.2.11", + "patch-package": "^8.0.0", "tsx": "^4.7.0", "yaml": "^2.3.4" }, @@ -36943,7 +36927,6 @@ "eslint": "^8.55.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-unused-imports": "^3.0.0", - "patch-package": "^8.0.0", "prettier": "^3.1.0" } }, diff --git a/packages/app/Dockerfile b/packages/app/Dockerfile index 4d588326..62f472ef 100644 --- a/packages/app/Dockerfile +++ b/packages/app/Dockerfile @@ -1,23 +1,46 @@ -FROM node:20-alpine +FROM node:20-alpine AS deps RUN mkdir -p /usr/src/app +WORKDIR /usr/src/app + +ENV NODE_ENV production + +#? Copy the necessary files to install dependencies +COPY package*.json . +COPY packages/lib/package*.json ./packages/lib/ +COPY packages/app/package*.json ./packages/app/ +COPY packages/app/prisma/schema.prisma ./packages/app/prisma/schema.prisma + +RUN npm i --only=production + + +FROM node:20-alpine AS builder +RUN mkdir -p /usr/src/app WORKDIR /usr/src/app -ENV PORT 3000 ENV NEXT_TELEMETRY_DISABLED 1 ENV NODE_ENV production -COPY package.json . -COPY package-lock.json . -COPY prisma/schema.prisma ./prisma/schema.prisma +COPY --from=deps /usr/src/app . -RUN npm i --only=production +COPY packages/lib ./packages/lib +COPY packages/app ./packages/app + +RUN npm run build -w packages/app + + +FROM node:20-alpine AS runner + +RUN mkdir -p /usr/src/app +WORKDIR /usr/src/app -COPY . . +ENV PORT 3000 +ENV NEXT_TELEMETRY_DISABLED 1 +ENV NODE_ENV production -RUN npm run build +COPY --from=builder /usr/src/app . EXPOSE 3000 -CMD [ "npm", "start" ] +CMD [ "npm", "start", "-w", "packages/app" ] diff --git a/packages/app/crons/Dockerfile b/packages/app/crons/Dockerfile index 1b7ccd8d..f38f274f 100644 --- a/packages/app/crons/Dockerfile +++ b/packages/app/crons/Dockerfile @@ -1,19 +1,28 @@ -FROM node:20-alpine +FROM node:20-alpine AS deps RUN mkdir -p /usr/src/app - WORKDIR /usr/src/app -ENV PORT 3000 -ENV NEXT_TELEMETRY_DISABLED 1 ENV NODE_ENV production -COPY package.json . -COPY package-lock.json . -COPY prisma/schema.prisma ./prisma/schema.prisma +#? Copy the necessary files to install dependencies +COPY package*.json . +COPY packages/lib/package*.json ./packages/lib/ +COPY packages/app/package*.json ./packages/app/ +COPY packages/app/prisma/schema.prisma ./packages/app/prisma/schema.prisma RUN npm i --only=production -COPY . . -CMD [ "npm", "run", "cron" ] +FROM node:20-alpine AS runner + +RUN mkdir -p /usr/src/app +WORKDIR /usr/src/app + +COPY --from=deps /usr/src/app . + +COPY packages/lib ./packages/lib +COPY packages/app ./packages/app + + +CMD [ "npm", "run", "cron", "-w", "packages/app" ] diff --git a/packages/app/package.json b/packages/app/package.json index 343b1d6a..32e65a78 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -3,7 +3,7 @@ "scripts": { "dev": "npm run is-initialized && prisma migrate dev && cross-env FORCE_COLOR=1 next dev", "build": "next build", - "start": "npm run deploy-db:prod && next start", + "start": "npm run deploy-db:prod && next start --port ${PORT:-3000}", "start:with-cron": "npm run deploy-db:prod && concurrently \"next start\" \"npm run cron\"", "deploy-db:prod": "prisma migrate deploy && npm run seed", "cron": "tsx ./crons/index.ts", diff --git a/packages/landing/Dockerfile b/packages/landing/Dockerfile index 269ecfd1..62f472ef 100644 --- a/packages/landing/Dockerfile +++ b/packages/landing/Dockerfile @@ -1,22 +1,46 @@ -FROM node:20-alpine +FROM node:20-alpine AS deps RUN mkdir -p /usr/src/app +WORKDIR /usr/src/app + +ENV NODE_ENV production + +#? Copy the necessary files to install dependencies +COPY package*.json . +COPY packages/lib/package*.json ./packages/lib/ +COPY packages/app/package*.json ./packages/app/ +COPY packages/app/prisma/schema.prisma ./packages/app/prisma/schema.prisma + +RUN npm i --only=production + + +FROM node:20-alpine AS builder +RUN mkdir -p /usr/src/app WORKDIR /usr/src/app -ENV PORT 3000 ENV NEXT_TELEMETRY_DISABLED 1 ENV NODE_ENV production -COPY package.json . -COPY package-lock.json . +COPY --from=deps /usr/src/app . -RUN npm i --only=production +COPY packages/lib ./packages/lib +COPY packages/app ./packages/app + +RUN npm run build -w packages/app + + +FROM node:20-alpine AS runner + +RUN mkdir -p /usr/src/app +WORKDIR /usr/src/app -COPY . . +ENV PORT 3000 +ENV NEXT_TELEMETRY_DISABLED 1 +ENV NODE_ENV production -RUN npm run build +COPY --from=builder /usr/src/app . EXPOSE 3000 -CMD [ "npm", "start" ] +CMD [ "npm", "start", "-w", "packages/app" ] diff --git a/packages/landing/package.json b/packages/landing/package.json index 6d4ae3b3..3163466a 100644 --- a/packages/landing/package.json +++ b/packages/landing/package.json @@ -3,7 +3,7 @@ "scripts": { "dev": "next dev -p 3002", "build": "next build", - "start": "next start", + "start": "next start --port ${PORT:-3000}", "lint": "next lint && eslint . --ext .js,.jsx,.ts,.tsx", "lint:fix": "next lint --fix && eslint . --ext .js,.jsx,.ts,.tsx --fix", "test": "exit 0" diff --git a/packages/scripts/packages-selection.ts b/packages/scripts/packages-selection.ts index 4deafd0c..99c3e93b 100644 --- a/packages/scripts/packages-selection.ts +++ b/packages/scripts/packages-selection.ts @@ -15,7 +15,10 @@ const __dirname = url.fileURLToPath(new URL(".", import.meta.url)) const rootDir = path.join(__dirname, "..", "..") const packagesAvailable = fs.readdirSync(path.join(rootDir, "packages")).filter((p) => p !== "scripts" && p !== "lib") -const dockerComposePath = path.join(rootDir, "docker", "docker-compose.yml") +const dockerComposePaths = [ + path.join(rootDir, "docker", "docker-compose.yml"), + path.join(rootDir, "docker", "docker-compose.local.yml"), +] export const packagesSelection = async () => { const { packages } = await inquirer.prompt<{ packages: string[] }>([ @@ -48,11 +51,13 @@ export const packagesSelection = async () => { logger.log(chalk.gray(`Removed ${packageToRemove}!`)) } // Remove the docker-compose services that are not needed anymore - const dockerCompose = fs.readFileSync(dockerComposePath).toString() - const dockerComposeYaml = YAML.parse(dockerCompose) - for (const packageToRemove of packagesToRemove) { - delete dockerComposeYaml.services[packageToRemove] + for (const dockerComposePath of dockerComposePaths) { + const dockerCompose = fs.readFileSync(dockerComposePath).toString() + const dockerComposeYaml = YAML.parse(dockerCompose) + for (const packageToRemove of packagesToRemove) { + delete dockerComposeYaml.services[packageToRemove] + } + fs.writeFileSync(dockerComposePath, YAML.stringify(dockerComposeYaml)) } - fs.writeFileSync(dockerComposePath, YAML.stringify(dockerComposeYaml)) logger.log(chalk.gray("Removed docker-compose services!")) }