mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-07-06 14:35:26 +02:00
Compare commits
49 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3590f3bed2 | ||
|
|
c70089ee53 | ||
|
|
161e479a0b | ||
|
|
bd735bfb64 | ||
|
|
85c814620e | ||
|
|
fb013fe4ec | ||
|
|
90a1bd9027 | ||
|
|
610ef8f35c | ||
|
|
9b2fcaea31 | ||
|
|
2ffa95b9fa | ||
|
|
559872c4e4 | ||
|
|
85642ed5f2 | ||
|
|
8bf701d2f2 | ||
|
|
38809a2034 | ||
|
|
4bd6ec2232 | ||
|
|
95899b7208 | ||
|
|
ac26bb95e3 | ||
|
|
5abcc82215 | ||
|
|
16791a9f4b | ||
|
|
54ab6e3436 | ||
|
|
f5ca72ddd7 | ||
|
|
7245e7dfd7 | ||
|
|
547d149987 | ||
|
|
3b2d29514c | ||
|
|
115abd378f | ||
|
|
9c101d78d1 | ||
|
|
610f8fa5bc | ||
|
|
e201bf12f8 | ||
|
|
bf872200a7 | ||
|
|
abc6906349 | ||
|
|
9440fd89ae | ||
|
|
bce1eb8907 | ||
|
|
4bf44b3275 | ||
|
|
06355ff089 | ||
|
|
95ecf4fe21 | ||
|
|
d50a6ce76f | ||
|
|
2d951e0b1f | ||
|
|
416de9879b | ||
|
|
082aff58a9 | ||
|
|
b74666fc2f | ||
|
|
dc626f1a94 | ||
|
|
533a5e490f | ||
|
|
cf54e4f5c2 | ||
|
|
d84c808887 | ||
|
|
89cd35adc6 | ||
|
|
6299385bb4 | ||
|
|
e6f9867500 | ||
|
|
3fdd3ddc74 | ||
|
|
6ed379243e |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -35,6 +35,7 @@ yarn-error.log*
|
|||||||
|
|
||||||
# Editor
|
# Editor
|
||||||
.vscode
|
.vscode
|
||||||
|
.idea
|
||||||
|
|
||||||
# Misc
|
# Misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<div align="center">
|
<div align="center">
|
||||||
<h1 align="center">Dokploy</h1>
|
<h1 align="center">Dokploy</h1>
|
||||||
<div>
|
<div>
|
||||||
<img style="object-fit: cover; border-radius:20px;" align="center" width="50%"src="https://raw.githubusercontent.com/Dokploy/docs/main/public/logo.png" >
|
<img style="object-fit: cover; border-radius:20px;" align="center" width="50%"src="https://dokploy.com/og.png" >
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ For detailed documentation, visit [docs.dokploy.com](https://docs.dokploy.com).
|
|||||||
### Premium Supporters 🥇
|
### Premium Supporters 🥇
|
||||||
|
|
||||||
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
|
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
|
||||||
<a href="https://supafort.com/" target="_blank"><img src="https://supafort.com/build/q-4Ht4rBZR.webp" alt="Supafort.com" width="190"/></a>
|
<a href="https://supafort.com/?ref=dokploy" target="_blank"><img src="https://supafort.com/build/q-4Ht4rBZR.webp" alt="Supafort.com" width="190"/></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Elite Contributors 🥈 -->
|
<!-- Elite Contributors 🥈 -->
|
||||||
@@ -69,13 +69,13 @@ For detailed documentation, visit [docs.dokploy.com](https://docs.dokploy.com).
|
|||||||
### Supporting Members 🥉
|
### Supporting Members 🥉
|
||||||
|
|
||||||
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
|
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
|
||||||
<a href="https://lightspeed.run/"><img src="https://github.com/lightspeedrun.png" width="60px" alt="Lightspeed.run"/></a>
|
<a href="https://lightspeed.run/?ref=dokploy"><img src="https://github.com/lightspeedrun.png" width="60px" alt="Lightspeed.run"/></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
### Community Backers 🤝
|
### Community Backers 🤝
|
||||||
|
|
||||||
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
|
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
|
||||||
<a href="https://steamsets.com/"><img src="https://avatars.githubusercontent.com/u/111978405?s=200&v=4" width="60px" alt="Steamsets.com"/></a>
|
<a href="https://steamsets.com/?ref=dokploy"><img src="https://avatars.githubusercontent.com/u/111978405?s=200&v=4" width="60px" alt="Steamsets.com"/></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
#### Organizations:
|
#### Organizations:
|
||||||
|
|||||||
@@ -3,13 +3,14 @@ title: "Overview"
|
|||||||
description: "Learn how to use Docker Compose with Dokploy"
|
description: "Learn how to use Docker Compose with Dokploy"
|
||||||
---
|
---
|
||||||
|
|
||||||
|
import { Callout } from "fumadocs-ui/components/callout";
|
||||||
|
|
||||||
Dokploy integrates with Docker Compose and Docker Stack to provide flexible deployment solutions. Whether you are developing locally or deploying at scale, Dokploy facilitates application management through these powerful Docker tools.
|
Dokploy integrates with Docker Compose and Docker Stack to provide flexible deployment solutions. Whether you are developing locally or deploying at scale, Dokploy facilitates application management through these powerful Docker tools.
|
||||||
|
|
||||||
### Configuration Methods
|
### Configuration Methods
|
||||||
|
|
||||||
Dokploy provides two methods for creating Docker Compose configurations:
|
Dokploy provides two methods for creating Docker Compose configurations:
|
||||||
|
|
||||||
|
|
||||||
- **Docker Compose**: Ideal for standard Docker Compose configurations.
|
- **Docker Compose**: Ideal for standard Docker Compose configurations.
|
||||||
- **Stack**: Geared towards orchestrating applications using Docker Swarm. Note that some Docker Compose features, such as `build`, are not available in this mode.
|
- **Stack**: Geared towards orchestrating applications using Docker Swarm. Note that some Docker Compose features, such as `build`, are not available in this mode.
|
||||||
|
|
||||||
@@ -21,7 +22,7 @@ Configure the source of your code, the way your application is built, and also m
|
|||||||
|
|
||||||
A code editor within Dokploy allows you to specify environment variables for your Docker Compose file. By default, Dokploy creates a `.env` file in the specified Docker Compose file path.
|
A code editor within Dokploy allows you to specify environment variables for your Docker Compose file. By default, Dokploy creates a `.env` file in the specified Docker Compose file path.
|
||||||
|
|
||||||
### Monitoring
|
### Monitoring
|
||||||
|
|
||||||
Monitor each service individually within Dokploy. If your application consists of multiple services, each can be monitored separately to ensure optimal performance.
|
Monitor each service individually within Dokploy. If your application consists of multiple services, each can be monitored separately to ensure optimal performance.
|
||||||
|
|
||||||
@@ -29,7 +30,6 @@ Monitor each service individually within Dokploy. If your application consists o
|
|||||||
|
|
||||||
Access detailed logs for each service through the Dokploy log viewer, which can help in troubleshooting and ensuring the stability of your services.
|
Access detailed logs for each service through the Dokploy log viewer, which can help in troubleshooting and ensuring the stability of your services.
|
||||||
|
|
||||||
|
|
||||||
### Deployments
|
### Deployments
|
||||||
|
|
||||||
You can view the last 10 deployments of your application. When you deploy your application in real time, a new deployment record will be created and it will gradually show you how your application is being built.
|
You can view the last 10 deployments of your application. When you deploy your application in real time, a new deployment record will be created and it will gradually show you how your application is being built.
|
||||||
@@ -38,7 +38,6 @@ We also offer a button to cancel deployments that are in queue. Note that those
|
|||||||
|
|
||||||
We provide a webhook so that you can trigger your own deployments by pushing to your GitHub, Gitea, GitLab, Bitbucket repository.
|
We provide a webhook so that you can trigger your own deployments by pushing to your GitHub, Gitea, GitLab, Bitbucket repository.
|
||||||
|
|
||||||
|
|
||||||
### Advanced
|
### Advanced
|
||||||
|
|
||||||
This section provides advanced configuration options for experienced users. It includes tools for custom commands within the container and volumes.
|
This section provides advanced configuration options for experienced users. It includes tools for custom commands within the container and volumes.
|
||||||
@@ -46,4 +45,32 @@ This section provides advanced configuration options for experienced users. It i
|
|||||||
- **Command**: Dokploy has a defined command to run the Docker Compose file, ensuring complete control through the UI. However, you can append flags or options to the command.
|
- **Command**: Dokploy has a defined command to run the Docker Compose file, ensuring complete control through the UI. However, you can append flags or options to the command.
|
||||||
- **Volumes**: To ensure data persistence across deployments, configure storage volumes for your application.
|
- **Volumes**: To ensure data persistence across deployments, configure storage volumes for your application.
|
||||||
|
|
||||||
<ImageZoom src="/assets/images/compose/overview.png" width={800} height={630} quality={100} priority alt='home og image' className="rounded-lg" />
|
<ImageZoom
|
||||||
|
src="/assets/images/compose/overview.png"
|
||||||
|
width={800}
|
||||||
|
height={630}
|
||||||
|
quality={100}
|
||||||
|
priority
|
||||||
|
alt="home og image"
|
||||||
|
className="rounded-lg"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Callout title="Volumes">
|
||||||
|
Docker volumes are a way to persist data generated and used by Docker containers. They are particularly useful for maintaining data between container restarts or for sharing data among different containers.
|
||||||
|
|
||||||
|
To bind a volume to the host machine, you can use the following syntax in your docker-compose.yml file, but this way will clean up the volumes when a new deployment is made:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
volumes:
|
||||||
|
- "/folder:/path/in/container" ❌
|
||||||
|
```
|
||||||
|
|
||||||
|
It's recommended to use the ../files folder to ensure your data persists between deployments. For example:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
volumes:
|
||||||
|
- "../files/my-database:/var/lib/mysql" ✅
|
||||||
|
- "../files/my-configs:/etc/my-app/config" ✅
|
||||||
|
```
|
||||||
|
|
||||||
|
</Callout>
|
||||||
|
|||||||
@@ -32,7 +32,8 @@ The following templates are available:
|
|||||||
- **Metabase**: Open Source Business Intelligence
|
- **Metabase**: Open Source Business Intelligence
|
||||||
- **Grafana**: Open Source Dashboard for your metrics
|
- **Grafana**: Open Source Dashboard for your metrics
|
||||||
- **Wordpress**: Open Source Content Management System
|
- **Wordpress**: Open Source Content Management System
|
||||||
|
- **Open WebUI**: Free and Open Source ChatGPT Alternative
|
||||||
|
- **Teable**: Open Source Airtable Alternative, Developer Friendly, No-code Database Built on Postgres
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -42,4 +43,4 @@ We accept contributions to upload new templates to the dokploy repository.
|
|||||||
|
|
||||||
Make sure to follow the guidelines for creating a template:
|
Make sure to follow the guidelines for creating a template:
|
||||||
|
|
||||||
[Steps to create your own template](https://github.com/Dokploy/dokploy/blob/canary/CONTRIBUTING.md#templates)
|
[Steps to create your own template](https://github.com/Dokploy/dokploy/blob/canary/CONTRIBUTING.md#templates)
|
||||||
|
|||||||
@@ -10,10 +10,10 @@
|
|||||||
"typecheck": "tsc --noEmit"
|
"typecheck": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fumadocs-core": "12.2.2",
|
"fumadocs-core": "^12.5.6",
|
||||||
"fumadocs-mdx": "8.2.33",
|
"fumadocs-mdx": "^8.2.34",
|
||||||
"fumadocs-openapi": "^3.1.3",
|
"fumadocs-openapi": "^3.3.0",
|
||||||
"fumadocs-ui": "12.2.2",
|
"fumadocs-ui": "^12.5.6",
|
||||||
"lucide-react": "^0.394.0",
|
"lucide-react": "^0.394.0",
|
||||||
"next": "^14.2.4",
|
"next": "^14.2.4",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ test("Should not touch config without host", () => {
|
|||||||
expect(originalConfig).toEqual(config);
|
expect(originalConfig).toEqual(config);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Should remove web-secure if https rollback to http", () => {
|
test("Should remove websecure if https rollback to http", () => {
|
||||||
const originalConfig: FileConfig = loadOrCreateConfig("dokploy");
|
const originalConfig: FileConfig = loadOrCreateConfig("dokploy");
|
||||||
|
|
||||||
updateServerTraefik(
|
updateServerTraefik(
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ const baseApp: ApplicationNested = {
|
|||||||
placementSwarm: null,
|
placementSwarm: null,
|
||||||
ports: [],
|
ports: [],
|
||||||
projectId: "",
|
projectId: "",
|
||||||
|
publishDirectory: null,
|
||||||
redirects: [],
|
redirects: [],
|
||||||
refreshToken: "",
|
refreshToken: "",
|
||||||
registry: null,
|
registry: null,
|
||||||
@@ -54,6 +55,7 @@ const baseApp: ApplicationNested = {
|
|||||||
title: null,
|
title: null,
|
||||||
updateConfigSwarm: null,
|
updateConfigSwarm: null,
|
||||||
username: null,
|
username: null,
|
||||||
|
dockerContextPath: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const baseDomain: Domain = {
|
const baseDomain: Domain = {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
FormDescription,
|
||||||
FormField,
|
FormField,
|
||||||
FormItem,
|
FormItem,
|
||||||
FormLabel,
|
FormLabel,
|
||||||
@@ -23,6 +24,7 @@ enum BuildType {
|
|||||||
heroku_buildpacks = "heroku_buildpacks",
|
heroku_buildpacks = "heroku_buildpacks",
|
||||||
paketo_buildpacks = "paketo_buildpacks",
|
paketo_buildpacks = "paketo_buildpacks",
|
||||||
nixpacks = "nixpacks",
|
nixpacks = "nixpacks",
|
||||||
|
static = "static",
|
||||||
}
|
}
|
||||||
|
|
||||||
const mySchema = z.discriminatedUnion("buildType", [
|
const mySchema = z.discriminatedUnion("buildType", [
|
||||||
@@ -34,6 +36,7 @@ const mySchema = z.discriminatedUnion("buildType", [
|
|||||||
invalid_type_error: "Dockerfile path is required",
|
invalid_type_error: "Dockerfile path is required",
|
||||||
})
|
})
|
||||||
.min(1, "Dockerfile required"),
|
.min(1, "Dockerfile required"),
|
||||||
|
dockerContextPath: z.string().nullable().default(""),
|
||||||
}),
|
}),
|
||||||
z.object({
|
z.object({
|
||||||
buildType: z.literal("heroku_buildpacks"),
|
buildType: z.literal("heroku_buildpacks"),
|
||||||
@@ -43,6 +46,10 @@ const mySchema = z.discriminatedUnion("buildType", [
|
|||||||
}),
|
}),
|
||||||
z.object({
|
z.object({
|
||||||
buildType: z.literal("nixpacks"),
|
buildType: z.literal("nixpacks"),
|
||||||
|
publishDirectory: z.string().optional(),
|
||||||
|
}),
|
||||||
|
z.object({
|
||||||
|
buildType: z.literal("static"),
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -73,17 +80,18 @@ export const ShowBuildChooseForm = ({ applicationId }: Props) => {
|
|||||||
const buildType = form.watch("buildType");
|
const buildType = form.watch("buildType");
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data) {
|
if (data) {
|
||||||
// TODO: refactor this
|
|
||||||
if (data.buildType === "dockerfile") {
|
if (data.buildType === "dockerfile") {
|
||||||
form.reset({
|
form.reset({
|
||||||
buildType: data.buildType,
|
buildType: data.buildType,
|
||||||
...(data.buildType && {
|
...(data.buildType && {
|
||||||
dockerfile: data.dockerfile || "",
|
dockerfile: data.dockerfile || "",
|
||||||
|
dockerContextPath: data.dockerContextPath || "",
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
form.reset({
|
form.reset({
|
||||||
buildType: data.buildType,
|
buildType: data.buildType,
|
||||||
|
publishDirectory: data.publishDirectory || undefined,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,7 +101,11 @@ export const ShowBuildChooseForm = ({ applicationId }: Props) => {
|
|||||||
await mutateAsync({
|
await mutateAsync({
|
||||||
applicationId,
|
applicationId,
|
||||||
buildType: data.buildType,
|
buildType: data.buildType,
|
||||||
|
publishDirectory:
|
||||||
|
data.buildType === "nixpacks" ? data.publishDirectory : null,
|
||||||
dockerfile: data.buildType === "dockerfile" ? data.dockerfile : null,
|
dockerfile: data.buildType === "dockerfile" ? data.dockerfile : null,
|
||||||
|
dockerContextPath:
|
||||||
|
data.buildType === "dockerfile" ? data.dockerContextPath : null,
|
||||||
})
|
})
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
toast.success("Build type saved");
|
toast.success("Build type saved");
|
||||||
@@ -171,6 +183,12 @@ export const ShowBuildChooseForm = ({ applicationId }: Props) => {
|
|||||||
Paketo Buildpacks
|
Paketo Buildpacks
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
<FormItem className="flex items-center space-x-3 space-y-0">
|
||||||
|
<FormControl>
|
||||||
|
<RadioGroupItem value="static" />
|
||||||
|
</FormControl>
|
||||||
|
<FormLabel className="font-normal">Static</FormLabel>
|
||||||
|
</FormItem>
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@@ -179,16 +197,71 @@ export const ShowBuildChooseForm = ({ applicationId }: Props) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{buildType === "dockerfile" && (
|
{buildType === "dockerfile" && (
|
||||||
|
<>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="dockerfile"
|
||||||
|
render={({ field }) => {
|
||||||
|
return (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Docker File</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
placeholder={"Path of your docker file"}
|
||||||
|
{...field}
|
||||||
|
value={field.value ?? ""}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="dockerContextPath"
|
||||||
|
render={({ field }) => {
|
||||||
|
return (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Docker Context Path</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
placeholder={
|
||||||
|
"Path of your docker context default: ."
|
||||||
|
}
|
||||||
|
{...field}
|
||||||
|
value={field.value ?? ""}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{buildType === "nixpacks" && (
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="dockerfile"
|
name="publishDirectory"
|
||||||
render={({ field }) => {
|
render={({ field }) => {
|
||||||
return (
|
return (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Docker File</FormLabel>
|
<div className="space-y-0.5">
|
||||||
|
<FormLabel>Publish Directory</FormLabel>
|
||||||
|
<FormDescription>
|
||||||
|
Allows you to serve a single directory via NGINX after
|
||||||
|
the build phase. Useful if the final build assets
|
||||||
|
should be served as a static site.
|
||||||
|
</FormDescription>
|
||||||
|
</div>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder={"Path of your docker file"}
|
placeholder={"Publish Directory"}
|
||||||
{...field}
|
{...field}
|
||||||
value={field.value ?? ""}
|
value={field.value ?? ""}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ export const SaveDockerProvider = ({ applicationId }: Props) => {
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Password</FormLabel>
|
<FormLabel>Password</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="Password" {...field} />
|
<Input placeholder="Password" {...field} type="password" />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|||||||
1
apps/dokploy/drizzle/0027_red_lady_bullseye.sql
Normal file
1
apps/dokploy/drizzle/0027_red_lady_bullseye.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE "application" ADD COLUMN "publishDirectory" text;
|
||||||
1
apps/dokploy/drizzle/0028_jittery_eternity.sql
Normal file
1
apps/dokploy/drizzle/0028_jittery_eternity.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TYPE "buildType" ADD VALUE 'static';
|
||||||
1
apps/dokploy/drizzle/0029_colossal_zodiak.sql
Normal file
1
apps/dokploy/drizzle/0029_colossal_zodiak.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE "application" ADD COLUMN "dockerContextPath" text;
|
||||||
3016
apps/dokploy/drizzle/meta/0027_snapshot.json
Normal file
3016
apps/dokploy/drizzle/meta/0027_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
3017
apps/dokploy/drizzle/meta/0028_snapshot.json
Normal file
3017
apps/dokploy/drizzle/meta/0028_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
3023
apps/dokploy/drizzle/meta/0029_snapshot.json
Normal file
3023
apps/dokploy/drizzle/meta/0029_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -190,6 +190,27 @@
|
|||||||
"when": 1721979220929,
|
"when": 1721979220929,
|
||||||
"tag": "0026_known_dormammu",
|
"tag": "0026_known_dormammu",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 27,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1722445099203,
|
||||||
|
"tag": "0027_red_lady_bullseye",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 28,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1722503439951,
|
||||||
|
"tag": "0028_jittery_eternity",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 29,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1722578386823,
|
||||||
|
"tag": "0029_colossal_zodiak",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "dokploy",
|
"name": "dokploy",
|
||||||
"version": "v0.5.1",
|
"version": "v0.6.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
BIN
apps/dokploy/public/templates/teable.png
Normal file
BIN
apps/dokploy/public/templates/teable.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 757 B |
@@ -191,6 +191,8 @@ export const applicationRouter = createTRPCRouter({
|
|||||||
await updateApplication(input.applicationId, {
|
await updateApplication(input.applicationId, {
|
||||||
buildType: input.buildType,
|
buildType: input.buildType,
|
||||||
dockerfile: input.dockerfile,
|
dockerfile: input.dockerfile,
|
||||||
|
publishDirectory: input.publishDirectory,
|
||||||
|
dockerContextPath: input.dockerContextPath,
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -227,7 +227,8 @@ export const composeRouter = createTRPCRouter({
|
|||||||
if (mounts && mounts?.length > 0) {
|
if (mounts && mounts?.length > 0) {
|
||||||
for (const mount of mounts) {
|
for (const mount of mounts) {
|
||||||
await createMount({
|
await createMount({
|
||||||
mountPath: mount.mountPath,
|
filePath: mount.filePath,
|
||||||
|
mountPath: "",
|
||||||
content: mount.content,
|
content: mount.content,
|
||||||
serviceId: compose.composeId,
|
serviceId: compose.composeId,
|
||||||
serviceType: "compose",
|
serviceType: "compose",
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ export const buildType = pgEnum("buildType", [
|
|||||||
"heroku_buildpacks",
|
"heroku_buildpacks",
|
||||||
"paketo_buildpacks",
|
"paketo_buildpacks",
|
||||||
"nixpacks",
|
"nixpacks",
|
||||||
|
"static",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// TODO: refactor this types
|
// TODO: refactor this types
|
||||||
@@ -140,6 +141,7 @@ export const applications = pgTable("application", {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
dockerfile: text("dockerfile"),
|
dockerfile: text("dockerfile"),
|
||||||
|
dockerContextPath: text("dockerContextPath"),
|
||||||
// Drop
|
// Drop
|
||||||
dropBuildPath: text("dropBuildPath"),
|
dropBuildPath: text("dropBuildPath"),
|
||||||
// Docker swarm json
|
// Docker swarm json
|
||||||
@@ -157,6 +159,7 @@ export const applications = pgTable("application", {
|
|||||||
.notNull()
|
.notNull()
|
||||||
.default("idle"),
|
.default("idle"),
|
||||||
buildType: buildType("buildType").notNull().default("nixpacks"),
|
buildType: buildType("buildType").notNull().default("nixpacks"),
|
||||||
|
publishDirectory: text("publishDirectory"),
|
||||||
createdAt: text("createdAt")
|
createdAt: text("createdAt")
|
||||||
.notNull()
|
.notNull()
|
||||||
.$defaultFn(() => new Date().toISOString()),
|
.$defaultFn(() => new Date().toISOString()),
|
||||||
@@ -315,7 +318,9 @@ const createSchema = createInsertSchema(applications, {
|
|||||||
"heroku_buildpacks",
|
"heroku_buildpacks",
|
||||||
"paketo_buildpacks",
|
"paketo_buildpacks",
|
||||||
"nixpacks",
|
"nixpacks",
|
||||||
|
"static",
|
||||||
]),
|
]),
|
||||||
|
publishDirectory: z.string().optional(),
|
||||||
owner: z.string(),
|
owner: z.string(),
|
||||||
healthCheckSwarm: HealthCheckSwarmSchema.nullable(),
|
healthCheckSwarm: HealthCheckSwarmSchema.nullable(),
|
||||||
restartPolicySwarm: RestartPolicySwarmSchema.nullable(),
|
restartPolicySwarm: RestartPolicySwarmSchema.nullable(),
|
||||||
@@ -352,8 +357,10 @@ export const apiSaveBuildType = createSchema
|
|||||||
applicationId: true,
|
applicationId: true,
|
||||||
buildType: true,
|
buildType: true,
|
||||||
dockerfile: true,
|
dockerfile: true,
|
||||||
|
dockerContextPath: true,
|
||||||
})
|
})
|
||||||
.required();
|
.required()
|
||||||
|
.merge(createSchema.pick({ publishDirectory: true }));
|
||||||
|
|
||||||
export const apiSaveGithubProvider = createSchema
|
export const apiSaveGithubProvider = createSchema
|
||||||
.pick({
|
.pick({
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import type { WriteStream } from "node:fs";
|
import type { WriteStream } from "node:fs";
|
||||||
import { prepareEnvironmentVariables } from "@/server/utils/docker/utils";
|
import { prepareEnvironmentVariables } from "@/server/utils/docker/utils";
|
||||||
import type { ApplicationNested } from ".";
|
import type { ApplicationNested } from ".";
|
||||||
import { getBuildAppDirectory } from "../filesystem/directory";
|
import {
|
||||||
|
getBuildAppDirectory,
|
||||||
|
getDockerContextPath,
|
||||||
|
} from "../filesystem/directory";
|
||||||
import { spawnAsync } from "../process/spawnAsync";
|
import { spawnAsync } from "../process/spawnAsync";
|
||||||
import { createEnvFile } from "./utils";
|
import { createEnvFile } from "./utils";
|
||||||
|
|
||||||
@@ -9,22 +12,30 @@ export const buildCustomDocker = async (
|
|||||||
application: ApplicationNested,
|
application: ApplicationNested,
|
||||||
writeStream: WriteStream,
|
writeStream: WriteStream,
|
||||||
) => {
|
) => {
|
||||||
const { appName, env, buildArgs } = application;
|
const { appName, env, publishDirectory, buildArgs } = application;
|
||||||
const dockerFilePath = getBuildAppDirectory(application);
|
const dockerFilePath = getBuildAppDirectory(application);
|
||||||
try {
|
try {
|
||||||
const image = `${appName}`;
|
const image = `${appName}`;
|
||||||
|
|
||||||
const contextPath =
|
const defaultContextPath =
|
||||||
dockerFilePath.substring(0, dockerFilePath.lastIndexOf("/") + 1) || ".";
|
dockerFilePath.substring(0, dockerFilePath.lastIndexOf("/") + 1) || ".";
|
||||||
const args = prepareEnvironmentVariables(buildArgs);
|
const args = prepareEnvironmentVariables(buildArgs);
|
||||||
|
|
||||||
|
const dockerContextPath = getDockerContextPath(application);
|
||||||
|
|
||||||
const commandArgs = ["build", "-t", image, "-f", dockerFilePath, "."];
|
const commandArgs = ["build", "-t", image, "-f", dockerFilePath, "."];
|
||||||
|
|
||||||
for (const arg of args) {
|
for (const arg of args) {
|
||||||
commandArgs.push("--build-arg", arg);
|
commandArgs.push("--build-arg", arg);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
Do not generate an environment file when publishDirectory is specified,
|
||||||
|
as it could be publicly exposed.
|
||||||
|
*/
|
||||||
|
if (!publishDirectory) {
|
||||||
|
createEnvFile(dockerFilePath, env);
|
||||||
|
}
|
||||||
|
|
||||||
createEnvFile(dockerFilePath, env);
|
|
||||||
await spawnAsync(
|
await spawnAsync(
|
||||||
"docker",
|
"docker",
|
||||||
commandArgs,
|
commandArgs,
|
||||||
@@ -34,7 +45,7 @@ export const buildCustomDocker = async (
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
cwd: contextPath,
|
cwd: dockerContextPath || defaultContextPath,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { buildCustomDocker } from "./docker-file";
|
|||||||
import { buildHeroku } from "./heroku";
|
import { buildHeroku } from "./heroku";
|
||||||
import { buildNixpacks } from "./nixpacks";
|
import { buildNixpacks } from "./nixpacks";
|
||||||
import { buildPaketo } from "./paketo";
|
import { buildPaketo } from "./paketo";
|
||||||
|
import { buildStatic } from "./static";
|
||||||
|
|
||||||
// NIXPACKS codeDirectory = where is the path of the code directory
|
// NIXPACKS codeDirectory = where is the path of the code directory
|
||||||
// HEROKU codeDirectory = where is the path of the code directory
|
// HEROKU codeDirectory = where is the path of the code directory
|
||||||
@@ -43,6 +44,8 @@ export const buildApplication = async (
|
|||||||
await buildPaketo(application, writeStream);
|
await buildPaketo(application, writeStream);
|
||||||
} else if (buildType === "dockerfile") {
|
} else if (buildType === "dockerfile") {
|
||||||
await buildCustomDocker(application, writeStream);
|
await buildCustomDocker(application, writeStream);
|
||||||
|
} else if (buildType === "static") {
|
||||||
|
await buildStatic(application, writeStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (application.registryId) {
|
if (application.registryId) {
|
||||||
@@ -51,7 +54,11 @@ export const buildApplication = async (
|
|||||||
await mechanizeDockerContainer(application);
|
await mechanizeDockerContainer(application);
|
||||||
writeStream.write("Docker Deployed: ✅");
|
writeStream.write("Docker Deployed: ✅");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
writeStream.write("Error ❌");
|
if (error instanceof Error) {
|
||||||
|
writeStream.write(`Error ❌\n${error?.message}`);
|
||||||
|
} else {
|
||||||
|
writeStream.write("Error ❌");
|
||||||
|
}
|
||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
writeStream.end();
|
writeStream.end();
|
||||||
|
|||||||
@@ -1,18 +1,28 @@
|
|||||||
import type { WriteStream } from "node:fs";
|
import type { WriteStream } from "node:fs";
|
||||||
|
import path from "node:path";
|
||||||
|
import { buildStatic } from "@/server/utils/builders/static";
|
||||||
|
import { nanoid } from "nanoid";
|
||||||
import type { ApplicationNested } from ".";
|
import type { ApplicationNested } from ".";
|
||||||
import { prepareEnvironmentVariables } from "../docker/utils";
|
import { prepareEnvironmentVariables } from "../docker/utils";
|
||||||
import { getBuildAppDirectory } from "../filesystem/directory";
|
import { getBuildAppDirectory } from "../filesystem/directory";
|
||||||
import { spawnAsync } from "../process/spawnAsync";
|
import { spawnAsync } from "../process/spawnAsync";
|
||||||
|
|
||||||
// TODO: integrate in the vps sudo chown -R $(whoami) ~/.docker
|
|
||||||
export const buildNixpacks = async (
|
export const buildNixpacks = async (
|
||||||
application: ApplicationNested,
|
application: ApplicationNested,
|
||||||
writeStream: WriteStream,
|
writeStream: WriteStream,
|
||||||
) => {
|
) => {
|
||||||
const { env, appName } = application;
|
const { env, appName, publishDirectory } = application;
|
||||||
const buildAppDirectory = getBuildAppDirectory(application);
|
|
||||||
|
|
||||||
|
const buildAppDirectory = getBuildAppDirectory(application);
|
||||||
|
const buildContainerId = `${appName}-${nanoid(10)}`;
|
||||||
const envVariables = prepareEnvironmentVariables(env);
|
const envVariables = prepareEnvironmentVariables(env);
|
||||||
|
|
||||||
|
const writeToStream = (data: string) => {
|
||||||
|
if (writeStream.writable) {
|
||||||
|
writeStream.write(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const args = ["build", buildAppDirectory, "--name", appName];
|
const args = ["build", buildAppDirectory, "--name", appName];
|
||||||
|
|
||||||
@@ -20,13 +30,44 @@ export const buildNixpacks = async (
|
|||||||
args.push("--env", env);
|
args.push("--env", env);
|
||||||
}
|
}
|
||||||
|
|
||||||
await spawnAsync("nixpacks", args, (data) => {
|
if (publishDirectory) {
|
||||||
if (writeStream.writable) {
|
/* No need for any start command, since we'll use nginx later on */
|
||||||
writeStream.write(data);
|
args.push("--no-error-without-start");
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
await spawnAsync("nixpacks", args, writeToStream);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Run the container with the image created by nixpacks,
|
||||||
|
and copy the artifacts on the host filesystem.
|
||||||
|
Then, remove the container and create a static build.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (publishDirectory) {
|
||||||
|
await spawnAsync(
|
||||||
|
"docker",
|
||||||
|
["create", "--name", buildContainerId, appName],
|
||||||
|
writeToStream,
|
||||||
|
);
|
||||||
|
|
||||||
|
await spawnAsync(
|
||||||
|
"docker",
|
||||||
|
[
|
||||||
|
"cp",
|
||||||
|
`${buildContainerId}:/app/${publishDirectory}`,
|
||||||
|
path.join(buildAppDirectory, publishDirectory),
|
||||||
|
],
|
||||||
|
writeToStream,
|
||||||
|
);
|
||||||
|
|
||||||
|
await spawnAsync("docker", ["rm", buildContainerId], writeToStream);
|
||||||
|
|
||||||
|
await buildStatic(application, writeStream);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
await spawnAsync("docker", ["rm", buildContainerId], writeToStream);
|
||||||
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
38
apps/dokploy/server/utils/builders/static.ts
Normal file
38
apps/dokploy/server/utils/builders/static.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import type { WriteStream } from "node:fs";
|
||||||
|
import { buildCustomDocker } from "@/server/utils/builders/docker-file";
|
||||||
|
import type { ApplicationNested } from ".";
|
||||||
|
import { createFile } from "../docker/utils";
|
||||||
|
import { getBuildAppDirectory } from "../filesystem/directory";
|
||||||
|
|
||||||
|
export const buildStatic = async (
|
||||||
|
application: ApplicationNested,
|
||||||
|
writeStream: WriteStream,
|
||||||
|
) => {
|
||||||
|
const { publishDirectory } = application;
|
||||||
|
const buildAppDirectory = getBuildAppDirectory(application);
|
||||||
|
|
||||||
|
try {
|
||||||
|
createFile(
|
||||||
|
buildAppDirectory,
|
||||||
|
"Dockerfile",
|
||||||
|
[
|
||||||
|
"FROM nginx:alpine",
|
||||||
|
"WORKDIR /usr/share/nginx/html/",
|
||||||
|
`COPY ${publishDirectory || "."} .`,
|
||||||
|
].join("\n"),
|
||||||
|
);
|
||||||
|
|
||||||
|
await buildCustomDocker(
|
||||||
|
{
|
||||||
|
...application,
|
||||||
|
buildType: "dockerfile",
|
||||||
|
dockerfile: "Dockerfile",
|
||||||
|
},
|
||||||
|
writeStream,
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -242,12 +242,7 @@ export const generateConfigContainer = (application: ApplicationNested) => {
|
|||||||
? {
|
? {
|
||||||
RestartPolicy: restartPolicySwarm,
|
RestartPolicy: restartPolicySwarm,
|
||||||
}
|
}
|
||||||
: {
|
: {}),
|
||||||
// if no restartPolicySwarm provided use default
|
|
||||||
RestartPolicy: {
|
|
||||||
Condition: "on-failure",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
...(placementSwarm
|
...(placementSwarm
|
||||||
? {
|
? {
|
||||||
Placement: placementSwarm,
|
Placement: placementSwarm,
|
||||||
|
|||||||
@@ -89,3 +89,12 @@ export const getBuildAppDirectory = (application: Application) => {
|
|||||||
|
|
||||||
return path.join(APPLICATIONS_PATH, appName, "code", buildPath ?? "");
|
return path.join(APPLICATIONS_PATH, appName, "code", buildPath ?? "");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getDockerContextPath = (application: Application) => {
|
||||||
|
const { appName, dockerContextPath } = application;
|
||||||
|
|
||||||
|
if (!dockerContextPath) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return path.join(APPLICATIONS_PATH, appName, "code", dockerContextPath);
|
||||||
|
};
|
||||||
|
|||||||
@@ -33,7 +33,9 @@ export const cloneGitRepository = async (
|
|||||||
const knownHostsPath = path.join(SSH_PATH, "known_hosts");
|
const knownHostsPath = path.join(SSH_PATH, "known_hosts");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await addHostToKnownHosts(customGitUrl);
|
if (!isHttpOrHttps(customGitUrl)) {
|
||||||
|
await addHostToKnownHosts(customGitUrl);
|
||||||
|
}
|
||||||
await recreateDirectory(outputPath);
|
await recreateDirectory(outputPath);
|
||||||
// const command = `GIT_SSH_COMMAND="ssh -i ${keyPath} -o UserKnownHostsFile=${knownHostsPath}" git clone --branch ${customGitBranch} --depth 1 ${customGitUrl} ${gitCopyPath} --progress`;
|
// const command = `GIT_SSH_COMMAND="ssh -i ${keyPath} -o UserKnownHostsFile=${knownHostsPath}" git clone --branch ${customGitBranch} --depth 1 ${customGitUrl} ${gitCopyPath} --progress`;
|
||||||
// const { stdout, stderr } = await execAsync(command);
|
// const { stdout, stderr } = await execAsync(command);
|
||||||
@@ -56,6 +58,7 @@ export const cloneGitRepository = async (
|
|||||||
customGitBranch,
|
customGitBranch,
|
||||||
"--depth",
|
"--depth",
|
||||||
"1",
|
"1",
|
||||||
|
"--recurse-submodules",
|
||||||
customGitUrl,
|
customGitUrl,
|
||||||
outputPath,
|
outputPath,
|
||||||
"--progress",
|
"--progress",
|
||||||
@@ -84,6 +87,11 @@ export const cloneGitRepository = async (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isHttpOrHttps = (url: string): boolean => {
|
||||||
|
const regex = /^https?:\/\//;
|
||||||
|
return regex.test(url);
|
||||||
|
};
|
||||||
|
|
||||||
const addHostToKnownHosts = async (repositoryURL: string) => {
|
const addHostToKnownHosts = async (repositoryURL: string) => {
|
||||||
const { domain, port } = sanitizeRepoPathSSH(repositoryURL);
|
const { domain, port } = sanitizeRepoPathSSH(repositoryURL);
|
||||||
const knownHostsPath = path.join(SSH_PATH, "known_hosts");
|
const knownHostsPath = path.join(SSH_PATH, "known_hosts");
|
||||||
@@ -121,7 +129,7 @@ const sanitizeRepoPathSSH = (input: string) => {
|
|||||||
return {
|
return {
|
||||||
user: found.groups?.user ?? "git",
|
user: found.groups?.user ?? "git",
|
||||||
domain: found.groups?.domain,
|
domain: found.groups?.domain,
|
||||||
port: 22,
|
port: Number(found.groups?.port ?? 22),
|
||||||
owner: found.groups?.owner ?? "",
|
owner: found.groups?.owner ?? "",
|
||||||
repo: found.groups?.repo,
|
repo: found.groups?.repo,
|
||||||
get repoPath() {
|
get repoPath() {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export const updateServerTraefik = (
|
|||||||
if (admin?.certificateType === "letsencrypt") {
|
if (admin?.certificateType === "letsencrypt") {
|
||||||
config.http.routers[`${appName}-router-app-secure`] = {
|
config.http.routers[`${appName}-router-app-secure`] = {
|
||||||
...currentRouterConfig,
|
...currentRouterConfig,
|
||||||
entryPoints: ["web-secure"],
|
entryPoints: ["websecure"],
|
||||||
tls: { certResolver: "letsencrypt" },
|
tls: { certResolver: "letsencrypt" },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export function generate(schema: Schema): Template {
|
|||||||
|
|
||||||
const mounts: Template["mounts"] = [
|
const mounts: Template["mounts"] = [
|
||||||
{
|
{
|
||||||
mountPath: "./config.toml",
|
filePath: "config.toml",
|
||||||
content: `[app]
|
content: `[app]
|
||||||
address = "0.0.0.0:9000"
|
address = "0.0.0.0:9000"
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export function generate(schema: Schema): Template {
|
|||||||
|
|
||||||
const mounts: Template["mounts"] = [
|
const mounts: Template["mounts"] = [
|
||||||
{
|
{
|
||||||
mountPath: "./clickhouse/clickhouse-config.xml",
|
filePath: "/clickhouse/clickhouse-config.xml",
|
||||||
content: `
|
content: `
|
||||||
<clickhouse>
|
<clickhouse>
|
||||||
<logger>
|
<logger>
|
||||||
@@ -45,7 +45,7 @@ export function generate(schema: Schema): Template {
|
|||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mountPath: "./clickhouse/clickhouse-user-config.xml",
|
filePath: "/clickhouse/clickhouse-user-config.xml",
|
||||||
content: `
|
content: `
|
||||||
<clickhouse>
|
<clickhouse>
|
||||||
<profiles>
|
<profiles>
|
||||||
|
|||||||
81
apps/dokploy/templates/teable/docker-compose.yml
Normal file
81
apps/dokploy/templates/teable/docker-compose.yml
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
version: "3.9"
|
||||||
|
|
||||||
|
services:
|
||||||
|
teable:
|
||||||
|
image: ghcr.io/teableio/teable:1.3.1-alpha-build.460
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- ${TEABLE_PORT}
|
||||||
|
volumes:
|
||||||
|
- teable-data:/app/.assets
|
||||||
|
# you may use a bind-mounted host directory instead,
|
||||||
|
# so that it is harder to accidentally remove the volume and lose all your data!
|
||||||
|
# - ./docker/teable/data:/app/.assets:rw
|
||||||
|
environment:
|
||||||
|
- TZ=${TIMEZONE}
|
||||||
|
- NEXT_ENV_IMAGES_ALL_REMOTE=true
|
||||||
|
- PUBLIC_ORIGIN=${PUBLIC_ORIGIN}
|
||||||
|
- PRISMA_DATABASE_URL=${PRISMA_DATABASE_URL}
|
||||||
|
- PUBLIC_DATABASE_PROXY=${PUBLIC_DATABASE_PROXY}
|
||||||
|
- BACKEND_MAIL_HOST=${BACKEND_MAIL_HOST}
|
||||||
|
- BACKEND_MAIL_PORT=${BACKEND_MAIL_PORT}
|
||||||
|
- BACKEND_MAIL_SECURE=${BACKEND_MAIL_SECURE}
|
||||||
|
- BACKEND_MAIL_SENDER=${BACKEND_MAIL_SENDER}
|
||||||
|
- BACKEND_MAIL_SENDER_NAME=${BACKEND_MAIL_SENDER_NAME}
|
||||||
|
- BACKEND_MAIL_AUTH_USER=${BACKEND_MAIL_AUTH_USER}
|
||||||
|
- BACKEND_MAIL_AUTH_PASS=${BACKEND_MAIL_AUTH_PASS}
|
||||||
|
networks:
|
||||||
|
- dokploy-network
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.${HASH}.rule=Host(`${TEABLE_HOST}`)"
|
||||||
|
- "traefik.http.services.${HASH}.loadbalancer.server.port=${TEABLE_PORT}"
|
||||||
|
depends_on:
|
||||||
|
teable-db-migrate:
|
||||||
|
condition: service_completed_successfully
|
||||||
|
|
||||||
|
teable-db:
|
||||||
|
image: postgres:15.4
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "${TEABLE_DB_PORT}:${POSTGRES_PORT}"
|
||||||
|
volumes:
|
||||||
|
- teable-db:/var/lib/postgresql/data
|
||||||
|
# you may use a bind-mounted host directory instead,
|
||||||
|
# so that it is harder to accidentally remove the volume and lose all your data!
|
||||||
|
# - ./docker/db/data:/var/lib/postgresql/data:rw
|
||||||
|
environment:
|
||||||
|
- TZ=${TIMEZONE}
|
||||||
|
- POSTGRES_DB=${POSTGRES_DB}
|
||||||
|
- POSTGRES_USER=${POSTGRES_USER}
|
||||||
|
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||||
|
networks:
|
||||||
|
- dokploy-network
|
||||||
|
healthcheck:
|
||||||
|
test:
|
||||||
|
[
|
||||||
|
"CMD-SHELL",
|
||||||
|
"sh -c 'pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}'",
|
||||||
|
]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 3
|
||||||
|
|
||||||
|
teable-db-migrate:
|
||||||
|
image: ghcr.io/teableio/teable-db-migrate:latest
|
||||||
|
environment:
|
||||||
|
- TZ=${TIMEZONE}
|
||||||
|
- PRISMA_DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
|
||||||
|
networks:
|
||||||
|
- dokploy-network
|
||||||
|
depends_on:
|
||||||
|
teable-db:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
networks:
|
||||||
|
dokploy-network:
|
||||||
|
external: true
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
teable-data: {}
|
||||||
|
teable-db: {}
|
||||||
48
apps/dokploy/templates/teable/index.ts
Normal file
48
apps/dokploy/templates/teable/index.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import {
|
||||||
|
type Schema,
|
||||||
|
type Template,
|
||||||
|
generateHash,
|
||||||
|
generatePassword,
|
||||||
|
generateRandomDomain,
|
||||||
|
} from "../utils";
|
||||||
|
|
||||||
|
export function generate(schema: Schema): Template {
|
||||||
|
const mainServiceHash = generateHash(schema.projectName);
|
||||||
|
const password = generatePassword();
|
||||||
|
const randomDomain = generateRandomDomain(schema);
|
||||||
|
|
||||||
|
const publicDbPort = ((min: number, max: number) => {
|
||||||
|
return Math.round(Math.random() * (max - min) + min);
|
||||||
|
})(32769, 65534);
|
||||||
|
|
||||||
|
const envs = [
|
||||||
|
`TEABLE_HOST=${randomDomain}`,
|
||||||
|
"TEABLE_PORT=3000",
|
||||||
|
`TEABLE_DB_PORT=${publicDbPort}`,
|
||||||
|
`HASH=${mainServiceHash}`,
|
||||||
|
"TIMEZONE=UTC",
|
||||||
|
"# Postgres",
|
||||||
|
"POSTGRES_HOST=teable-db",
|
||||||
|
"POSTGRES_PORT=5432",
|
||||||
|
"POSTGRES_DB=teable",
|
||||||
|
"POSTGRES_USER=teable",
|
||||||
|
`POSTGRES_PASSWORD=${password}`,
|
||||||
|
"# App",
|
||||||
|
"PUBLIC_ORIGIN=https://${TEABLE_HOST}",
|
||||||
|
"PRISMA_DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}",
|
||||||
|
"PUBLIC_DATABASE_PROXY=${TEABLE_HOST}:${TEABLE_DB_PORT}",
|
||||||
|
"# Need to support sending emails to enable the following configurations",
|
||||||
|
"# You need to modify the configuration according to the actual situation, otherwise it will not be able to send emails correctly.",
|
||||||
|
"#BACKEND_MAIL_HOST=smtp.teable.io",
|
||||||
|
"#BACKEND_MAIL_PORT=465",
|
||||||
|
"#BACKEND_MAIL_SECURE=true",
|
||||||
|
"#BACKEND_MAIL_SENDER=noreply.teable.io",
|
||||||
|
"#BACKEND_MAIL_SENDER_NAME=Teable",
|
||||||
|
"#BACKEND_MAIL_AUTH_USER=username",
|
||||||
|
"#BACKEND_MAIL_AUTH_PASS=password",
|
||||||
|
];
|
||||||
|
|
||||||
|
return {
|
||||||
|
envs,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -393,4 +393,19 @@ export const templates: TemplateData[] = [
|
|||||||
tags: ["media system"],
|
tags: ["media system"],
|
||||||
load: () => import("./jellyfin/index").then((m) => m.generate),
|
load: () => import("./jellyfin/index").then((m) => m.generate),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "teable",
|
||||||
|
name: "teable",
|
||||||
|
version: "v1.3.1-alpha-build.460",
|
||||||
|
description:
|
||||||
|
"Teable is a Super fast, Real-time, Professional, Developer friendly, No-code database built on Postgres. It uses a simple, spreadsheet-like interface to create complex enterprise-level database applications. Unlock efficient app development with no-code, free from the hurdles of data security and scalability.",
|
||||||
|
logo: "teable.png",
|
||||||
|
links: {
|
||||||
|
github: "https://github.com/teableio/teable",
|
||||||
|
website: "https://teable.io/",
|
||||||
|
docs: "https://help.teable.io/",
|
||||||
|
},
|
||||||
|
tags: ["database", "spreadsheet", "low-code", "nocode"],
|
||||||
|
load: () => import("./teable/index").then((m) => m.generate),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export interface Schema {
|
|||||||
export interface Template {
|
export interface Template {
|
||||||
envs: string[];
|
envs: string[];
|
||||||
mounts?: {
|
mounts?: {
|
||||||
mountPath: string;
|
filePath: string;
|
||||||
content?: string;
|
content?: string;
|
||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
|||||||
147
pnpm-lock.yaml
generated
147
pnpm-lock.yaml
generated
@@ -39,17 +39,17 @@ importers:
|
|||||||
apps/docs:
|
apps/docs:
|
||||||
dependencies:
|
dependencies:
|
||||||
fumadocs-core:
|
fumadocs-core:
|
||||||
specifier: 12.2.2
|
specifier: ^12.5.6
|
||||||
version: 12.2.2(@types/react@18.3.3)(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 12.5.6(@types/react@18.3.3)(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
fumadocs-mdx:
|
fumadocs-mdx:
|
||||||
specifier: 8.2.33
|
specifier: ^8.2.34
|
||||||
version: 8.2.33(fumadocs-core@12.2.2(@types/react@18.3.3)(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
version: 8.2.34(fumadocs-core@12.5.6(@types/react@18.3.3)(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
||||||
fumadocs-openapi:
|
fumadocs-openapi:
|
||||||
specifier: ^3.1.3
|
specifier: ^3.3.0
|
||||||
version: 3.3.0
|
version: 3.3.0
|
||||||
fumadocs-ui:
|
fumadocs-ui:
|
||||||
specifier: 12.2.2
|
specifier: ^12.5.6
|
||||||
version: 12.2.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.7)
|
version: 12.5.6(@types/react-dom@18.3.0)(@types/react@18.3.3)(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.7)
|
||||||
lucide-react:
|
lucide-react:
|
||||||
specifier: ^0.394.0
|
specifier: ^0.394.0
|
||||||
version: 0.394.0(react@18.3.1)
|
version: 0.394.0(react@18.3.1)
|
||||||
@@ -2251,6 +2251,19 @@ packages:
|
|||||||
'@types/react-dom':
|
'@types/react-dom':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-accordion@1.2.0':
|
||||||
|
resolution: {integrity: sha512-HJOzSX8dQqtsp/3jVxCU3CXEONF7/2jlGAB28oX8TTw1Dz8JYbEI1UcL8355PuLBE41/IRRMvCw7VkiK/jcUOQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@radix-ui/react-alert-dialog@1.1.1':
|
'@radix-ui/react-alert-dialog@1.1.1':
|
||||||
resolution: {integrity: sha512-wmCoJwj7byuVuiLKqDLlX7ClSUU0vd9sdCeM+2Ls+uf13+cpSJoMgwysHq1SGVVkJj5Xn0XWi1NoRCdkMpr6Mw==}
|
resolution: {integrity: sha512-wmCoJwj7byuVuiLKqDLlX7ClSUU0vd9sdCeM+2Ls+uf13+cpSJoMgwysHq1SGVVkJj5Xn0XWi1NoRCdkMpr6Mw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2316,6 +2329,19 @@ packages:
|
|||||||
'@types/react-dom':
|
'@types/react-dom':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-collapsible@1.1.0':
|
||||||
|
resolution: {integrity: sha512-zQY7Epa8sTL0mq4ajSJpjgn2YmCgyrG7RsQgLp3C0LQVkG7+Tf6Pv1CeNWZLyqMjhdPkBa5Lx7wYBeSu7uCSTA==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@radix-ui/react-collection@1.0.3':
|
'@radix-ui/react-collection@1.0.3':
|
||||||
resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==}
|
resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -5409,15 +5435,15 @@ packages:
|
|||||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
fumadocs-core@12.2.2:
|
fumadocs-core@12.5.6:
|
||||||
resolution: {integrity: sha512-e8WZ/+iNUuqsxMHWYr/gBXjB5tHVJpeNfNkINyzrwDpatVQ3Ds3sGyvPn/cWkNka4ZYvMbwkjw/7n/0ijsjfRA==}
|
resolution: {integrity: sha512-sKbVq+Yrf7uLZD/pHojLGwClRxuOyjR1NaIlm/cO9dCaEO6n568NTom/2rEn+jyhII+LbGTJqfIJmktBW6rgNA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
next: '>= 14.1.0'
|
next: '>= 14.1.0'
|
||||||
react: '>= 18'
|
react: '>= 18'
|
||||||
react-dom: '>= 18'
|
react-dom: '>= 18'
|
||||||
|
|
||||||
fumadocs-mdx@8.2.33:
|
fumadocs-mdx@8.2.34:
|
||||||
resolution: {integrity: sha512-bKT4CaFMWrPYUqsM2MD6uN4i2XIgZ2mCw9XoMJMpPS3Oq2Eq5MlNs9B5L6ItO7FfckCb9hoCA6LHdT1tVkgtyQ==}
|
resolution: {integrity: sha512-vq7gd16z3fxMCjkjzFSTkqbQXbhZ3ucNvXAWdQxhkbhRbx3EAcmokkbcySsqVdqHPDIm0eGmCV33fQJsku1DgA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
fumadocs-core: 12.x.x
|
fumadocs-core: 12.x.x
|
||||||
next: '>= 14.1.0'
|
next: '>= 14.1.0'
|
||||||
@@ -5425,8 +5451,8 @@ packages:
|
|||||||
fumadocs-openapi@3.3.0:
|
fumadocs-openapi@3.3.0:
|
||||||
resolution: {integrity: sha512-a6G1+FoBA4kH2HnjlgwmPpO9z4itrKPRENkVqxJPsOCwpCKdHZc6Tpwogo9CXvEifGqjAvyTbhNPy0N3+YmHLg==}
|
resolution: {integrity: sha512-a6G1+FoBA4kH2HnjlgwmPpO9z4itrKPRENkVqxJPsOCwpCKdHZc6Tpwogo9CXvEifGqjAvyTbhNPy0N3+YmHLg==}
|
||||||
|
|
||||||
fumadocs-ui@12.2.2:
|
fumadocs-ui@12.5.6:
|
||||||
resolution: {integrity: sha512-cOUiGk/Bp8Cqd/lBx5LqjbCHO4Ny8qtFItJog6aI5POFVJDJoYuCMv65MLoS/ar7QxIdaiFSw2XYYziZQaLmrQ==}
|
resolution: {integrity: sha512-8kYsrSCbRuo2rS09xTAb5HejtH8QDsSlqWGC8k+D9GI4WdAW7kAQCg6k9idnhhP/nq3QOsyMtvpoUGkje91bpQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
next: '>= 14.1.0'
|
next: '>= 14.1.0'
|
||||||
react: '>= 18'
|
react: '>= 18'
|
||||||
@@ -6212,10 +6238,10 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^16.5.1 || ^17.0.0 || ^18.0.0
|
react: ^16.5.1 || ^17.0.0 || ^18.0.0
|
||||||
|
|
||||||
lucide-react@0.395.0:
|
lucide-react@0.414.0:
|
||||||
resolution: {integrity: sha512-6hzdNH5723A4FLaYZWpK50iyZH8iS2Jq5zuPRRotOFkhu6kxxJiebVdJ72tCR5XkiIeYFOU5NUawFZOac+VeYw==}
|
resolution: {integrity: sha512-Krr/MHg9AWoJc52qx8hyJ64X9++JNfS1wjaJviLM1EP/68VNB7Tv0VMldLCB1aUe6Ka9QxURPhQm/eB6cqOM3A==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^16.5.1 || ^17.0.0 || ^18.0.0
|
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||||
|
|
||||||
luxon@3.4.4:
|
luxon@3.4.4:
|
||||||
resolution: {integrity: sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==}
|
resolution: {integrity: sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==}
|
||||||
@@ -10203,18 +10229,17 @@ snapshots:
|
|||||||
'@types/react': 18.3.3
|
'@types/react': 18.3.3
|
||||||
'@types/react-dom': 18.3.0
|
'@types/react-dom': 18.3.0
|
||||||
|
|
||||||
'@radix-ui/react-accordion@1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
'@radix-ui/react-accordion@1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.25.0
|
'@radix-ui/primitive': 1.1.0
|
||||||
'@radix-ui/primitive': 1.0.1
|
'@radix-ui/react-collapsible': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
'@radix-ui/react-collapsible': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
'@radix-ui/react-collection': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1)
|
||||||
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.3)(react@18.3.1)
|
'@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1)
|
||||||
'@radix-ui/react-context': 1.0.1(@types/react@18.3.3)(react@18.3.1)
|
'@radix-ui/react-direction': 1.1.0(@types/react@18.3.3)(react@18.3.1)
|
||||||
'@radix-ui/react-direction': 1.0.1(@types/react@18.3.3)(react@18.3.1)
|
'@radix-ui/react-id': 1.1.0(@types/react@18.3.3)(react@18.3.1)
|
||||||
'@radix-ui/react-id': 1.0.1(@types/react@18.3.3)(react@18.3.1)
|
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.3)(react@18.3.1)
|
||||||
'@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.3.3)(react@18.3.1)
|
|
||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
@@ -10298,17 +10323,16 @@ snapshots:
|
|||||||
'@types/react': 18.3.3
|
'@types/react': 18.3.3
|
||||||
'@types/react-dom': 18.3.0
|
'@types/react-dom': 18.3.0
|
||||||
|
|
||||||
'@radix-ui/react-collapsible@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
'@radix-ui/react-collapsible@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.25.0
|
'@radix-ui/primitive': 1.1.0
|
||||||
'@radix-ui/primitive': 1.0.1
|
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1)
|
||||||
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.3)(react@18.3.1)
|
'@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1)
|
||||||
'@radix-ui/react-context': 1.0.1(@types/react@18.3.3)(react@18.3.1)
|
'@radix-ui/react-id': 1.1.0(@types/react@18.3.3)(react@18.3.1)
|
||||||
'@radix-ui/react-id': 1.0.1(@types/react@18.3.3)(react@18.3.1)
|
'@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
'@radix-ui/react-presence': 1.0.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.3)(react@18.3.1)
|
||||||
'@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.3.3)(react@18.3.1)
|
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.3)(react@18.3.1)
|
||||||
'@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.3)(react@18.3.1)
|
|
||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
@@ -10328,19 +10352,6 @@ snapshots:
|
|||||||
'@types/react': 18.3.3
|
'@types/react': 18.3.3
|
||||||
'@types/react-dom': 18.3.0
|
'@types/react-dom': 18.3.0
|
||||||
|
|
||||||
'@radix-ui/react-collection@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
|
||||||
dependencies:
|
|
||||||
'@babel/runtime': 7.25.0
|
|
||||||
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.3)(react@18.3.1)
|
|
||||||
'@radix-ui/react-context': 1.0.1(@types/react@18.3.3)(react@18.3.1)
|
|
||||||
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
|
||||||
'@radix-ui/react-slot': 1.0.2(@types/react@18.3.3)(react@18.3.1)
|
|
||||||
react: 18.3.1
|
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
|
||||||
optionalDependencies:
|
|
||||||
'@types/react': 18.3.3
|
|
||||||
'@types/react-dom': 18.3.0
|
|
||||||
|
|
||||||
'@radix-ui/react-collection@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
|
'@radix-ui/react-collection@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.2.0)
|
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.2.0)
|
||||||
@@ -10529,13 +10540,6 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 18.3.3
|
'@types/react': 18.3.3
|
||||||
|
|
||||||
'@radix-ui/react-direction@1.0.1(@types/react@18.3.3)(react@18.3.1)':
|
|
||||||
dependencies:
|
|
||||||
'@babel/runtime': 7.25.0
|
|
||||||
react: 18.3.1
|
|
||||||
optionalDependencies:
|
|
||||||
'@types/react': 18.3.3
|
|
||||||
|
|
||||||
'@radix-ui/react-direction@1.1.0(@types/react@18.3.3)(react@18.2.0)':
|
'@radix-ui/react-direction@1.1.0(@types/react@18.3.3)(react@18.2.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
@@ -12409,7 +12413,7 @@ snapshots:
|
|||||||
|
|
||||||
'@types/hast@3.0.4':
|
'@types/hast@3.0.4':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/unist': 2.0.10
|
'@types/unist': 3.0.2
|
||||||
|
|
||||||
'@types/http-cache-semantics@4.0.4': {}
|
'@types/http-cache-semantics@4.0.4': {}
|
||||||
|
|
||||||
@@ -12429,7 +12433,7 @@ snapshots:
|
|||||||
|
|
||||||
'@types/mdast@4.0.4':
|
'@types/mdast@4.0.4':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/unist': 2.0.10
|
'@types/unist': 3.0.2
|
||||||
|
|
||||||
'@types/mdx@2.0.13': {}
|
'@types/mdx@2.0.13': {}
|
||||||
|
|
||||||
@@ -14033,7 +14037,7 @@ snapshots:
|
|||||||
eslint: 8.45.0
|
eslint: 8.45.0
|
||||||
eslint-import-resolver-node: 0.3.9
|
eslint-import-resolver-node: 0.3.9
|
||||||
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.45.0)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.45.0))(eslint@8.45.0)
|
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.45.0)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.45.0))(eslint@8.45.0)
|
||||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.45.0)(typescript@5.1.6))(eslint-import-resolver-typescript@3.6.1)(eslint@8.45.0)
|
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.45.0)(typescript@5.1.6))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.45.0)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.45.0))(eslint@8.45.0))(eslint@8.45.0)
|
||||||
eslint-plugin-jsx-a11y: 6.9.0(eslint@8.45.0)
|
eslint-plugin-jsx-a11y: 6.9.0(eslint@8.45.0)
|
||||||
eslint-plugin-react: 7.35.0(eslint@8.45.0)
|
eslint-plugin-react: 7.35.0(eslint@8.45.0)
|
||||||
eslint-plugin-react-hooks: 5.0.0-canary-7118f5dd7-20230705(eslint@8.45.0)
|
eslint-plugin-react-hooks: 5.0.0-canary-7118f5dd7-20230705(eslint@8.45.0)
|
||||||
@@ -14057,7 +14061,7 @@ snapshots:
|
|||||||
enhanced-resolve: 5.17.1
|
enhanced-resolve: 5.17.1
|
||||||
eslint: 8.45.0
|
eslint: 8.45.0
|
||||||
eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.45.0)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.45.0)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.45.0))(eslint@8.45.0))(eslint@8.45.0)
|
eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.45.0)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.45.0)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.45.0))(eslint@8.45.0))(eslint@8.45.0)
|
||||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.45.0)(typescript@5.1.6))(eslint-import-resolver-typescript@3.6.1)(eslint@8.45.0)
|
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.45.0)(typescript@5.1.6))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.45.0)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.45.0))(eslint@8.45.0))(eslint@8.45.0)
|
||||||
fast-glob: 3.3.2
|
fast-glob: 3.3.2
|
||||||
get-tsconfig: 4.7.5
|
get-tsconfig: 4.7.5
|
||||||
is-core-module: 2.15.0
|
is-core-module: 2.15.0
|
||||||
@@ -14079,7 +14083,7 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.45.0)(typescript@5.1.6))(eslint-import-resolver-typescript@3.6.1)(eslint@8.45.0):
|
eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.45.0)(typescript@5.1.6))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.45.0)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.45.0))(eslint@8.45.0))(eslint@8.45.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
array-includes: 3.1.8
|
array-includes: 3.1.8
|
||||||
array.prototype.findlastindex: 1.2.5
|
array.prototype.findlastindex: 1.2.5
|
||||||
@@ -14434,7 +14438,7 @@ snapshots:
|
|||||||
fsevents@2.3.3:
|
fsevents@2.3.3:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
fumadocs-core@12.2.2(@types/react@18.3.3)(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
fumadocs-core@12.5.6(@types/react@18.3.3)(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@formatjs/intl-localematcher': 0.5.4
|
'@formatjs/intl-localematcher': 0.5.4
|
||||||
'@shikijs/rehype': 1.12.0
|
'@shikijs/rehype': 1.12.0
|
||||||
@@ -14458,13 +14462,13 @@ snapshots:
|
|||||||
- '@types/react'
|
- '@types/react'
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
fumadocs-mdx@8.2.33(fumadocs-core@12.2.2(@types/react@18.3.3)(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)):
|
fumadocs-mdx@8.2.34(fumadocs-core@12.5.6(@types/react@18.3.3)(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@mdx-js/mdx': 3.0.1
|
'@mdx-js/mdx': 3.0.1
|
||||||
cross-spawn: 7.0.3
|
cross-spawn: 7.0.3
|
||||||
estree-util-value-to-estree: 3.1.2
|
estree-util-value-to-estree: 3.1.2
|
||||||
fast-glob: 3.3.2
|
fast-glob: 3.3.2
|
||||||
fumadocs-core: 12.2.2(@types/react@18.3.3)(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
fumadocs-core: 12.5.6(@types/react@18.3.3)(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
gray-matter: 4.0.3
|
gray-matter: 4.0.3
|
||||||
next: 14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
next: 14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
zod: 3.23.8
|
zod: 3.23.8
|
||||||
@@ -14479,10 +14483,10 @@ snapshots:
|
|||||||
json-schema-to-typescript: 14.1.0
|
json-schema-to-typescript: 14.1.0
|
||||||
openapi-sampler: 1.5.1
|
openapi-sampler: 1.5.1
|
||||||
|
|
||||||
fumadocs-ui@12.2.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.7):
|
fumadocs-ui@12.5.6(@types/react-dom@18.3.0)(@types/react@18.3.3)(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.7):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@radix-ui/react-accordion': 1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@radix-ui/react-accordion': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
'@radix-ui/react-collapsible': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@radix-ui/react-collapsible': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
'@radix-ui/react-dialog': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@radix-ui/react-dialog': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
'@radix-ui/react-direction': 1.1.0(@types/react@18.3.3)(react@18.3.1)
|
'@radix-ui/react-direction': 1.1.0(@types/react@18.3.3)(react@18.3.1)
|
||||||
'@radix-ui/react-popover': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@radix-ui/react-popover': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
@@ -14491,13 +14495,14 @@ snapshots:
|
|||||||
'@tailwindcss/typography': 0.5.13(tailwindcss@3.4.7)
|
'@tailwindcss/typography': 0.5.13(tailwindcss@3.4.7)
|
||||||
class-variance-authority: 0.7.0
|
class-variance-authority: 0.7.0
|
||||||
cmdk: 1.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
cmdk: 1.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
fumadocs-core: 12.2.2(@types/react@18.3.3)(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
fumadocs-core: 12.5.6(@types/react@18.3.3)(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
lucide-react: 0.395.0(react@18.3.1)
|
lucide-react: 0.414.0(react@18.3.1)
|
||||||
next: 14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
next: 14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
next-themes: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
next-themes: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
react-medium-image-zoom: 5.2.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
react-medium-image-zoom: 5.2.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
swr: 2.2.5(react@18.3.1)
|
||||||
tailwind-merge: 2.4.0
|
tailwind-merge: 2.4.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@types/react'
|
- '@types/react'
|
||||||
@@ -15357,7 +15362,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
|
|
||||||
lucide-react@0.395.0(react@18.3.1):
|
lucide-react@0.414.0(react@18.3.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user