feat: select base image for buildpacks
This commit is contained in:
parent
5998212b82
commit
d03fbd9224
10
README.md
10
README.md
@ -13,10 +13,16 @@ https://demo.coolify.io/
|
|||||||
Installation is automated with the following command:
|
Installation is automated with the following command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
/bin/bash -c "$(curl -fsSL https://get.coollabs.io/coolify/install.sh)"
|
wget -q https://get.coollabs.io/coolify/install.sh -O install.sh; sudo bash ./install.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
If you would like no questions during installation
|
If you would like no questions during installation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wget -q https://get.coollabs.io/coolify/install.sh -O install.sh; sudo bash ./install.sh -f
|
||||||
|
```
|
||||||
|
|
||||||
|
For more details goto the [docs](https://docs.coollabs.io/coolify/installation).
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "coolify",
|
"name": "coolify",
|
||||||
"description": "An open-source & self-hostable Heroku / Netlify alternative.",
|
"description": "An open-source & self-hostable Heroku / Netlify alternative.",
|
||||||
"version": "2.5.2",
|
"version": "2.5.3",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "docker-compose -f docker-compose-dev.yaml up -d && cross-env NODE_ENV=development & svelte-kit dev --host 0.0.0.0",
|
"dev": "docker-compose -f docker-compose-dev.yaml up -d && cross-env NODE_ENV=development & svelte-kit dev --host 0.0.0.0",
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Application" ADD COLUMN "baseBuildImage" TEXT;
|
||||||
|
ALTER TABLE "Application" ADD COLUMN "baseImage" TEXT;
|
@ -106,6 +106,7 @@ model Application {
|
|||||||
secrets Secret[]
|
secrets Secret[]
|
||||||
persistentStorage ApplicationPersistentStorage[]
|
persistentStorage ApplicationPersistentStorage[]
|
||||||
baseImage String?
|
baseImage String?
|
||||||
|
baseBuildImage String?
|
||||||
}
|
}
|
||||||
|
|
||||||
model ApplicationSettings {
|
model ApplicationSettings {
|
||||||
|
@ -5,6 +5,9 @@ import { scanningTemplates } from '$lib/components/templates';
|
|||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import { staticDeployments } from '$lib/components/common';
|
import { staticDeployments } from '$lib/components/common';
|
||||||
|
|
||||||
|
const staticApps = ['static', 'react', 'vuejs', 'svelte', 'gatsby', 'astro', 'eleventy'];
|
||||||
|
const nodeBased = ['react', 'vuejs', 'svelte', 'gatsby', 'php', 'astro', 'eleventy', 'node'];
|
||||||
|
|
||||||
export function makeLabelForStandaloneApplication({
|
export function makeLabelForStandaloneApplication({
|
||||||
applicationId,
|
applicationId,
|
||||||
fqdn,
|
fqdn,
|
||||||
@ -137,7 +140,13 @@ export const setDefaultConfiguration = async (data) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function copyBaseConfigurationFiles(buildPack, workdir, buildId, applicationId) {
|
export async function copyBaseConfigurationFiles(
|
||||||
|
buildPack,
|
||||||
|
workdir,
|
||||||
|
buildId,
|
||||||
|
applicationId,
|
||||||
|
baseImage
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
if (buildPack === 'php') {
|
if (buildPack === 'php') {
|
||||||
await fs.writeFile(`${workdir}/entrypoint.sh`, `chown -R 1000 /app`);
|
await fs.writeFile(`${workdir}/entrypoint.sh`, `chown -R 1000 /app`);
|
||||||
@ -146,7 +155,7 @@ export async function copyBaseConfigurationFiles(buildPack, workdir, buildId, ap
|
|||||||
buildId,
|
buildId,
|
||||||
applicationId
|
applicationId
|
||||||
});
|
});
|
||||||
} else if (staticDeployments.includes(buildPack)) {
|
} else if (staticDeployments.includes(buildPack) && baseImage.includes('nginx')) {
|
||||||
await fs.writeFile(
|
await fs.writeFile(
|
||||||
`${workdir}/nginx.conf`,
|
`${workdir}/nginx.conf`,
|
||||||
`user nginx;
|
`user nginx;
|
||||||
@ -199,11 +208,6 @@ export async function copyBaseConfigurationFiles(buildPack, workdir, buildId, ap
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
await saveBuildLog({
|
|
||||||
line: 'Copied default configuration file for Nginx.',
|
|
||||||
buildId,
|
|
||||||
applicationId
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
@ -218,3 +222,207 @@ export function checkPnpm(installCommand = null, buildCommand = null, startComma
|
|||||||
startCommand?.includes('pnpm')
|
startCommand?.includes('pnpm')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setDefaultBaseImage(buildPack) {
|
||||||
|
const nodeVersions = [
|
||||||
|
{
|
||||||
|
value: 'node:lts',
|
||||||
|
label: 'node:lts'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'node:18',
|
||||||
|
label: 'node:18'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'node:17',
|
||||||
|
label: 'node:17'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'node:16',
|
||||||
|
label: 'node:16'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'node:14',
|
||||||
|
label: 'node:14'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'node:12',
|
||||||
|
label: 'node:12'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const staticVersions = [
|
||||||
|
{
|
||||||
|
value: 'webdevops/nginx:alpine',
|
||||||
|
label: 'webdevops/nginx:alpine'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/apache:alpine',
|
||||||
|
label: 'webdevops/apache:alpine'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const rustVersions = [
|
||||||
|
{
|
||||||
|
value: 'rust:latest',
|
||||||
|
label: 'rust:latest'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'rust:1.60',
|
||||||
|
label: 'rust:1.60'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'rust:1.60-buster',
|
||||||
|
label: 'rust:1.60-buster'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'rust:1.60-bullseye',
|
||||||
|
label: 'rust:1.60-bullseye'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'rust:1.60-slim-buster',
|
||||||
|
label: 'rust:1.60-slim-buster'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'rust:1.60-slim-bullseye',
|
||||||
|
label: 'rust:1.60-slim-bullseye'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'rust:1.60-alpine3.14',
|
||||||
|
label: 'rust:1.60-alpine3.14'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'rust:1.60-alpine3.15',
|
||||||
|
label: 'rust:1.60-alpine3.15'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const phpVersions = [
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-apache:8.0',
|
||||||
|
label: 'webdevops/php-apache:8.0'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-nginx:8.0',
|
||||||
|
label: 'webdevops/php-nginx:8.0'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-apache:7.4',
|
||||||
|
label: 'webdevops/php-apache:7.4'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-nginx:7.4',
|
||||||
|
label: 'webdevops/php-nginx:7.4'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-apache:7.3',
|
||||||
|
label: 'webdevops/php-apache:7.3'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-nginx:7.3',
|
||||||
|
label: 'webdevops/php-nginx:7.3'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-apache:7.2',
|
||||||
|
label: 'webdevops/php-apache:7.2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-nginx:7.2',
|
||||||
|
label: 'webdevops/php-nginx:7.2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-apache:7.1',
|
||||||
|
label: 'webdevops/php-apache:7.1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-nginx:7.1',
|
||||||
|
label: 'webdevops/php-nginx:7.1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-apache:7.0',
|
||||||
|
label: 'webdevops/php-apache:7.0'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-nginx:7.0',
|
||||||
|
label: 'webdevops/php-nginx:7.0'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-apache:5.6',
|
||||||
|
label: 'webdevops/php-apache:5.6'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-nginx:5.6',
|
||||||
|
label: 'webdevops/php-nginx:5.6'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-apache:8.0-alpine',
|
||||||
|
label: 'webdevops/php-apache:8.0-alpine'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-nginx:8.0-alpine',
|
||||||
|
label: 'webdevops/php-nginx:8.0-alpine'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-apache:7.4-alpine',
|
||||||
|
label: 'webdevops/php-apache:7.4-alpine'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-nginx:7.4-alpine',
|
||||||
|
label: 'webdevops/php-nginx:7.4-alpine'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-apache:7.3-alpine',
|
||||||
|
label: 'webdevops/php-apache:7.3-alpine'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-nginx:7.3-alpine',
|
||||||
|
label: 'webdevops/php-nginx:7.3-alpine'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-apache:7.2-alpine',
|
||||||
|
label: 'webdevops/php-apache:7.2-alpine'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-nginx:7.2-alpine',
|
||||||
|
label: 'webdevops/php-nginx:7.2-alpine'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-apache:7.1-alpine',
|
||||||
|
label: 'webdevops/php-apache:7.1-alpine'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'webdevops/php-nginx:7.1-alpine',
|
||||||
|
label: 'webdevops/php-nginx:7.1-alpine'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
let payload = {
|
||||||
|
baseImage: null,
|
||||||
|
baseBuildImage: null,
|
||||||
|
baseImages: [],
|
||||||
|
baseBuildImages: []
|
||||||
|
};
|
||||||
|
if (nodeBased.includes(buildPack)) {
|
||||||
|
payload.baseImage = 'node:lts';
|
||||||
|
payload.baseImages = nodeVersions;
|
||||||
|
}
|
||||||
|
if (staticApps.includes(buildPack)) {
|
||||||
|
payload.baseImage = 'webdevops/nginx:alpine';
|
||||||
|
payload.baseImages = staticVersions;
|
||||||
|
payload.baseBuildImage = 'node:lts';
|
||||||
|
payload.baseBuildImages = nodeVersions;
|
||||||
|
}
|
||||||
|
if (buildPack === 'python') {
|
||||||
|
payload.baseImage = 'python:3-alpine';
|
||||||
|
}
|
||||||
|
if (buildPack === 'rust') {
|
||||||
|
payload.baseImage = 'rust:latest';
|
||||||
|
payload.baseBuildImage = 'rust:latest';
|
||||||
|
payload.baseImages = rustVersions;
|
||||||
|
payload.baseBuildImages = rustVersions;
|
||||||
|
}
|
||||||
|
if (buildPack === 'deno') {
|
||||||
|
payload.baseImage = 'denoland/deno:latest';
|
||||||
|
}
|
||||||
|
if (buildPack === 'php') {
|
||||||
|
payload.baseImage = 'webdevops/php-apache:8.0-alpine';
|
||||||
|
payload.baseImages = phpVersions;
|
||||||
|
}
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
@ -45,8 +45,8 @@ const createDockerfile = async (data, image): Promise<void> => {
|
|||||||
|
|
||||||
export default async function (data) {
|
export default async function (data) {
|
||||||
try {
|
try {
|
||||||
const image = 'denoland/deno:latest';
|
const { baseImage, baseBuildImage } = data;
|
||||||
await createDockerfile(data, image);
|
await createDockerfile(data, baseImage);
|
||||||
await buildImage(data);
|
await buildImage(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
|
@ -2,25 +2,25 @@ import { buildCacheImageWithNode, buildImage } from '$lib/docker';
|
|||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
|
|
||||||
const createDockerfile = async (data, imageforBuild): Promise<void> => {
|
const createDockerfile = async (data, imageforBuild): Promise<void> => {
|
||||||
const { applicationId, tag, workdir, publishDirectory } = data;
|
const { applicationId, tag, workdir, publishDirectory, baseImage } = data;
|
||||||
const Dockerfile: Array<string> = [];
|
const Dockerfile: Array<string> = [];
|
||||||
|
|
||||||
Dockerfile.push(`FROM ${imageforBuild}`);
|
Dockerfile.push(`FROM ${imageforBuild}`);
|
||||||
Dockerfile.push('WORKDIR /app');
|
Dockerfile.push('WORKDIR /app');
|
||||||
Dockerfile.push(`LABEL coolify.image=true`);
|
Dockerfile.push(`LABEL coolify.image=true`);
|
||||||
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /app/${publishDirectory} ./`);
|
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /app/${publishDirectory} ./`);
|
||||||
|
if (baseImage.includes('nginx')) {
|
||||||
Dockerfile.push(`COPY /nginx.conf /etc/nginx/nginx.conf`);
|
Dockerfile.push(`COPY /nginx.conf /etc/nginx/nginx.conf`);
|
||||||
|
}
|
||||||
Dockerfile.push(`EXPOSE 80`);
|
Dockerfile.push(`EXPOSE 80`);
|
||||||
await fs.writeFile(`${workdir}/Dockerfile`, Dockerfile.join('\n'));
|
await fs.writeFile(`${workdir}/Dockerfile`, Dockerfile.join('\n'));
|
||||||
};
|
};
|
||||||
|
|
||||||
export default async function (data) {
|
export default async function (data) {
|
||||||
try {
|
try {
|
||||||
const image = 'webdevops/nginx:alpine';
|
const { baseImage, baseBuildImage } = data;
|
||||||
const imageForBuild = 'node:lts';
|
await buildCacheImageWithNode(data, baseImage);
|
||||||
|
await createDockerfile(data, baseBuildImage);
|
||||||
await buildCacheImageWithNode(data, imageForBuild);
|
|
||||||
await createDockerfile(data, image);
|
|
||||||
await buildImage(data);
|
await buildImage(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
|
@ -22,11 +22,9 @@ const createDockerfile = async (data, image): Promise<void> => {
|
|||||||
|
|
||||||
export default async function (data) {
|
export default async function (data) {
|
||||||
try {
|
try {
|
||||||
const image = 'node:lts';
|
const { baseImage, baseBuildImage } = data;
|
||||||
const imageForBuild = 'node:lts';
|
await buildCacheImageWithNode(data, baseBuildImage);
|
||||||
|
await createDockerfile(data, baseImage);
|
||||||
await buildCacheImageWithNode(data, imageForBuild);
|
|
||||||
await createDockerfile(data, image);
|
|
||||||
await buildImage(data);
|
await buildImage(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
|
@ -50,8 +50,8 @@ const createDockerfile = async (data, image): Promise<void> => {
|
|||||||
|
|
||||||
export default async function (data) {
|
export default async function (data) {
|
||||||
try {
|
try {
|
||||||
const image = 'node:lts';
|
const { baseImage, baseBuildImage } = data;
|
||||||
await createDockerfile(data, image);
|
await createDockerfile(data, baseImage);
|
||||||
await buildImage(data);
|
await buildImage(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
|
@ -50,8 +50,8 @@ const createDockerfile = async (data, image): Promise<void> => {
|
|||||||
|
|
||||||
export default async function (data) {
|
export default async function (data) {
|
||||||
try {
|
try {
|
||||||
const image = 'node:lts';
|
const { baseImage, baseBuildImage } = data;
|
||||||
await createDockerfile(data, image);
|
await createDockerfile(data, baseImage);
|
||||||
await buildImage(data);
|
await buildImage(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
|
@ -49,8 +49,8 @@ const createDockerfile = async (data, image): Promise<void> => {
|
|||||||
|
|
||||||
export default async function (data) {
|
export default async function (data) {
|
||||||
try {
|
try {
|
||||||
const image = 'node:lts';
|
const { baseImage, baseBuildImage } = data;
|
||||||
await createDockerfile(data, image);
|
await createDockerfile(data, baseImage);
|
||||||
await buildImage(data);
|
await buildImage(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
|
@ -27,7 +27,7 @@ const createDockerfile = async (data, image, htaccessFound): Promise<void> => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function (data) {
|
export default async function (data) {
|
||||||
const { workdir, baseDirectory } = data;
|
const { workdir, baseDirectory, baseImage } = data;
|
||||||
try {
|
try {
|
||||||
let htaccessFound = false;
|
let htaccessFound = false;
|
||||||
try {
|
try {
|
||||||
@ -36,10 +36,7 @@ export default async function (data) {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
const image = htaccessFound
|
await createDockerfile(data, baseImage, htaccessFound);
|
||||||
? 'webdevops/php-apache:8.0-alpine'
|
|
||||||
: 'webdevops/php-nginx:8.0-alpine';
|
|
||||||
await createDockerfile(data, image, htaccessFound);
|
|
||||||
await buildImage(data);
|
await buildImage(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
|
@ -62,8 +62,8 @@ const createDockerfile = async (data, image): Promise<void> => {
|
|||||||
|
|
||||||
export default async function (data) {
|
export default async function (data) {
|
||||||
try {
|
try {
|
||||||
const image = 'python:3-alpine';
|
const { baseImage, baseBuildImage } = data;
|
||||||
await createDockerfile(data, image);
|
await createDockerfile(data, baseImage);
|
||||||
await buildImage(data);
|
await buildImage(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
|
@ -2,24 +2,25 @@ import { buildCacheImageWithNode, buildImage } from '$lib/docker';
|
|||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
|
|
||||||
const createDockerfile = async (data, image): Promise<void> => {
|
const createDockerfile = async (data, image): Promise<void> => {
|
||||||
const { applicationId, tag, workdir, publishDirectory } = data;
|
const { applicationId, tag, workdir, publishDirectory, baseImage } = data;
|
||||||
const Dockerfile: Array<string> = [];
|
const Dockerfile: Array<string> = [];
|
||||||
|
|
||||||
Dockerfile.push(`FROM ${image}`);
|
Dockerfile.push(`FROM ${image}`);
|
||||||
Dockerfile.push(`LABEL coolify.image=true`);
|
Dockerfile.push(`LABEL coolify.image=true`);
|
||||||
Dockerfile.push('WORKDIR /app');
|
Dockerfile.push('WORKDIR /app');
|
||||||
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /app/${publishDirectory} ./`);
|
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /app/${publishDirectory} ./`);
|
||||||
|
if (baseImage.includes('nginx')) {
|
||||||
Dockerfile.push(`COPY /nginx.conf /etc/nginx/nginx.conf`);
|
Dockerfile.push(`COPY /nginx.conf /etc/nginx/nginx.conf`);
|
||||||
|
}
|
||||||
Dockerfile.push(`EXPOSE 80`);
|
Dockerfile.push(`EXPOSE 80`);
|
||||||
await fs.writeFile(`${workdir}/Dockerfile`, Dockerfile.join('\n'));
|
await fs.writeFile(`${workdir}/Dockerfile`, Dockerfile.join('\n'));
|
||||||
};
|
};
|
||||||
|
|
||||||
export default async function (data) {
|
export default async function (data) {
|
||||||
try {
|
try {
|
||||||
const image = 'webdevops/nginx:alpine';
|
const { baseImage, baseBuildImage } = data;
|
||||||
const imageForBuild = 'node:lts';
|
await buildCacheImageWithNode(data, baseBuildImage);
|
||||||
await buildCacheImageWithNode(data, imageForBuild);
|
await createDockerfile(data, baseImage);
|
||||||
await createDockerfile(data, image);
|
|
||||||
await buildImage(data);
|
await buildImage(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
|
@ -27,14 +27,12 @@ const createDockerfile = async (data, image, name): Promise<void> => {
|
|||||||
|
|
||||||
export default async function (data) {
|
export default async function (data) {
|
||||||
try {
|
try {
|
||||||
const { workdir } = data;
|
const { workdir, baseImage, baseBuildImage } = data;
|
||||||
const image = 'rust:latest';
|
|
||||||
const imageForBuild = 'rust:latest';
|
|
||||||
const { stdout: cargoToml } = await asyncExecShell(`cat ${workdir}/Cargo.toml`);
|
const { stdout: cargoToml } = await asyncExecShell(`cat ${workdir}/Cargo.toml`);
|
||||||
const parsedToml: any = TOML.parse(cargoToml);
|
const parsedToml: any = TOML.parse(cargoToml);
|
||||||
const name = parsedToml.package.name;
|
const name = parsedToml.package.name;
|
||||||
await buildCacheImageWithCargo(data, imageForBuild);
|
await buildCacheImageWithCargo(data, baseBuildImage);
|
||||||
await createDockerfile(data, image, name);
|
await createDockerfile(data, baseImage, name);
|
||||||
await buildImage(data);
|
await buildImage(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
|
@ -10,7 +10,8 @@ const createDockerfile = async (data, image): Promise<void> => {
|
|||||||
baseDirectory,
|
baseDirectory,
|
||||||
publishDirectory,
|
publishDirectory,
|
||||||
secrets,
|
secrets,
|
||||||
pullmergeRequestId
|
pullmergeRequestId,
|
||||||
|
baseImage
|
||||||
} = data;
|
} = data;
|
||||||
const Dockerfile: Array<string> = [];
|
const Dockerfile: Array<string> = [];
|
||||||
|
|
||||||
@ -37,17 +38,18 @@ const createDockerfile = async (data, image): Promise<void> => {
|
|||||||
} else {
|
} else {
|
||||||
Dockerfile.push(`COPY .${baseDirectory || ''} ./`);
|
Dockerfile.push(`COPY .${baseDirectory || ''} ./`);
|
||||||
}
|
}
|
||||||
|
if (baseImage.includes('nginx')) {
|
||||||
Dockerfile.push(`COPY /nginx.conf /etc/nginx/nginx.conf`);
|
Dockerfile.push(`COPY /nginx.conf /etc/nginx/nginx.conf`);
|
||||||
|
}
|
||||||
Dockerfile.push(`EXPOSE 80`);
|
Dockerfile.push(`EXPOSE 80`);
|
||||||
await fs.writeFile(`${workdir}/Dockerfile`, Dockerfile.join('\n'));
|
await fs.writeFile(`${workdir}/Dockerfile`, Dockerfile.join('\n'));
|
||||||
};
|
};
|
||||||
|
|
||||||
export default async function (data) {
|
export default async function (data) {
|
||||||
try {
|
try {
|
||||||
const image = 'webdevops/nginx:alpine';
|
const { baseImage, baseBuildImage } = data;
|
||||||
const imageForBuild = 'node:lts';
|
if (data.buildCommand) await buildCacheImageWithNode(data, baseBuildImage);
|
||||||
if (data.buildCommand) await buildCacheImageWithNode(data, imageForBuild);
|
await createDockerfile(data, baseImage);
|
||||||
await createDockerfile(data, image);
|
|
||||||
await buildImage(data);
|
await buildImage(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
|
@ -2,25 +2,25 @@ import { buildCacheImageWithNode, buildImage } from '$lib/docker';
|
|||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
|
|
||||||
const createDockerfile = async (data, image): Promise<void> => {
|
const createDockerfile = async (data, image): Promise<void> => {
|
||||||
const { applicationId, tag, workdir, publishDirectory } = data;
|
const { applicationId, tag, workdir, publishDirectory, baseImage } = data;
|
||||||
const Dockerfile: Array<string> = [];
|
const Dockerfile: Array<string> = [];
|
||||||
|
|
||||||
Dockerfile.push(`FROM ${image}`);
|
Dockerfile.push(`FROM ${image}`);
|
||||||
Dockerfile.push('WORKDIR /app');
|
Dockerfile.push('WORKDIR /app');
|
||||||
Dockerfile.push(`LABEL coolify.image=true`);
|
Dockerfile.push(`LABEL coolify.image=true`);
|
||||||
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /app/${publishDirectory} ./`);
|
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /app/${publishDirectory} ./`);
|
||||||
|
if (baseImage.includes('nginx')) {
|
||||||
Dockerfile.push(`COPY /nginx.conf /etc/nginx/nginx.conf`);
|
Dockerfile.push(`COPY /nginx.conf /etc/nginx/nginx.conf`);
|
||||||
|
}
|
||||||
Dockerfile.push(`EXPOSE 80`);
|
Dockerfile.push(`EXPOSE 80`);
|
||||||
await fs.writeFile(`${workdir}/Dockerfile`, Dockerfile.join('\n'));
|
await fs.writeFile(`${workdir}/Dockerfile`, Dockerfile.join('\n'));
|
||||||
};
|
};
|
||||||
|
|
||||||
export default async function (data) {
|
export default async function (data) {
|
||||||
try {
|
try {
|
||||||
const image = 'webdevops/nginx:alpine';
|
const { baseImage, baseBuildImage } = data;
|
||||||
const imageForBuild = 'node:lts';
|
await buildCacheImageWithNode(data, baseBuildImage);
|
||||||
|
await createDockerfile(data, baseImage);
|
||||||
await buildCacheImageWithNode(data, imageForBuild);
|
|
||||||
await createDockerfile(data, image);
|
|
||||||
await buildImage(data);
|
await buildImage(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
|
@ -2,24 +2,25 @@ import { buildCacheImageWithNode, buildImage } from '$lib/docker';
|
|||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
|
|
||||||
const createDockerfile = async (data, image): Promise<void> => {
|
const createDockerfile = async (data, image): Promise<void> => {
|
||||||
const { applicationId, tag, workdir, publishDirectory } = data;
|
const { applicationId, tag, workdir, publishDirectory, baseImage } = data;
|
||||||
const Dockerfile: Array<string> = [];
|
const Dockerfile: Array<string> = [];
|
||||||
|
|
||||||
Dockerfile.push(`FROM ${image}`);
|
Dockerfile.push(`FROM ${image}`);
|
||||||
Dockerfile.push('WORKDIR /app');
|
Dockerfile.push('WORKDIR /app');
|
||||||
Dockerfile.push(`LABEL coolify.image=true`);
|
Dockerfile.push(`LABEL coolify.image=true`);
|
||||||
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /app/${publishDirectory} ./`);
|
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /app/${publishDirectory} ./`);
|
||||||
|
if (baseImage.includes('nginx')) {
|
||||||
Dockerfile.push(`COPY /nginx.conf /etc/nginx/nginx.conf`);
|
Dockerfile.push(`COPY /nginx.conf /etc/nginx/nginx.conf`);
|
||||||
|
}
|
||||||
Dockerfile.push(`EXPOSE 80`);
|
Dockerfile.push(`EXPOSE 80`);
|
||||||
await fs.writeFile(`${workdir}/Dockerfile`, Dockerfile.join('\n'));
|
await fs.writeFile(`${workdir}/Dockerfile`, Dockerfile.join('\n'));
|
||||||
};
|
};
|
||||||
|
|
||||||
export default async function (data) {
|
export default async function (data) {
|
||||||
try {
|
try {
|
||||||
const image = 'webdevops/nginx:alpine';
|
const { baseImage, baseBuildImage } = data;
|
||||||
const imageForBuild = 'node:lts';
|
await buildCacheImageWithNode(data, baseBuildImage);
|
||||||
await buildCacheImageWithNode(data, imageForBuild);
|
await createDockerfile(data, baseImage);
|
||||||
await createDockerfile(data, image);
|
|
||||||
await buildImage(data);
|
await buildImage(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
|
@ -12,17 +12,7 @@ import type {
|
|||||||
Application,
|
Application,
|
||||||
ApplicationPersistentStorage
|
ApplicationPersistentStorage
|
||||||
} from '@prisma/client';
|
} from '@prisma/client';
|
||||||
const nodeBased = [
|
import { setDefaultBaseImage } from '$lib/buildPacks/common';
|
||||||
'react',
|
|
||||||
'vuejs',
|
|
||||||
'static',
|
|
||||||
'svelte',
|
|
||||||
'gatsby',
|
|
||||||
'php',
|
|
||||||
'astro',
|
|
||||||
'eleventy',
|
|
||||||
'node'
|
|
||||||
];
|
|
||||||
|
|
||||||
export async function listApplications(teamId: string): Promise<Application[]> {
|
export async function listApplications(teamId: string): Promise<Application[]> {
|
||||||
if (teamId === '0') {
|
if (teamId === '0') {
|
||||||
@ -206,26 +196,18 @@ export async function getApplication({ id, teamId }: { id: string; teamId: strin
|
|||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const { baseImage, baseBuildImage, baseBuildImages, baseImages } = setDefaultBaseImage(
|
||||||
|
body.buildPack
|
||||||
|
);
|
||||||
|
|
||||||
// Set default build images
|
// Set default build images
|
||||||
if (!body.baseImage) {
|
if (!body.baseImage) {
|
||||||
if (nodeBased.includes(body.buildPack)) {
|
body.baseImage = baseImage;
|
||||||
body.baseImage = 'node:lts';
|
|
||||||
}
|
}
|
||||||
if (body.buildPack === 'python') {
|
if (!body.baseBuildImage) {
|
||||||
body.baseImage = 'python:3-alpine';
|
body.baseBuildImage = baseBuildImage;
|
||||||
}
|
}
|
||||||
if (body.buildPack === 'rust') {
|
return { ...body, baseBuildImages, baseImages };
|
||||||
body.baseImage = 'rust:latest';
|
|
||||||
}
|
|
||||||
if (body.buildPack === 'deno') {
|
|
||||||
body.baseImage = 'denoland/deno:latest';
|
|
||||||
}
|
|
||||||
if (body.buildPack === 'php') {
|
|
||||||
body.baseImage = 'webdevops/php-apache:8.0-alpine';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return { ...body };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function configureGitRepository({
|
export async function configureGitRepository({
|
||||||
@ -296,7 +278,8 @@ export async function configureApplication({
|
|||||||
dockerFileLocation,
|
dockerFileLocation,
|
||||||
denoMainFile,
|
denoMainFile,
|
||||||
denoOptions,
|
denoOptions,
|
||||||
baseImage
|
baseImage,
|
||||||
|
baseBuildImage
|
||||||
}: {
|
}: {
|
||||||
id: string;
|
id: string;
|
||||||
buildPack: string;
|
buildPack: string;
|
||||||
@ -315,6 +298,7 @@ export async function configureApplication({
|
|||||||
denoMainFile: string;
|
denoMainFile: string;
|
||||||
denoOptions: string;
|
denoOptions: string;
|
||||||
baseImage: string;
|
baseImage: string;
|
||||||
|
baseBuildImage: string;
|
||||||
}): Promise<Application> {
|
}): Promise<Application> {
|
||||||
return await prisma.application.update({
|
return await prisma.application.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
@ -334,7 +318,8 @@ export async function configureApplication({
|
|||||||
dockerFileLocation,
|
dockerFileLocation,
|
||||||
denoMainFile,
|
denoMainFile,
|
||||||
denoOptions,
|
denoOptions,
|
||||||
baseImage
|
baseImage,
|
||||||
|
baseBuildImage
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -185,6 +185,7 @@
|
|||||||
"git_repository": "Git Repository",
|
"git_repository": "Git Repository",
|
||||||
"build_pack": "Build Pack",
|
"build_pack": "Build Pack",
|
||||||
"base_image": "Base Image",
|
"base_image": "Base Image",
|
||||||
|
"base_build_image": "Base Build Image",
|
||||||
"destination": "Destination",
|
"destination": "Destination",
|
||||||
"application": "Application",
|
"application": "Application",
|
||||||
"url_fqdn": "URL (FQDN)",
|
"url_fqdn": "URL (FQDN)",
|
||||||
|
@ -47,7 +47,9 @@ export default async function (job: Job<BuilderJob, void, string>): Promise<void
|
|||||||
pythonWSGI,
|
pythonWSGI,
|
||||||
pythonModule,
|
pythonModule,
|
||||||
pythonVariable,
|
pythonVariable,
|
||||||
denoOptions
|
denoOptions,
|
||||||
|
baseImage,
|
||||||
|
baseBuildImage
|
||||||
} = job.data;
|
} = job.data;
|
||||||
let {
|
let {
|
||||||
branch,
|
branch,
|
||||||
@ -186,7 +188,7 @@ export default async function (job: Job<BuilderJob, void, string>): Promise<void
|
|||||||
//
|
//
|
||||||
}
|
}
|
||||||
if (!imageFound || deployNeeded) {
|
if (!imageFound || deployNeeded) {
|
||||||
await copyBaseConfigurationFiles(buildPack, workdir, buildId, applicationId);
|
await copyBaseConfigurationFiles(buildPack, workdir, buildId, applicationId, baseImage);
|
||||||
if (buildpacks[buildPack])
|
if (buildpacks[buildPack])
|
||||||
await buildpacks[buildPack]({
|
await buildpacks[buildPack]({
|
||||||
buildId,
|
buildId,
|
||||||
@ -217,7 +219,9 @@ export default async function (job: Job<BuilderJob, void, string>): Promise<void
|
|||||||
pythonVariable,
|
pythonVariable,
|
||||||
dockerFileLocation,
|
dockerFileLocation,
|
||||||
denoMainFile,
|
denoMainFile,
|
||||||
denoOptions
|
denoOptions,
|
||||||
|
baseImage,
|
||||||
|
baseBuildImage
|
||||||
});
|
});
|
||||||
else {
|
else {
|
||||||
await saveBuildLog({ line: `Build pack ${buildPack} not found`, buildId, applicationId });
|
await saveBuildLog({ line: `Build pack ${buildPack} not found`, buildId, applicationId });
|
||||||
|
@ -34,6 +34,8 @@ export type BuilderJob = {
|
|||||||
persistentStorage: { path: string }[];
|
persistentStorage: { path: string }[];
|
||||||
pullmergeRequestId?: unknown;
|
pullmergeRequestId?: unknown;
|
||||||
sourceBranch?: string;
|
sourceBranch?: string;
|
||||||
|
baseImage: string;
|
||||||
|
baseBuildImage: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Add the other build types
|
// TODO: Add the other build types
|
||||||
|
@ -63,7 +63,8 @@ export const post: RequestHandler = async (event) => {
|
|||||||
dockerFileLocation,
|
dockerFileLocation,
|
||||||
denoMainFile,
|
denoMainFile,
|
||||||
denoOptions,
|
denoOptions,
|
||||||
baseImage
|
baseImage,
|
||||||
|
baseBuildImage
|
||||||
} = await event.request.json();
|
} = await event.request.json();
|
||||||
if (port) port = Number(port);
|
if (port) port = Number(port);
|
||||||
if (denoOptions) denoOptions = denoOptions.trim();
|
if (denoOptions) denoOptions = denoOptions.trim();
|
||||||
@ -98,6 +99,7 @@ export const post: RequestHandler = async (event) => {
|
|||||||
denoMainFile,
|
denoMainFile,
|
||||||
denoOptions,
|
denoOptions,
|
||||||
baseImage,
|
baseImage,
|
||||||
|
baseBuildImage,
|
||||||
...defaultConfiguration
|
...defaultConfiguration
|
||||||
});
|
});
|
||||||
return { status: 201 };
|
return { status: 201 };
|
||||||
|
@ -33,6 +33,8 @@
|
|||||||
gitlabApp: Prisma.GitlabApp;
|
gitlabApp: Prisma.GitlabApp;
|
||||||
gitSource: Prisma.GitSource;
|
gitSource: Prisma.GitSource;
|
||||||
destinationDocker: Prisma.DestinationDocker;
|
destinationDocker: Prisma.DestinationDocker;
|
||||||
|
baseImages: Array<{ value: string; label: string }>;
|
||||||
|
baseBuildImages: Array<{ value: string; label: string }>;
|
||||||
};
|
};
|
||||||
export let isRunning;
|
export let isRunning;
|
||||||
import { page, session } from '$app/stores';
|
import { page, session } from '$app/stores';
|
||||||
@ -71,11 +73,14 @@
|
|||||||
label: 'Gunicorn'
|
label: 'Gunicorn'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
function containerClass() {
|
||||||
|
if (!$session.isAdmin || isRunning) {
|
||||||
|
return 'text-white border border-dashed border-coolgray-300 bg-transparent font-thin px-0';
|
||||||
|
}
|
||||||
|
}
|
||||||
if (browser && window.location.hostname === 'demo.coolify.io' && !application.fqdn) {
|
if (browser && window.location.hostname === 'demo.coolify.io' && !application.fqdn) {
|
||||||
application.fqdn = `http://${cuid()}.demo.coolify.io`;
|
application.fqdn = `http://${cuid()}.demo.coolify.io`;
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
domainEl.focus();
|
domainEl.focus();
|
||||||
});
|
});
|
||||||
@ -138,6 +143,14 @@
|
|||||||
async function selectWSGI(event) {
|
async function selectWSGI(event) {
|
||||||
application.pythonWSGI = event.detail.value;
|
application.pythonWSGI = event.detail.value;
|
||||||
}
|
}
|
||||||
|
async function selectBaseImage(event) {
|
||||||
|
application.baseImage = event.detail.value;
|
||||||
|
await handleSubmit();
|
||||||
|
}
|
||||||
|
async function selectBaseBuildImage(event) {
|
||||||
|
application.baseBuildImage = event.detail.value;
|
||||||
|
await handleSubmit();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex items-center space-x-2 p-5 px-6 font-bold">
|
<div class="flex items-center space-x-2 p-5 px-6 font-bold">
|
||||||
@ -310,14 +323,42 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-2 items-center pb-8">
|
<div class="grid grid-cols-2 items-center">
|
||||||
<label for="baseImage" class="text-base font-bold text-stone-100"
|
<label for="baseImage" class="text-base font-bold text-stone-100"
|
||||||
>{$t('application.base_image')}</label
|
>{$t('application.base_image')}</label
|
||||||
>
|
>
|
||||||
<div class="no-underline">
|
<div class="custom-select-wrapper">
|
||||||
<input value={application.baseImage} id="baseImage" disabled class="bg-transparent " />
|
<Select
|
||||||
|
isDisabled={!$session.isAdmin || isRunning}
|
||||||
|
containerClasses={containerClass()}
|
||||||
|
id="baseImages"
|
||||||
|
showIndicator={!isRunning}
|
||||||
|
items={application.baseImages}
|
||||||
|
on:select={selectBaseImage}
|
||||||
|
value={application.baseImage}
|
||||||
|
isClearable={false}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{#if application.buildCommand || application.buildPack === 'rust'}
|
||||||
|
<div class="grid grid-cols-2 items-center pb-8">
|
||||||
|
<label for="baseBuildImage" class="text-base font-bold text-stone-100"
|
||||||
|
>{$t('application.base_build_image')}</label
|
||||||
|
>
|
||||||
|
<div class="custom-select-wrapper">
|
||||||
|
<Select
|
||||||
|
isDisabled={!$session.isAdmin || isRunning}
|
||||||
|
containerClasses={containerClass()}
|
||||||
|
id="baseBuildImages"
|
||||||
|
showIndicator={!isRunning}
|
||||||
|
items={application.baseBuildImages}
|
||||||
|
on:select={selectBaseBuildImage}
|
||||||
|
value={application.baseBuildImage}
|
||||||
|
isClearable={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex space-x-1 py-5 font-bold">
|
<div class="flex space-x-1 py-5 font-bold">
|
||||||
<div class="title">{$t('application.application')}</div>
|
<div class="title">{$t('application.application')}</div>
|
||||||
|
@ -46,14 +46,14 @@ textarea {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#svelte .custom-select-wrapper .selectContainer {
|
#svelte .custom-select-wrapper .selectContainer {
|
||||||
@apply h-12 w-96 rounded border-none bg-coolgray-200 p-2 text-xs font-bold tracking-tight outline-none transition duration-150 hover:bg-coolgray-500 focus:bg-coolgray-500 md:text-sm;
|
@apply h-12 w-96 rounded border-none bg-coolgray-200 p-2 px-0 text-xs tracking-tight outline-none transition duration-150 hover:bg-coolgray-500 focus:bg-coolgray-500 md:text-sm;
|
||||||
}
|
}
|
||||||
|
|
||||||
#svelte .listContainer {
|
#svelte .listContainer {
|
||||||
@apply bg-coolgray-400 text-white scrollbar-w-2 scrollbar-thumb-green-500 scrollbar-track-coolgray-200;
|
@apply bg-coolgray-400 text-white scrollbar-w-2 scrollbar-thumb-green-500 scrollbar-track-coolgray-200;
|
||||||
}
|
}
|
||||||
#svelte .selectedItem {
|
#svelte .selectedItem {
|
||||||
@apply pl-3;
|
@apply pl-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
#svelte .item.hover {
|
#svelte .item.hover {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user