v1.0.14 (#48)
# Features - Basic Python support # Fixes - Fix default start command
This commit is contained in:
parent
adcd68c1ab
commit
c7efe899fa
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "coolify",
|
"name": "coolify",
|
||||||
"description": "An open-source, hassle-free, self-hostable Heroku & Netlify alternative.",
|
"description": "An open-source, hassle-free, self-hostable Heroku & Netlify alternative.",
|
||||||
"version": "1.0.13",
|
"version": "1.0.14",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev:docker:start": "docker-compose -f docker-compose-dev.yml up -d",
|
"dev:docker:start": "docker-compose -f docker-compose-dev.yml up -d",
|
||||||
|
@ -99,6 +99,15 @@
|
|||||||
},
|
},
|
||||||
build: false,
|
build: false,
|
||||||
start: false
|
start: false
|
||||||
|
},
|
||||||
|
python: {
|
||||||
|
port: {
|
||||||
|
active: true,
|
||||||
|
number: 4000
|
||||||
|
},
|
||||||
|
build: false,
|
||||||
|
start: false,
|
||||||
|
custom: true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
function selectBuildPack(event) {
|
function selectBuildPack(event) {
|
||||||
@ -214,6 +223,14 @@
|
|||||||
>
|
>
|
||||||
Docker
|
Docker
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
class={$application.build.pack === 'python'
|
||||||
|
? 'buildpack bg-green-500'
|
||||||
|
: 'buildpack hover:border-green-500'}
|
||||||
|
on:click={selectBuildPack}
|
||||||
|
>
|
||||||
|
Python
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-2xl font-bold border-gradient w-52">General settings</div>
|
<div class="text-2xl font-bold border-gradient w-52">General settings</div>
|
||||||
@ -282,15 +299,39 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="text-2xl font-bold w-40"
|
class="text-2xl font-bold w-40 border-gradient"
|
||||||
class:border-gradient={buildpacks[$application.build.pack].build}
|
|
||||||
class:text-warmGray-800={!buildpacks[$application.build.pack].build}
|
|
||||||
>
|
>
|
||||||
Commands
|
Commands
|
||||||
</div>
|
</div>
|
||||||
<div class=" max-w-2xl md:mx-auto mx-6 justify-center items-center pt-10 pb-32">
|
<div class=" max-w-2xl md:mx-auto mx-6 justify-center items-center pt-10 pb-32">
|
||||||
<div class="grid grid-flow-col gap-2 items-center">
|
<div class="grid grid-flow-col gap-2 items-center">
|
||||||
<div class="grid grid-flow-row">
|
<div class="grid grid-flow-row">
|
||||||
|
{#if $application.build.pack === 'python'}
|
||||||
|
<label for="ModulePackageName"
|
||||||
|
>Module/Package Name<TooltipInfo
|
||||||
|
label="The module/package name to start (eg: the entry filename [main], without the py extension. See gunicorn.org for more details)"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<input
|
||||||
|
class="mb-6"
|
||||||
|
id="ModulePackageName"
|
||||||
|
bind:value={$application.build.command.python.module}
|
||||||
|
placeholder="main"
|
||||||
|
/>
|
||||||
|
<label for="ApplicationInstance"
|
||||||
|
>Application Instance<TooltipInfo
|
||||||
|
label="The instance name (the main function name. See gunicorn.org for more details)"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<input
|
||||||
|
class="mb-6"
|
||||||
|
id="ApplicationInstance"
|
||||||
|
bind:value={$application.build.command.python.instance}
|
||||||
|
placeholder="app"
|
||||||
|
/>
|
||||||
|
{:else}
|
||||||
<label
|
<label
|
||||||
for="installCommand"
|
for="installCommand"
|
||||||
class:text-warmGray-800={!buildpacks[$application.build.pack].build}
|
class:text-warmGray-800={!buildpacks[$application.build.pack].build}
|
||||||
@ -331,7 +372,9 @@
|
|||||||
<label
|
<label
|
||||||
for="startCommand"
|
for="startCommand"
|
||||||
class:text-warmGray-800={!buildpacks[$application.build.pack].start}
|
class:text-warmGray-800={!buildpacks[$application.build.pack].start}
|
||||||
>Start Command <TooltipInfo label="Command to start the application. eg: yarn start" /></label
|
>Start Command <TooltipInfo
|
||||||
|
label="Command to start the application. eg: yarn start"
|
||||||
|
/></label
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
class="mb-6"
|
class="mb-6"
|
||||||
@ -344,6 +387,7 @@
|
|||||||
bind:value={$application.build.command.start}
|
bind:value={$application.build.command.start}
|
||||||
placeholder="eg: yarn start"
|
placeholder="eg: yarn start"
|
||||||
/>
|
/>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -66,7 +66,7 @@
|
|||||||
const packageJson = dir.find((f) => f.type === 'file' && f.name === 'package.json');
|
const packageJson = dir.find((f) => f.type === 'file' && f.name === 'package.json');
|
||||||
const Dockerfile = dir.find((f) => f.type === 'file' && f.name === 'Dockerfile');
|
const Dockerfile = dir.find((f) => f.type === 'file' && f.name === 'Dockerfile');
|
||||||
const CargoToml = dir.find((f) => f.type === 'file' && f.name === 'Cargo.toml');
|
const CargoToml = dir.find((f) => f.type === 'file' && f.name === 'Cargo.toml');
|
||||||
|
const requirementsTXT = dir.find((f) => f.type === 'file' && f.name === 'requirements.txt');
|
||||||
if (packageJson) {
|
if (packageJson) {
|
||||||
const { content } = await request(packageJson.git_url, $session);
|
const { content } = await request(packageJson.git_url, $session);
|
||||||
const packageJsonContent = JSON.parse(atob(content));
|
const packageJsonContent = JSON.parse(atob(content));
|
||||||
@ -102,6 +102,9 @@
|
|||||||
} else if (CargoToml) {
|
} else if (CargoToml) {
|
||||||
$application.build.pack = 'rust';
|
$application.build.pack = 'rust';
|
||||||
browser && toast.push(`Rust language detected. Default values set.`);
|
browser && toast.push(`Rust language detected. Default values set.`);
|
||||||
|
} else if (requirementsTXT) {
|
||||||
|
$application.build.pack = 'python'
|
||||||
|
browser && toast.push('Python language detected. Default values set.');
|
||||||
} else if (Dockerfile) {
|
} else if (Dockerfile) {
|
||||||
$application.build.pack = 'docker';
|
$application.build.pack = 'docker';
|
||||||
browser && toast.push('Custom Dockerfile found. Build pack set to docker.');
|
browser && toast.push('Custom Dockerfile found. Build pack set to docker.');
|
||||||
|
5
src/global.d.ts
vendored
5
src/global.d.ts
vendored
@ -44,6 +44,11 @@ export type Application = {
|
|||||||
build: string | null;
|
build: string | null;
|
||||||
installation: string;
|
installation: string;
|
||||||
start: string;
|
start: string;
|
||||||
|
python: {
|
||||||
|
module?: string;
|
||||||
|
instance?: string;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
container: {
|
container: {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -39,7 +39,6 @@ async function connectMongoDB() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
console.log(mongoose.connection.readyState)
|
|
||||||
if (mongoose.connection.readyState !== 1) await connectMongoDB();
|
if (mongoose.connection.readyState !== 1) await connectMongoDB();
|
||||||
try {
|
try {
|
||||||
await mongoose.connection.db.dropCollection('logs-servers');
|
await mongoose.connection.db.dropCollection('logs-servers');
|
||||||
|
@ -29,9 +29,12 @@ export function setDefaultConfiguration(configuration) {
|
|||||||
configuration.build.pack === 'vuejs' ||
|
configuration.build.pack === 'vuejs' ||
|
||||||
configuration.build.pack === 'nuxtjs' ||
|
configuration.build.pack === 'nuxtjs' ||
|
||||||
configuration.build.pack === 'rust' ||
|
configuration.build.pack === 'rust' ||
|
||||||
configuration.build.pack === 'nextjs'
|
configuration.build.pack === 'nextjs' ||
|
||||||
|
configuration.build.pack === 'nestjs'
|
||||||
) {
|
) {
|
||||||
configuration.publish.port = 3000;
|
configuration.publish.port = 3000;
|
||||||
|
} else if (configuration.build.pack === 'python') {
|
||||||
|
configuration.publish.port = 4000;
|
||||||
} else {
|
} else {
|
||||||
configuration.publish.port = 80;
|
configuration.publish.port = 80;
|
||||||
}
|
}
|
||||||
@ -48,6 +51,19 @@ export function setDefaultConfiguration(configuration) {
|
|||||||
if (!configuration.build.command.installation)
|
if (!configuration.build.command.installation)
|
||||||
configuration.build.command.installation = 'yarn install';
|
configuration.build.command.installation = 'yarn install';
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
configuration.build.pack === 'nodejs' ||
|
||||||
|
configuration.build.pack === 'vuejs' ||
|
||||||
|
configuration.build.pack === 'nuxtjs' ||
|
||||||
|
configuration.build.pack === 'nextjs' ||
|
||||||
|
configuration.build.pack === 'nestjs'
|
||||||
|
) {
|
||||||
|
if (!configuration.build.command.start) configuration.build.command.start = 'yarn start'
|
||||||
|
}
|
||||||
|
if (configuration.build.pack === 'python') {
|
||||||
|
if (!configuration.build.command.python.module) configuration.build.command.python.module = 'main'
|
||||||
|
if (!configuration.build.command.python.instance) configuration.build.command.python.instance = 'app'
|
||||||
|
}
|
||||||
|
|
||||||
configuration.build.container.baseSHA = crypto
|
configuration.build.container.baseSHA = crypto
|
||||||
.createHash('sha256')
|
.createHash('sha256')
|
||||||
@ -148,8 +164,7 @@ export async function updateServiceLabels(configuration) {
|
|||||||
await execShellAsync(
|
await execShellAsync(
|
||||||
`docker service update --label-add configuration='${JSON.stringify(
|
`docker service update --label-add configuration='${JSON.stringify(
|
||||||
Labels
|
Labels
|
||||||
)}' --label-add com.docker.stack.image='${configuration.build.container.name}:${
|
)}' --label-add com.docker.stack.image='${configuration.build.container.name}:${configuration.build.container.tag
|
||||||
configuration.build.container.tag
|
|
||||||
}' ${ID}`
|
}' ${ID}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import nextjs from './nextjs';
|
|||||||
import nestjs from './nestjs';
|
import nestjs from './nestjs';
|
||||||
import gatsby from './gatsby';
|
import gatsby from './gatsby';
|
||||||
import docker from './docker';
|
import docker from './docker';
|
||||||
|
import python from './python';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
vuejs,
|
vuejs,
|
||||||
@ -23,5 +24,6 @@ export {
|
|||||||
nextjs,
|
nextjs,
|
||||||
nestjs,
|
nestjs,
|
||||||
gatsby,
|
gatsby,
|
||||||
docker
|
docker,
|
||||||
|
python
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,7 @@ const publishPHPDocker = (configuration) => {
|
|||||||
'WORKDIR /usr/src/app',
|
'WORKDIR /usr/src/app',
|
||||||
`COPY ./${configuration.build.directory} /var/www/html`,
|
`COPY ./${configuration.build.directory} /var/www/html`,
|
||||||
'EXPOSE 80',
|
'EXPOSE 80',
|
||||||
' CMD ["apache2-foreground"]'
|
'CMD ["apache2-foreground"]'
|
||||||
].join('\n');
|
].join('\n');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
27
src/lib/api/applications/packs/python/index.ts
Normal file
27
src/lib/api/applications/packs/python/index.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { docker, streamEvents } from '$lib/api/docker';
|
||||||
|
import { promises as fs } from 'fs';
|
||||||
|
// `HEALTHCHECK --timeout=10s --start-period=10s --interval=5s CMD curl -I -s -f http://localhost:${configuration.publish.port}${configuration.publish.path} || exit 1`,
|
||||||
|
const publishPython = (configuration) => {
|
||||||
|
return [
|
||||||
|
'FROM python:3-alpine',
|
||||||
|
'WORKDIR /usr/src/app',
|
||||||
|
'RUN pip install gunicorn',
|
||||||
|
`COPY ./${configuration.build.directory}/requirements.txt ./`,
|
||||||
|
`RUN pip install --no-cache-dir -r ./${configuration.build.directory}/requirements.txt`,
|
||||||
|
`COPY ./${configuration.build.directory}/ .`,
|
||||||
|
`EXPOSE ${configuration.publish.port}`,
|
||||||
|
`CMD gunicorn -w=4 ${configuration.build.command.python.module}:${configuration.build.command.python.instance}`
|
||||||
|
].join('\n');
|
||||||
|
};
|
||||||
|
|
||||||
|
export default async function (configuration) {
|
||||||
|
await fs.writeFile(
|
||||||
|
`${configuration.general.workdir}/Dockerfile`,
|
||||||
|
publishPython(configuration)
|
||||||
|
);
|
||||||
|
const stream = await docker.engine.buildImage(
|
||||||
|
{ src: ['.'], context: configuration.general.workdir },
|
||||||
|
{ t: `${configuration.build.container.name}:${configuration.build.container.tag}` }
|
||||||
|
);
|
||||||
|
await streamEvents(stream, configuration);
|
||||||
|
}
|
@ -27,6 +27,11 @@ const ConfigurationSchema = new Schema({
|
|||||||
build: { type: String },
|
build: { type: String },
|
||||||
installation: { type: String },
|
installation: { type: String },
|
||||||
start: { type: String },
|
start: { type: String },
|
||||||
|
python: {
|
||||||
|
module: { type: String },
|
||||||
|
instance: { type: String },
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
container: {
|
container: {
|
||||||
name: { type: String, required: true },
|
name: { type: String, required: true },
|
||||||
|
@ -278,6 +278,57 @@
|
|||||||
fill-rule="evenodd"
|
fill-rule="evenodd"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
|
{:else if application.configuration.build.pack === 'python'}
|
||||||
|
<svg class="w-14 h-14 absolute top-0 left-0 -m-6" viewBox="0 0 128 128">
|
||||||
|
<linearGradient
|
||||||
|
id="a"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="70.252"
|
||||||
|
y1="1237.476"
|
||||||
|
x2="170.659"
|
||||||
|
y2="1151.089"
|
||||||
|
gradientTransform="matrix(.563 0 0 -.568 -29.215 707.817)"
|
||||||
|
><stop offset="0" stop-color="#5A9FD4" /><stop
|
||||||
|
offset="1"
|
||||||
|
stop-color="#306998"
|
||||||
|
/></linearGradient
|
||||||
|
><path
|
||||||
|
fill="url(#a)"
|
||||||
|
d="M63.391 1.988c-4.222.02-8.252.379-11.8 1.007-10.45 1.846-12.346 5.71-12.346 12.837v9.411h24.693v3.137h-33.961c-7.176 0-13.46 4.313-15.426 12.521-2.268 9.405-2.368 15.275 0 25.096 1.755 7.311 5.947 12.519 13.124 12.519h8.491v-11.282c0-8.151 7.051-15.34 15.426-15.34h24.665c6.866 0 12.346-5.654 12.346-12.548v-23.513c0-6.693-5.646-11.72-12.346-12.837-4.244-.706-8.645-1.027-12.866-1.008zm-13.354 7.569c2.55 0 4.634 2.117 4.634 4.721 0 2.593-2.083 4.69-4.634 4.69-2.56 0-4.633-2.097-4.633-4.69-.001-2.604 2.073-4.721 4.633-4.721z"
|
||||||
|
/><linearGradient
|
||||||
|
id="b"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="209.474"
|
||||||
|
y1="1098.811"
|
||||||
|
x2="173.62"
|
||||||
|
y2="1149.537"
|
||||||
|
gradientTransform="matrix(.563 0 0 -.568 -29.215 707.817)"
|
||||||
|
><stop offset="0" stop-color="#FFD43B" /><stop
|
||||||
|
offset="1"
|
||||||
|
stop-color="#FFE873"
|
||||||
|
/></linearGradient
|
||||||
|
><path
|
||||||
|
fill="url(#b)"
|
||||||
|
d="M91.682 28.38v10.966c0 8.5-7.208 15.655-15.426 15.655h-24.665c-6.756 0-12.346 5.783-12.346 12.549v23.515c0 6.691 5.818 10.628 12.346 12.547 7.816 2.297 15.312 2.713 24.665 0 6.216-1.801 12.346-5.423 12.346-12.547v-9.412h-24.664v-3.138h37.012c7.176 0 9.852-5.005 12.348-12.519 2.578-7.735 2.467-15.174 0-25.096-1.774-7.145-5.161-12.521-12.348-12.521h-9.268zm-13.873 59.547c2.561 0 4.634 2.097 4.634 4.692 0 2.602-2.074 4.719-4.634 4.719-2.55 0-4.633-2.117-4.633-4.719 0-2.595 2.083-4.692 4.633-4.692z"
|
||||||
|
/><radialGradient
|
||||||
|
id="c"
|
||||||
|
cx="1825.678"
|
||||||
|
cy="444.45"
|
||||||
|
r="26.743"
|
||||||
|
gradientTransform="matrix(0 -.24 -1.055 0 532.979 557.576)"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
><stop offset="0" stop-color="#B8B8B8" stop-opacity=".498" /><stop
|
||||||
|
offset="1"
|
||||||
|
stop-color="#7F7F7F"
|
||||||
|
stop-opacity="0"
|
||||||
|
/></radialGradient
|
||||||
|
><path
|
||||||
|
opacity=".444"
|
||||||
|
fill="url(#c)"
|
||||||
|
enable-background="new"
|
||||||
|
d="M97.309 119.597c0 3.543-14.816 6.416-33.091 6.416-18.276 0-33.092-2.873-33.092-6.416 0-3.544 14.815-6.417 33.092-6.417 18.275 0 33.091 2.872 33.091 6.417z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="flex flex-col justify-center items-center w-full">
|
<div class="flex flex-col justify-center items-center w-full">
|
||||||
<div class="text-base font-bold text-center w-full text-white pb-6">
|
<div class="text-base font-bold text-center w-full text-white pb-6">
|
||||||
|
@ -5,7 +5,7 @@ import type {
|
|||||||
DateTimeFormatOptions,
|
DateTimeFormatOptions,
|
||||||
GithubInstallations
|
GithubInstallations
|
||||||
} from 'src/global';
|
} from 'src/global';
|
||||||
import { writable, derived, readable, Writable } from 'svelte/store';
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
export const dashboard = writable<Dashboard>({
|
export const dashboard = writable<Dashboard>({
|
||||||
databases: {
|
databases: {
|
||||||
@ -55,7 +55,12 @@ export const application = writable<Application>({
|
|||||||
directory: null,
|
directory: null,
|
||||||
command: {
|
command: {
|
||||||
build: null,
|
build: null,
|
||||||
installation: null
|
installation: null,
|
||||||
|
start: null,
|
||||||
|
python: {
|
||||||
|
module: null,
|
||||||
|
instance: null
|
||||||
|
}
|
||||||
},
|
},
|
||||||
container: {
|
container: {
|
||||||
name: null,
|
name: null,
|
||||||
@ -99,7 +104,12 @@ export const initialApplication: Application = {
|
|||||||
directory: null,
|
directory: null,
|
||||||
command: {
|
command: {
|
||||||
build: null,
|
build: null,
|
||||||
installation: null
|
installation: null,
|
||||||
|
start: null,
|
||||||
|
python: {
|
||||||
|
module: null,
|
||||||
|
instance: null
|
||||||
|
}
|
||||||
},
|
},
|
||||||
container: {
|
container: {
|
||||||
name: null,
|
name: null,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user