@django-stack/cli 0.6.0 → 0.8.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@django-stack/cli",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "The production-ready Django, batteries included stack. Create and manage DjangoStack projects: a Django backend, a frontend, Postgres and Docker Compose in one command.",
5
5
  "license": "MIT",
6
6
  "author": "Leon van der Grient",
@@ -25,10 +25,12 @@ RUN --mount=type=cache,target=/root/.cache/uv \
25
25
 
26
26
  # Development runs as root, so files the container writes into the mounted
27
27
  # source (such as new migrations) work on every host. Production does not.
28
+ # The entrypoint runs with sh, so it works without the executable bit (the
29
+ # mounted source keeps the host's file modes).
28
30
  FROM deps AS dev
29
31
  RUN --mount=type=cache,target=/root/.cache/uv \
30
32
  uv sync --no-install-project
31
- ENTRYPOINT ["/app/entrypoint.sh"]
33
+ ENTRYPOINT ["sh", "/app/entrypoint.sh"]
32
34
  CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
33
35
 
34
36
  FROM base AS prod
@@ -41,5 +43,5 @@ USER app
41
43
  EXPOSE 8000
42
44
  HEALTHCHECK --interval=10s --timeout=5s --start-period=30s --retries=5 \
43
45
  CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/readyz', timeout=4)"
44
- ENTRYPOINT ["/app/entrypoint.sh"]
46
+ ENTRYPOINT ["sh", "/app/entrypoint.sh"]
45
47
  CMD ["gunicorn", "config.asgi:application", "--worker-class", "uvicorn_worker.UvicornWorker", "--bind", "0.0.0.0:8000", "--workers", "3", "--access-logfile", "-", "--no-control-socket"]
@@ -5,7 +5,7 @@ description = "The Django backend of {{project_name}}."
5
5
  requires-python = ">=3.12"
6
6
  dependencies = [
7
7
  "Django>=6.1,<6.2",
8
- "django-stack[server,s3]>=0.6.0",
8
+ "django-stack[server,s3]>=0.8.0",
9
9
  "django-headless[schema]>=1.1.1",
10
10
  "django-content-studio[images,huey]>=1.11.0",
11
11
  ]
@@ -6,7 +6,9 @@ A website with a Django backend and a frontend built with {{frontend_label}}, cr
6
6
  - [Django Headless](https://djangoheadless.org) serves the content API.
7
7
  - [Django Content Studio](https://djangocontentstudio.org) is the admin.
8
8
  - [{{frontend_label}}]({{frontend_url}}) renders the site.
9
- - Postgres stores the content; Valkey is the cache and task queue.
9
+ - Postgres stores the content, and by default also the cache and the task
10
+ queue (`CACHE_URL` and `TASKS_URL` in `.env`); Valkey can take those over
11
+ with the `valkey` profile.
10
12
 
11
13
  ## Start
12
14
 
@@ -16,9 +18,12 @@ You need Docker.
16
18
  docker compose up --build
17
19
  ```
18
20
 
19
- - Site: http://localhost:3000
20
- - Admin: http://localhost:3000/admin/ (user `admin`, password `ADMIN_PASSWORD` in `.env`)
21
- - Outgoing mail: http://localhost:8025
21
+ - Site: http://localhost:{{site_port}}
22
+ - Admin: http://localhost:{{site_port}}/admin/ (user `admin`, password `ADMIN_PASSWORD` in `.env`)
23
+ - Outgoing mail: http://localhost:{{mail_port}}
24
+
25
+ The ports are `SITE_PORT` and `MAIL_PORT` in `.env`. When you change
26
+ `SITE_PORT`, change `SITE_URL` and `BACKEND_URL` with it.
22
27
 
23
28
  The first start migrates the database, creates the admin user and adds demo
24
29
  content. Edit a page in the admin, publish, and reload the site.
@@ -2,12 +2,14 @@
2
2
  #
3
3
  # COMPOSE_PROFILES in .env picks the services:
4
4
  # dev,db `docker compose up` on a laptop: dev servers with hot reload,
5
- # http://localhost:3000, Mailpit at http://localhost:8025.
5
+ # http://localhost:3000, Mailpit at http://localhost:8025 (the
6
+ # *_PORT variables in .env change the ports).
6
7
  # prod,db `docker compose up -d` on a server: production images behind
7
8
  # Caddy on ports 80 and 443, with automatic HTTPS and daily backups.
8
9
  # Leave out `db` to use an external Postgres through DATABASE_URL, and add
9
10
  # `s3` in development for a local S3 service (see .env). `analytics` runs
10
- # Umami for page analytics.
11
+ # Umami for page analytics, `valkey` the Valkey service for CACHE_URL or
12
+ # TASKS_URL.
11
13
  #
12
14
  # The frontend only receives the variables it needs: never the full-access
13
15
  # API key or the database password.
@@ -42,6 +44,7 @@ x-backend-depends: &backend-depends
42
44
  required: false
43
45
  cache:
44
46
  condition: service_healthy
47
+ required: false
45
48
  s3:
46
49
  condition: service_started
47
50
  required: false
@@ -72,7 +75,7 @@ services:
72
75
  - ./backend:/app
73
76
  - media:/app/media
74
77
  ports:
75
- - "127.0.0.1:8000:8000"
78
+ - "127.0.0.1:${BACKEND_PORT:-8000}:8000"
76
79
  depends_on: *backend-depends
77
80
  healthcheck: *backend-health
78
81
  restart: unless-stopped
@@ -87,6 +90,9 @@ services:
87
90
  volumes:
88
91
  - ./backend:/app
89
92
  - media:/app/media
93
+ # 0 with TASKS_URL=immediate://: tasks run in the request.
94
+ deploy:
95
+ replicas: ${TASK_WORKERS:-1}
90
96
  depends_on:
91
97
  backend:
92
98
  condition: service_healthy
@@ -102,7 +108,7 @@ services:
102
108
  - ./frontend:/app
103
109
  - frontend_node_modules:/app/node_modules
104
110
  ports:
105
- - "127.0.0.1:3000:3000"
111
+ - "127.0.0.1:${SITE_PORT:-3000}:3000"
106
112
  depends_on:
107
113
  backend:
108
114
  condition: service_healthy
@@ -112,11 +118,12 @@ services:
112
118
  profiles: [dev]
113
119
  image: axllent/mailpit:v1.27
114
120
  ports:
115
- - "127.0.0.1:8025:8025"
121
+ - "127.0.0.1:${MAIL_PORT:-8025}:8025"
116
122
  restart: unless-stopped
117
123
 
118
124
  # A local S3 service, so development runs the same storage code as
119
- # production with S3. Files are public at http://localhost:8333/<bucket>/.
125
+ # production with S3. Files are public at http://localhost:8333/<bucket>/
126
+ # (S3_PORT).
120
127
  s3:
121
128
  profiles: [s3]
122
129
  image: chrislusf/seaweedfs:4.52
@@ -124,7 +131,7 @@ services:
124
131
  volumes:
125
132
  - s3data:/data
126
133
  ports:
127
- - "127.0.0.1:8333:8333"
134
+ - "127.0.0.1:${S3_PORT:-8333}:8333"
128
135
  restart: unless-stopped
129
136
 
130
137
  # Production -------------------------------------------------------------
@@ -181,6 +188,7 @@ services:
181
188
  healthcheck:
182
189
  disable: true
183
190
  deploy:
191
+ replicas: ${TASK_WORKERS:-1}
184
192
  resources:
185
193
  limits:
186
194
  memory: 512M
@@ -292,9 +300,11 @@ services:
292
300
  memory: 1G
293
301
  restart: unless-stopped
294
302
 
295
- # Cache, sessions and the task queue. Only keys with an expiry are
296
- # evicted when memory runs out, so queued tasks are never dropped.
303
+ # Valkey (the valkey profile), for CACHE_URL or TASKS_URL redis://cache.
304
+ # Only keys with an expiry are evicted when memory runs out, so queued
305
+ # tasks are never dropped.
297
306
  cache:
307
+ profiles: [valkey]
298
308
  image: valkey/valkey:8-alpine
299
309
  user: valkey
300
310
  command: ["valkey-server", "--save", "", "--appendonly", "no", "--maxmemory", "200mb", "--maxmemory-policy", "volatile-lru"]
@@ -8,7 +8,8 @@ PROJECT_NAME={{project_name}}
8
8
  # dev,db development on this machine
9
9
  # prod,db production on a server
10
10
  # Leave out `db` when DATABASE_URL points to an external Postgres; add `s3`
11
- # in development for the local S3 service. `analytics` runs Umami.
11
+ # in development for the local S3 service. `analytics` runs Umami, `valkey`
12
+ # the Valkey service.
12
13
  COMPOSE_PROFILES=dev,db
13
14
 
14
15
  # The public URL of the site. In development the frontend's dev server also
@@ -17,6 +18,15 @@ COMPOSE_PROFILES=dev,db
17
18
  SITE_URL=http://localhost:3000
18
19
  BACKEND_URL=http://localhost:3000
19
20
 
21
+ # The ports of the development services on this machine: the site with the
22
+ # admin, the backend, Mailpit and the local S3 service. `init` and
23
+ # `dstack dev` move to free ones when these are in use, and change the
24
+ # URLs above with SITE_PORT.
25
+ SITE_PORT=3000
26
+ BACKEND_PORT=8000
27
+ MAIL_PORT=8025
28
+ S3_PORT=8333
29
+
20
30
  # Behind the proxy of a platform such as Coolify or Dokploy, which gets the
21
31
  # certificate, Caddy serves plain HTTP on port 80 to it instead:
22
32
  # CADDY_ADDRESS=:80 TRUSTED_PROXIES=private_ranges NUM_PROXIES=2
@@ -33,9 +43,18 @@ POSTGRES_USER=app
33
43
  POSTGRES_PASSWORD={{secret:postgres}}
34
44
  DATABASE_URL=postgres://app:{{secret:postgres}}@db:5432/app
35
45
 
36
- # Cache, task queue and mail. In production, EMAIL_URL is your SMTP server,
37
- # such as smtp+tls://user:password@smtp.example.com:587.
38
- CACHE_URL=redis://cache:6379/0
46
+ # Cache and task queue: db:// keeps them in tables in the database, so
47
+ # nothing else runs. For the Valkey service add `valkey` to COMPOSE_PROFILES
48
+ # and use redis://cache:6379/0 (the cache) or redis://cache:6379/1 (the
49
+ # tasks). CACHE_URL=locmem:// is a cache per process. TASKS_URL=immediate://
50
+ # runs tasks in the request, with TASK_WORKERS=0 to stop the worker; there
51
+ # are no daily backups then.
52
+ CACHE_URL=db://
53
+ TASKS_URL=db://
54
+ TASK_WORKERS=1
55
+
56
+ # Mail. In production, EMAIL_URL is your SMTP server, such as
57
+ # smtp+tls://user:password@smtp.example.com:587.
39
58
  EMAIL_URL=smtp://mailpit:1025
40
59
  DEFAULT_FROM_EMAIL={{project_name}} <noreply@localhost>
41
60
 
@@ -16,7 +16,7 @@
16
16
  "@astrojs/node": "^11.1.9",
17
17
  "@astrojs/rss": "^4.0.19",
18
18
  "@django-headless/client": "^1.1.1",
19
- "@django-stack/utils": "^0.6.0",
19
+ "@django-stack/utils": "^0.8.0",
20
20
  "astro": "^7.4.5"
21
21
  },
22
22
  "devDependencies": {
@@ -13,9 +13,9 @@
13
13
  },
14
14
  "dependencies": {
15
15
  "@django-headless/client": "^1.1.1",
16
- "@django-stack/next": "^0.6.0",
17
- "@django-stack/react": "^0.6.0",
18
- "@django-stack/utils": "^0.6.0",
16
+ "@django-stack/next": "^0.8.0",
17
+ "@django-stack/react": "^0.8.0",
18
+ "@django-stack/utils": "^0.8.0",
19
19
  "next": "^16.4.4",
20
20
  "react": "^19.3.1",
21
21
  "react-dom": "^19.3.1",
@@ -15,8 +15,8 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "@django-headless/client": "^1.1.1",
18
- "@django-stack/utils": "^0.6.0",
19
- "@django-stack/vue": "^0.6.0",
18
+ "@django-stack/utils": "^0.8.0",
19
+ "@django-stack/vue": "^0.8.0",
20
20
  "nuxt": "^4.6.3",
21
21
  "nuxt-security": "^2.7.0",
22
22
  "vue": "^3.5.44",
@@ -19,8 +19,8 @@
19
19
  },
20
20
  "dependencies": {
21
21
  "@django-headless/client": "^1.1.1",
22
- "@django-stack/svelte": "^0.6.0",
23
- "@django-stack/utils": "^0.6.0"
22
+ "@django-stack/svelte": "^0.8.0",
23
+ "@django-stack/utils": "^0.8.0"
24
24
  },
25
25
  "devDependencies": {
26
26
  "@sveltejs/adapter-node": "^6.0.1",