create-better-t-stack 2.24.5 → 2.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3795,6 +3795,7 @@ const DatabaseSetupSchema = enumType([
3795
3795
  "mongodb-atlas",
3796
3796
  "supabase",
3797
3797
  "d1",
3798
+ "docker",
3798
3799
  "none"
3799
3800
  ]).describe("Database hosting setup");
3800
3801
  const APISchema = enumType([
@@ -4135,21 +4136,43 @@ async function getDBSetupChoice(databaseType, dbSetup, orm, backend, runtime) {
4135
4136
  label: "Prisma Postgres",
4136
4137
  hint: "Instant Postgres for Global Applications"
4137
4138
  }] : [],
4139
+ {
4140
+ value: "docker",
4141
+ label: "Docker",
4142
+ hint: "Run locally with docker compose"
4143
+ },
4138
4144
  {
4139
4145
  value: "none",
4140
4146
  label: "None",
4141
4147
  hint: "Manual setup"
4142
4148
  }
4143
4149
  ];
4144
- else if (databaseType === "mongodb") options = [{
4145
- value: "mongodb-atlas",
4146
- label: "MongoDB Atlas",
4147
- hint: "The most effective way to deploy MongoDB"
4150
+ else if (databaseType === "mysql") options = [{
4151
+ value: "docker",
4152
+ label: "Docker",
4153
+ hint: "Run locally with docker compose"
4148
4154
  }, {
4149
4155
  value: "none",
4150
4156
  label: "None",
4151
4157
  hint: "Manual setup"
4152
4158
  }];
4159
+ else if (databaseType === "mongodb") options = [
4160
+ {
4161
+ value: "mongodb-atlas",
4162
+ label: "MongoDB Atlas",
4163
+ hint: "The most effective way to deploy MongoDB"
4164
+ },
4165
+ {
4166
+ value: "docker",
4167
+ label: "Docker",
4168
+ hint: "Run locally with docker compose"
4169
+ },
4170
+ {
4171
+ value: "none",
4172
+ label: "None",
4173
+ hint: "Manual setup"
4174
+ }
4175
+ ];
4153
4176
  else return "none";
4154
4177
  const response = await select({
4155
4178
  message: `Select ${databaseType} setup option`,
@@ -5050,6 +5073,14 @@ function processAndValidateFlags(options, providedFlags, projectName) {
5050
5073
  process.exit(1);
5051
5074
  }
5052
5075
  }
5076
+ if (config.dbSetup === "docker" && config.database === "sqlite") {
5077
+ consola$1.fatal("Docker setup is not compatible with SQLite database. SQLite is file-based and doesn't require Docker. Please use '--database postgres', '--database mysql', '--database mongodb', or choose a different setup.");
5078
+ process.exit(1);
5079
+ }
5080
+ if (config.dbSetup === "docker" && config.runtime === "workers") {
5081
+ consola$1.fatal("Docker setup is not compatible with Cloudflare Workers runtime. Workers runtime uses serverless databases (D1) and doesn't support local Docker containers. Please use '--db-setup d1' for SQLite or choose a different runtime.");
5082
+ process.exit(1);
5083
+ }
5053
5084
  if (providedFlags.has("runtime") && options.runtime === "workers" && config.backend && config.backend !== "hono") {
5054
5085
  consola$1.fatal(`Cloudflare Workers runtime (--runtime workers) is only supported with Hono backend (--backend hono). Current backend: ${config.backend}. Please use '--backend hono' or choose a different runtime.`);
5055
5086
  process.exit(1);
@@ -5070,10 +5101,18 @@ function processAndValidateFlags(options, providedFlags, projectName) {
5070
5101
  consola$1.fatal("Cloudflare Workers runtime (--runtime workers) is not compatible with MongoDB database. MongoDB requires Prisma or Mongoose ORM, but Workers runtime only supports Drizzle ORM. Please use a different database or runtime.");
5071
5102
  process.exit(1);
5072
5103
  }
5104
+ if (providedFlags.has("runtime") && options.runtime === "workers" && config.dbSetup === "docker") {
5105
+ consola$1.fatal("Cloudflare Workers runtime (--runtime workers) is not compatible with Docker setup. Workers runtime uses serverless databases (D1) and doesn't support local Docker containers. Please use '--db-setup d1' for SQLite or choose a different runtime.");
5106
+ process.exit(1);
5107
+ }
5073
5108
  if (providedFlags.has("database") && config.database === "mongodb" && config.runtime === "workers") {
5074
5109
  consola$1.fatal("MongoDB database is not compatible with Cloudflare Workers runtime. MongoDB requires Prisma or Mongoose ORM, but Workers runtime only supports Drizzle ORM. Please use a different database or runtime.");
5075
5110
  process.exit(1);
5076
5111
  }
5112
+ if (providedFlags.has("db-setup") && options.dbSetup === "docker" && config.runtime === "workers") {
5113
+ consola$1.fatal("Docker setup (--db-setup docker) is not compatible with Cloudflare Workers runtime. Workers runtime uses serverless databases (D1) and doesn't support local Docker containers. Please use '--db-setup d1' for SQLite or choose a different runtime.");
5114
+ process.exit(1);
5115
+ }
5077
5116
  const hasWebFrontendFlag = (config.frontend ?? []).some((f) => WEB_FRAMEWORKS.includes(f));
5078
5117
  if (config.webDeploy && config.webDeploy !== "none" && !hasWebFrontendFlag && providedFlags.has("frontend")) {
5079
5118
  consola$1.fatal("'--web-deploy' requires a web frontend. Please select a web frontend or set '--web-deploy none'.");
@@ -5864,6 +5903,12 @@ async function handleExtras(projectDir, context) {
5864
5903
  if (await fs.pathExists(runtimeWorkersDir)) await processAndCopyFiles("**/*", runtimeWorkersDir, projectDir, context, false);
5865
5904
  }
5866
5905
  }
5906
+ async function setupDockerComposeTemplates(projectDir, context) {
5907
+ if (context.dbSetup !== "docker" || context.database === "none") return;
5908
+ const serverAppDir = path.join(projectDir, "apps/server");
5909
+ const dockerSrcDir = path.join(PKG_ROOT, `templates/db-setup/docker-compose/${context.database}`);
5910
+ if (await fs.pathExists(dockerSrcDir)) await processAndCopyFiles("**/*", dockerSrcDir, serverAppDir, context);
5911
+ }
5867
5912
  async function setupDeploymentTemplates(projectDir, context) {
5868
5913
  if (context.webDeploy === "none") return;
5869
5914
  if (context.webDeploy === "workers") {
@@ -6613,7 +6658,7 @@ async function setupEnvironmentVariables(config) {
6613
6658
  let corsOrigin = "http://localhost:3001";
6614
6659
  if (hasReactRouter || hasSvelte) corsOrigin = "http://localhost:5173";
6615
6660
  let databaseUrl = null;
6616
- const specializedSetup = dbSetup === "turso" || dbSetup === "prisma-postgres" || dbSetup === "mongodb-atlas" || dbSetup === "neon" || dbSetup === "supabase" || dbSetup === "d1";
6661
+ const specializedSetup = dbSetup === "turso" || dbSetup === "prisma-postgres" || dbSetup === "mongodb-atlas" || dbSetup === "neon" || dbSetup === "supabase" || dbSetup === "d1" || dbSetup === "docker";
6617
6662
  if (database !== "none" && !specializedSetup) switch (database) {
6618
6663
  case "postgres":
6619
6664
  databaseUrl = "postgresql://postgres:password@localhost:5432/postgres";
@@ -6692,6 +6737,35 @@ async function setupCloudflareD1(config) {
6692
6737
  } catch (_err) {}
6693
6738
  }
6694
6739
 
6740
+ //#endregion
6741
+ //#region src/helpers/database-providers/docker-compose-setup.ts
6742
+ async function setupDockerCompose(config) {
6743
+ const { database, projectDir, projectName } = config;
6744
+ if (database === "none" || database === "sqlite") return;
6745
+ try {
6746
+ await writeEnvFile$4(projectDir, database, projectName);
6747
+ } catch (error) {
6748
+ if (error instanceof Error) console.error(`Error: ${error.message}`);
6749
+ }
6750
+ }
6751
+ async function writeEnvFile$4(projectDir, database, projectName) {
6752
+ const envPath = path.join(projectDir, "apps/server", ".env");
6753
+ const variables = [{
6754
+ key: "DATABASE_URL",
6755
+ value: getDatabaseUrl(database, projectName),
6756
+ condition: true
6757
+ }];
6758
+ await addEnvVariablesToFile(envPath, variables);
6759
+ }
6760
+ function getDatabaseUrl(database, projectName) {
6761
+ switch (database) {
6762
+ case "postgres": return `postgresql://postgres:password@localhost:5432/${projectName}`;
6763
+ case "mysql": return `mysql://user:password@localhost:3306/${projectName}`;
6764
+ case "mongodb": return `mongodb://root:password@localhost:27017/${projectName}?authSource=admin`;
6765
+ default: return "";
6766
+ }
6767
+ }
6768
+
6695
6769
  //#endregion
6696
6770
  //#region src/utils/command-exists.ts
6697
6771
  async function commandExists(command) {
@@ -7474,7 +7548,8 @@ async function setupDatabase(config) {
7474
7548
  devDependencies: [],
7475
7549
  projectDir: serverDir
7476
7550
  });
7477
- if (database === "sqlite" && dbSetup === "turso") await setupTurso(config);
7551
+ if (dbSetup === "docker") await setupDockerCompose(config);
7552
+ else if (database === "sqlite" && dbSetup === "turso") await setupTurso(config);
7478
7553
  else if (database === "sqlite" && dbSetup === "d1") await setupCloudflareD1(config);
7479
7554
  else if (database === "postgres") {
7480
7555
  if (orm === "prisma" && dbSetup === "prisma-postgres") await setupPrismaPostgres(config);
@@ -7901,15 +7976,68 @@ async function initializeGit(projectDir, useGit) {
7901
7976
  await $({ cwd: projectDir })`git commit -m ${"initial commit"}`;
7902
7977
  }
7903
7978
 
7979
+ //#endregion
7980
+ //#region src/utils/docker-utils.ts
7981
+ async function isDockerInstalled() {
7982
+ return commandExists("docker");
7983
+ }
7984
+ async function isDockerRunning() {
7985
+ try {
7986
+ const { $: $$1 } = await import("execa");
7987
+ await $$1`docker info`;
7988
+ return true;
7989
+ } catch {
7990
+ return false;
7991
+ }
7992
+ }
7993
+ function getDockerInstallInstructions(platform, database) {
7994
+ const isMac = platform === "darwin";
7995
+ const isWindows = platform === "win32";
7996
+ const isLinux = platform === "linux";
7997
+ let installUrl = "";
7998
+ let platformName = "";
7999
+ if (isMac) {
8000
+ installUrl = "https://docs.docker.com/desktop/setup/install/mac-install/";
8001
+ platformName = "macOS";
8002
+ } else if (isWindows) {
8003
+ installUrl = "https://docs.docker.com/desktop/setup/install/windows-install/";
8004
+ platformName = "Windows";
8005
+ } else if (isLinux) {
8006
+ installUrl = "https://docs.docker.com/desktop/setup/install/linux/";
8007
+ platformName = "Linux";
8008
+ }
8009
+ const databaseName = database === "mongodb" ? "MongoDB" : database === "mysql" ? "MySQL" : "PostgreSQL";
8010
+ return `${pc.yellow("IMPORTANT:")} Docker required for ${databaseName}. Install for ${platformName}:\n${pc.blue(installUrl)}`;
8011
+ }
8012
+ async function getDockerStatus(database) {
8013
+ const platform = os.platform();
8014
+ const installed = await isDockerInstalled();
8015
+ if (!installed) return {
8016
+ installed: false,
8017
+ running: false,
8018
+ message: getDockerInstallInstructions(platform, database)
8019
+ };
8020
+ const running = await isDockerRunning();
8021
+ if (!running) return {
8022
+ installed: true,
8023
+ running: false,
8024
+ message: `${pc.yellow("IMPORTANT:")} Docker is installed but not running.`
8025
+ };
8026
+ return {
8027
+ installed: true,
8028
+ running: true
8029
+ };
8030
+ }
8031
+
7904
8032
  //#endregion
7905
8033
  //#region src/helpers/project-generation/post-installation.ts
7906
- function displayPostInstallInstructions(config) {
8034
+ async function displayPostInstallInstructions(config) {
7907
8035
  const { database, relativePath, packageManager, depsInstalled, orm, addons, runtime, frontend, backend, dbSetup, webDeploy } = config;
7908
8036
  const isConvex = backend === "convex";
7909
8037
  const runCmd = packageManager === "npm" ? "npm run" : packageManager;
7910
8038
  const cdCmd = `cd ${relativePath}`;
7911
8039
  const hasHuskyOrBiome = addons?.includes("husky") || addons?.includes("biome");
7912
- const databaseInstructions = !isConvex && database !== "none" ? getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup) : "";
8040
+ const databaseInstructions = !isConvex && database !== "none" ? await getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup) : "";
7913
8041
  const tauriInstructions = addons?.includes("tauri") ? getTauriInstructions(runCmd) : "";
7914
8042
  const lintingInstructions = hasHuskyOrBiome ? getLintingInstructions(runCmd) : "";
7915
8043
  const nativeInstructions = frontend?.includes("native-nativewind") || frontend?.includes("native-unistyles") ? getNativeInstructions(isConvex) : "";
@@ -7978,8 +8106,15 @@ function getNativeInstructions(isConvex) {
7978
8106
  function getLintingInstructions(runCmd) {
7979
8107
  return `${pc.bold("Linting and formatting:")}\n${pc.cyan("•")} Format and lint fix: ${`${runCmd} check`}\n`;
7980
8108
  }
7981
- function getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup) {
8109
+ async function getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup) {
7982
8110
  const instructions = [];
8111
+ if (dbSetup === "docker") {
8112
+ const dockerStatus = await getDockerStatus(database);
8113
+ if (dockerStatus.message) {
8114
+ instructions.push(dockerStatus.message);
8115
+ instructions.push("");
8116
+ }
8117
+ }
7983
8118
  if (runtime === "workers" && dbSetup === "d1") {
7984
8119
  const packageManager = runCmd === "npm run" ? "npm" : runCmd || "npm";
7985
8120
  instructions.push(`${pc.cyan("1.")} Login to Cloudflare: ${pc.white(`${packageManager} wrangler login`)}`);
@@ -7993,12 +8128,17 @@ function getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup) {
7993
8128
  if (orm === "prisma") {
7994
8129
  if (database === "sqlite") instructions.push(`${pc.yellow("NOTE:")} Turso support with Prisma is in Early Access and requires additional setup.`, `Learn more at: https://www.prisma.io/docs/orm/overview/databases/turso`);
7995
8130
  if (runtime === "bun") instructions.push(`${pc.yellow("NOTE:")} Prisma with Bun may require additional configuration. If you encounter errors,\nfollow the guidance provided in the error messages`);
8131
+ if (database === "mongodb" && dbSetup === "docker") instructions.push(`${pc.yellow("WARNING:")} Prisma + MongoDB + Docker combination may not work.`);
8132
+ if (dbSetup === "docker") instructions.push(`${pc.cyan("•")} Start docker container: ${`${runCmd} db:start`}`);
7996
8133
  instructions.push(`${pc.cyan("•")} Apply schema: ${`${runCmd} db:push`}`);
7997
8134
  instructions.push(`${pc.cyan("•")} Database UI: ${`${runCmd} db:studio`}`);
7998
8135
  } else if (orm === "drizzle") {
8136
+ if (dbSetup === "docker") instructions.push(`${pc.cyan("•")} Start docker container: ${`${runCmd} db:start`}`);
7999
8137
  instructions.push(`${pc.cyan("•")} Apply schema: ${`${runCmd} db:push`}`);
8000
8138
  instructions.push(`${pc.cyan("•")} Database UI: ${`${runCmd} db:studio`}`);
8001
8139
  if (database === "sqlite" && dbSetup !== "d1") instructions.push(`${pc.cyan("•")} Start local DB (if needed): ${`cd apps/server && ${runCmd} db:local`}`);
8140
+ } else if (orm === "mongoose") {
8141
+ if (dbSetup === "docker") instructions.push(`${pc.cyan("•")} Start docker container: ${`${runCmd} db:start`}`);
8002
8142
  } else if (orm === "none") instructions.push(`${pc.yellow("NOTE:")} Manual database schema setup required.`);
8003
8143
  return instructions.length ? `${pc.bold("Database commands:")}\n${instructions.join("\n")}` : "";
8004
8144
  }
@@ -8065,6 +8205,12 @@ async function updateRootPackageJson(projectDir, options) {
8065
8205
  scripts["db:migrate"] = `turbo -F ${backendPackageName} db:migrate`;
8066
8206
  }
8067
8207
  }
8208
+ if (options.dbSetup === "docker") {
8209
+ scripts["db:start"] = `turbo -F ${backendPackageName} db:start`;
8210
+ scripts["db:watch"] = `turbo -F ${backendPackageName} db:watch`;
8211
+ scripts["db:stop"] = `turbo -F ${backendPackageName} db:stop`;
8212
+ scripts["db:down"] = `turbo -F ${backendPackageName} db:down`;
8213
+ }
8068
8214
  } else if (options.packageManager === "pnpm") {
8069
8215
  scripts.dev = devScript;
8070
8216
  scripts.build = "pnpm -r build";
@@ -8084,6 +8230,12 @@ async function updateRootPackageJson(projectDir, options) {
8084
8230
  scripts["db:migrate"] = `pnpm --filter ${backendPackageName} db:migrate`;
8085
8231
  }
8086
8232
  }
8233
+ if (options.dbSetup === "docker") {
8234
+ scripts["db:start"] = `pnpm --filter ${backendPackageName} db:start`;
8235
+ scripts["db:watch"] = `pnpm --filter ${backendPackageName} db:watch`;
8236
+ scripts["db:stop"] = `pnpm --filter ${backendPackageName} db:stop`;
8237
+ scripts["db:down"] = `pnpm --filter ${backendPackageName} db:down`;
8238
+ }
8087
8239
  } else if (options.packageManager === "npm") {
8088
8240
  scripts.dev = devScript;
8089
8241
  scripts.build = "npm run build --workspaces";
@@ -8103,6 +8255,12 @@ async function updateRootPackageJson(projectDir, options) {
8103
8255
  scripts["db:migrate"] = `npm run db:migrate --workspace ${backendPackageName}`;
8104
8256
  }
8105
8257
  }
8258
+ if (options.dbSetup === "docker") {
8259
+ scripts["db:start"] = `npm run db:start --workspace ${backendPackageName}`;
8260
+ scripts["db:watch"] = `npm run db:watch --workspace ${backendPackageName}`;
8261
+ scripts["db:stop"] = `npm run db:stop --workspace ${backendPackageName}`;
8262
+ scripts["db:down"] = `npm run db:down --workspace ${backendPackageName}`;
8263
+ }
8106
8264
  } else if (options.packageManager === "bun") {
8107
8265
  scripts.dev = devScript;
8108
8266
  scripts.build = "bun run --filter '*' build";
@@ -8122,6 +8280,12 @@ async function updateRootPackageJson(projectDir, options) {
8122
8280
  scripts["db:migrate"] = `bun run --filter ${backendPackageName} db:migrate`;
8123
8281
  }
8124
8282
  }
8283
+ if (options.dbSetup === "docker") {
8284
+ scripts["db:start"] = `bun run --filter ${backendPackageName} db:start`;
8285
+ scripts["db:watch"] = `bun run --filter ${backendPackageName} db:watch`;
8286
+ scripts["db:stop"] = `bun run --filter ${backendPackageName} db:stop`;
8287
+ scripts["db:down"] = `bun run --filter ${backendPackageName} db:down`;
8288
+ }
8125
8289
  }
8126
8290
  if (options.addons.includes("biome")) scripts.check = "biome check --write .";
8127
8291
  if (options.addons.includes("husky")) {
@@ -8166,6 +8330,12 @@ async function updateServerPackageJson(projectDir, options) {
8166
8330
  scripts["db:migrate"] = "drizzle-kit migrate";
8167
8331
  }
8168
8332
  }
8333
+ if (options.dbSetup === "docker") {
8334
+ scripts["db:start"] = "docker compose up -d";
8335
+ scripts["db:watch"] = "docker compose up";
8336
+ scripts["db:stop"] = "docker compose stop";
8337
+ scripts["db:down"] = "docker compose down";
8338
+ }
8169
8339
  await fs.writeJson(serverPackageJsonPath, serverPackageJson, { spaces: 2 });
8170
8340
  }
8171
8341
  async function updateConvexPackageJson(projectDir, options) {
@@ -8189,6 +8359,7 @@ async function createProject(options) {
8189
8359
  await setupBackendFramework(projectDir, options);
8190
8360
  if (!isConvex) {
8191
8361
  await setupDbOrmTemplates(projectDir, options);
8362
+ await setupDockerComposeTemplates(projectDir, options);
8192
8363
  await setupAuthTemplate(projectDir, options);
8193
8364
  }
8194
8365
  if (options.examples.length > 0 && options.examples[0] !== "none") await setupExamplesTemplate(projectDir, options);
@@ -8218,7 +8389,7 @@ async function createProject(options) {
8218
8389
  await generateCloudflareWorkerTypes(options);
8219
8390
  }
8220
8391
  await initializeGit(projectDir, options.git);
8221
- displayPostInstallInstructions({
8392
+ await displayPostInstallInstructions({
8222
8393
  ...options,
8223
8394
  depsInstalled: options.install
8224
8395
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-better-t-stack",
3
- "version": "2.24.5",
3
+ "version": "2.25.0",
4
4
  "description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -39,5 +39,23 @@
39
39
  "persistent": true
40
40
  }
41
41
  {{/unless}}{{/if}}
42
+ {{#if (eq dbSetup "docker")}},
43
+ "db:start": {
44
+ "cache": false,
45
+ "persistent": true
46
+ },
47
+ "db:stop": {
48
+ "cache": false,
49
+ "persistent": true
50
+ },
51
+ "db:watch": {
52
+ "cache": false,
53
+ "persistent": true
54
+ },
55
+ "db:down": {
56
+ "cache": false,
57
+ "persistent": true
58
+ }
59
+ {{/if}}
42
60
  }
43
61
  }
@@ -0,0 +1,23 @@
1
+ name: {{projectName}}
2
+
3
+ services:
4
+ mongodb:
5
+ image: mongo
6
+ container_name: {{projectName}}-mongodb
7
+ environment:
8
+ MONGO_INITDB_ROOT_USERNAME: root
9
+ MONGO_INITDB_ROOT_PASSWORD: password
10
+ MONGO_INITDB_DATABASE: {{projectName}}
11
+ ports:
12
+ - "27017:27017"
13
+ volumes:
14
+ - {{projectName}}_mongodb_data:/data/db
15
+ healthcheck:
16
+ test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
17
+ interval: 10s
18
+ timeout: 5s
19
+ retries: 5
20
+ restart: unless-stopped
21
+
22
+ volumes:
23
+ {{projectName}}_mongodb_data:
@@ -0,0 +1,24 @@
1
+ name: {{projectName}}
2
+
3
+ services:
4
+ mysql:
5
+ image: mysql
6
+ container_name: {{projectName}}-mysql
7
+ environment:
8
+ MYSQL_ROOT_PASSWORD: password
9
+ MYSQL_DATABASE: {{projectName}}
10
+ MYSQL_USER: user
11
+ MYSQL_PASSWORD: password
12
+ ports:
13
+ - "3306:3306"
14
+ volumes:
15
+ - {{projectName}}_mysql_data:/var/lib/mysql
16
+ healthcheck:
17
+ test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
18
+ interval: 10s
19
+ timeout: 5s
20
+ retries: 5
21
+ restart: unless-stopped
22
+
23
+ volumes:
24
+ {{projectName}}_mysql_data:
@@ -0,0 +1,23 @@
1
+ name: {{projectName}}
2
+
3
+ services:
4
+ postgres:
5
+ image: postgres
6
+ container_name: {{projectName}}-postgres
7
+ environment:
8
+ POSTGRES_DB: {{projectName}}
9
+ POSTGRES_USER: postgres
10
+ POSTGRES_PASSWORD: password
11
+ ports:
12
+ - "5432:5432"
13
+ volumes:
14
+ - {{projectName}}_postgres_data:/var/lib/postgresql/data
15
+ healthcheck:
16
+ test: ["CMD-SHELL", "pg_isready -U postgres"]
17
+ interval: 10s
18
+ timeout: 5s
19
+ retries: 5
20
+ restart: unless-stopped
21
+
22
+ volumes:
23
+ {{projectName}}_postgres_data: