Édition du docker-compose.yml depuis la page d'un conteneur

Vérification par docker compose config avant écriture, application avec
docker compose up -d et retour à la version précédente en cas d'échec.
Historique des versions par fichier. Le Caddyfile et le compose gardent
un retour à la ligne final.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
RutraandClaude Opus 5.5 committed 2026-10-12 18:31:33 +02:00
1 parent dcdac915f9
commit c106fcfc62
27 files changed
+1035 -58

No files matched your search

+18
View File
@@ -60,6 +60,24 @@ const routes = {
tokens: [{"old":"/api/containers/:id/logs","type":0,"val":"api","end":""},{"old":"/api/containers/:id/logs","type":0,"val":"containers","end":""},{"old":"/api/containers/:id/logs","type":1,"val":"id","end":""},{"old":"/api/containers/:id/logs","type":0,"val":"logs","end":""}],
types: placeholder as Registry['containers.logs']['types'],
},
'compose.show': {
methods: ["GET","HEAD"],
pattern: '/api/containers/:id/compose',
tokens: [{"old":"/api/containers/:id/compose","type":0,"val":"api","end":""},{"old":"/api/containers/:id/compose","type":0,"val":"containers","end":""},{"old":"/api/containers/:id/compose","type":1,"val":"id","end":""},{"old":"/api/containers/:id/compose","type":0,"val":"compose","end":""}],
types: placeholder as Registry['compose.show']['types'],
},
'compose.update': {
methods: ["PUT"],
pattern: '/api/containers/:id/compose',
tokens: [{"old":"/api/containers/:id/compose","type":0,"val":"api","end":""},{"old":"/api/containers/:id/compose","type":0,"val":"containers","end":""},{"old":"/api/containers/:id/compose","type":1,"val":"id","end":""},{"old":"/api/containers/:id/compose","type":0,"val":"compose","end":""}],
types: placeholder as Registry['compose.update']['types'],
},
'compose.version': {
methods: ["GET","HEAD"],
pattern: '/api/containers/:id/compose/versions/:versionId',
tokens: [{"old":"/api/containers/:id/compose/versions/:versionId","type":0,"val":"api","end":""},{"old":"/api/containers/:id/compose/versions/:versionId","type":0,"val":"containers","end":""},{"old":"/api/containers/:id/compose/versions/:versionId","type":1,"val":"id","end":""},{"old":"/api/containers/:id/compose/versions/:versionId","type":0,"val":"compose","end":""},{"old":"/api/containers/:id/compose/versions/:versionId","type":0,"val":"versions","end":""},{"old":"/api/containers/:id/compose/versions/:versionId","type":1,"val":"versionId","end":""}],
types: placeholder as Registry['compose.version']['types'],
},
'containers.action': {
methods: ["POST"],
pattern: '/api/containers/:id/:action',
+36
View File
@@ -115,6 +115,42 @@ export interface Registry {
errorResponse: ExtractErrorResponse<Awaited<ReturnType<import('#controllers/containers_controller').default['logs']>>>
}
}
'compose.show': {
methods: ["GET","HEAD"]
pattern: '/api/containers/:id/compose'
types: {
body: {}
paramsTuple: [ParamValue]
params: { id: ParamValue }
query: {}
response: ExtractResponse<Awaited<ReturnType<import('#controllers/compose_controller').default['show']>>>
errorResponse: ExtractErrorResponse<Awaited<ReturnType<import('#controllers/compose_controller').default['show']>>>
}
}
'compose.update': {
methods: ["PUT"]
pattern: '/api/containers/:id/compose'
types: {
body: ExtractBody<InferInput<(typeof import('#validators/compose').updateComposeValidator)>>
paramsTuple: [ParamValue]
params: { id: ParamValue }
query: ExtractQuery<InferInput<(typeof import('#validators/compose').updateComposeValidator)>>
response: ExtractResponse<Awaited<ReturnType<import('#controllers/compose_controller').default['update']>>>
errorResponse: ExtractErrorResponse<Awaited<ReturnType<import('#controllers/compose_controller').default['update']>>> | { status: 422; response: { errors: SimpleError[] } }
}
}
'compose.version': {
methods: ["GET","HEAD"]
pattern: '/api/containers/:id/compose/versions/:versionId'
types: {
body: {}
paramsTuple: [ParamValue, ParamValue]
params: { id: ParamValue; versionId: ParamValue }
query: {}
response: ExtractResponse<Awaited<ReturnType<import('#controllers/compose_controller').default['version']>>>
errorResponse: ExtractErrorResponse<Awaited<ReturnType<import('#controllers/compose_controller').default['version']>>>
}
}
'containers.action': {
methods: ["POST"]
pattern: '/api/containers/:id/:action'
+5
View File
@@ -20,6 +20,11 @@ export interface ApiDefinition {
logs: typeof routes['containers.logs']
action: typeof routes['containers.action']
}
compose: {
show: typeof routes['compose.show']
update: typeof routes['compose.update']
version: typeof routes['compose.version']
}
sites: {
index: typeof routes['sites.index']
check: typeof routes['sites.check']
+1
View File
@@ -8,6 +8,7 @@ export const controllers = {
Auth: () => import('#controllers/auth_controller'),
Backups: () => import('#controllers/backups_controller'),
Caddy: () => import('#controllers/caddy_controller'),
Compose: () => import('#controllers/compose_controller'),
Containers: () => import('#controllers/containers_controller'),
Jobs: () => import('#controllers/jobs_controller'),
Metrics: () => import('#controllers/metrics_controller'),
+8
View File
@@ -13,6 +13,9 @@ export type ScannedRoutes = {
'containers.index': { paramsTuple?: []; params?: {} }
'containers.show': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }
'containers.logs': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }
'compose.show': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }
'compose.update': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }
'compose.version': { paramsTuple: [ParamValue,ParamValue]; params: {'id': ParamValue,'versionId': ParamValue} }
'containers.action': { paramsTuple: [ParamValue,ParamValue]; params: {'id': ParamValue,'action': ParamValue} }
'sites.index': { paramsTuple?: []; params?: {} }
'sites.check': { paramsTuple?: []; params?: {} }
@@ -58,6 +61,8 @@ export type ScannedRoutes = {
'containers.index': { paramsTuple?: []; params?: {} }
'containers.show': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }
'containers.logs': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }
'compose.show': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }
'compose.version': { paramsTuple: [ParamValue,ParamValue]; params: {'id': ParamValue,'versionId': ParamValue} }
'sites.index': { paramsTuple?: []; params?: {} }
'sites.show': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }
'projects.index': { paramsTuple?: []; params?: {} }
@@ -81,6 +86,8 @@ export type ScannedRoutes = {
'containers.index': { paramsTuple?: []; params?: {} }
'containers.show': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }
'containers.logs': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }
'compose.show': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }
'compose.version': { paramsTuple: [ParamValue,ParamValue]; params: {'id': ParamValue,'versionId': ParamValue} }
'sites.index': { paramsTuple?: []; params?: {} }
'sites.show': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }
'projects.index': { paramsTuple?: []; params?: {} }
@@ -97,6 +104,7 @@ export type ScannedRoutes = {
'spa.index': { paramsTuple: [...ParamValue[]]; params: {'*': ParamValue[]} }
}
PUT: {
'compose.update': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }
'caddy.update': { paramsTuple?: []; params?: {} }
}
DELETE: {