Skip to content

Commit

Permalink
v1.0.11 (#41)
Browse files Browse the repository at this point in the history
Features: 
- Build packs for popular frontend frameworks. It will help to understand which build packs should be chosen.

Fixes:
- Github queries optimized.
- Save repositories to store (faster navigation).
- Remove unnecessary data on dashboard requests.
- Speed up static site builds with a lot.

UI:
- Redesign of the application deployment page.
- Redesign of database deployments page.
  • Loading branch information
andrasbacsai authored Apr 30, 2021
1 parent b416e3a commit cccb9a5
Show file tree
Hide file tree
Showing 49 changed files with 1,308 additions and 796 deletions.
125 changes: 48 additions & 77 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,93 +1,64 @@
# About

https://andrasbacsai.com/farewell-netlify-and-heroku-after-3-days-of-coding
# Coolify

# Features
- Deploy your Node.js, static sites, PHP or any custom application (with custom Dockerfile) just by pushing code to git.
- Hassle-free installation and upgrade process.
- One-click MongoDB, MySQL, PostgreSQL, CouchDB deployments!
An open-source, hassle-free, self-hostable Heroku & Netlify alternative.

# Upcoming features
- Backups & monitoring.
- User analytics with privacy in mind.
- And much more (see [Roadmap](https://github.com/coollabsio/coolify/projects/1)).
## Demo

[Small video](https://cdn.coollabs.io/assets/coolify/video/coolify.webm)

# FAQ
Q: What is a buildpack?

A: It defines your application's final form.
`Static` means that it will be hosted as a static site.
`NodeJs` means that it will be started as a node application.

# Screenshots

[Login](https://coolify.io/login.jpg)

[Applications](https://coolify.io/applications.jpg)

[Databases](https://coolify.io/databases.jpg)

[Configuration](https://coolify.io/configuration.jpg)

[Settings](https://coolify.io/settings.jpg)

[Logs](https://coolify.io/logs.jpg)

# Getting Started

Automatically: `/bin/bash -c "$(curl -fsSL https://get.coollabs.io/coolify/install.sh)"`

Manually:
### Requirements before installation
- [Docker](https://docs.docker.com/engine/install/) version 20+
- Docker in [swarm mode enabled](https://docs.docker.com/engine/reference/commandline/swarm_init/) (should be set manually before installation)
- A [MongoDB](https://docs.mongodb.com/manual/installation/) instance.
- We have a [simple installation](https://github.com/coollabsio/infrastructure/tree/main/mongo) if you need one
- A configured DNS entry (see `.env.template`)
- [Github App](https://docs.github.com/en/developers/apps/creating-a-github-app)

- GitHub App name: could be anything weird
- Homepage URL: https://yourdomain

Identifying and authorizing users:
- Callback URL: https://yourdomain/api/v1/login/github/app
- Request user authorization (OAuth) during installation -> Check!

Webhook:
- Active -> Check!
- Webhook URL: https://yourdomain/api/v1/webhooks/deploy
- Webhook Secret: it should be super secret

Repository permissions:
- Contents: Read-only
- Metadata: Read-only

User permissions:
- Email: Read-only

Subscribe to events:
- Push -> Check!
## Installation

### Installation
- Clone this repository: `git clone [email protected]:coollabsio/coolify.git`
- Set `.env` (see `.env.template`)
- Installation: `bash install.sh all`
Installation is automated with the following command:

## Manual updating process (You probably never need to do this!)
### Update everything (proxy+coolify)
- `bash install.sh all`
```bash
/bin/bash -c "$(curl -fsSL https://get.coollabs.io/coolify/install.sh)"
```

### Update coolify only
- `bash install.sh coolify`

## Features
You can deploy any of the following applications, databases and services easily.

(constantly growing lists)

### Applications
With Github integration

- Static sites
- NodeJS
- VueJS
- NuxtJS
- React/Preact
- NextJS
- Gatsby
- Svelte
- PHP
- Rust
- or any custom dockerfile

### Databases
- MongoDB
- MySQL
- PostgreSQL
- CouchDB

### Services
- [Plausible Analytics](https://plausible.io)

### Update proxy only
- `bash install.sh proxy`
## Support

# Contact
- Twitter: [@andrasbacsai](https://twitter.com/andrasbacsai)
- Telegram: [@andrasbacsai](https://t.me/andrasbacsai)
- Email: [[email protected]](mailto:[email protected])
- Discord: [Invitation](https://discord.com/invite/bvS3WhR)

## Roadmap
[See the Roadmap here](https://github.com/coollabsio/coolify/projects/1)

## License

# License
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Please see the [LICENSE](/LICENSE) file in our repository for the full text.


File renamed without changes.
25 changes: 25 additions & 0 deletions api/buildPacks/gatsby/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const fs = require('fs').promises
const { buildImage } = require('../helpers')
const { streamEvents, docker } = require('../../libs/docker')

// 'HEALTHCHECK --timeout=10s --start-period=10s --interval=5s CMD curl -I -s -f http://localhost/ || exit 1',
const publishStaticDocker = (configuration) => {
return [
'FROM nginx:stable-alpine',
'COPY nginx.conf /etc/nginx/nginx.conf',
'WORKDIR /usr/share/nginx/html',
`COPY --from=${configuration.build.container.name}:${configuration.build.container.tag}-cache /usr/src/app/${configuration.publish.directory} ./`,
'EXPOSE 80',
'CMD ["nginx", "-g", "daemon off;"]'
].join('\n')
}

module.exports = async function (configuration) {
await buildImage(configuration, true)
await fs.writeFile(`${configuration.general.workdir}/Dockerfile`, publishStaticDocker(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)
}
4 changes: 2 additions & 2 deletions api/buildPacks/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ const buildImageNodeDocker = (configuration) => {
`RUN ${configuration.build.command.build}`
].join('\n')
}
async function buildImage (configuration) {
async function buildImage (configuration, cacheBuild) {
await fs.writeFile(`${configuration.general.workdir}/Dockerfile`, buildImageNodeDocker(configuration))
const stream = await docker.engine.buildImage(
{ src: ['.'], context: configuration.general.workdir },
{ t: `${configuration.build.container.name}:${configuration.build.container.tag}` }
{ t: `${configuration.build.container.name}:${cacheBuild ? `${configuration.build.container.tag}-cache` : configuration.build.container.tag}` }
)
await streamEvents(stream, configuration)
}
Expand Down
12 changes: 9 additions & 3 deletions api/buildPacks/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
const static = require('./static')
const Static = require('./static')
const react = require('./react')
const nextjs = require('./nextjs')
const nuxtjs = require('./nuxtjs')
const gatsby = require('./gatsby')
const vuejs = require('./vuejs')
const svelte = require('./svelte')
const nodejs = require('./nodejs')
const php = require('./php')
const custom = require('./custom')
const docker = require('./docker')
const rust = require('./rust')

module.exports = { static, nodejs, php, custom, rust }
module.exports = { static: Static, nodejs, php, docker, rust, react, vuejs, nextjs, nuxtjs, svelte, gatsby }
28 changes: 28 additions & 0 deletions api/buildPacks/nextjs/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const fs = require('fs').promises
const { buildImage } = require('../helpers')
const { streamEvents, docker } = require('../../libs/docker')
// `HEALTHCHECK --timeout=10s --start-period=10s --interval=5s CMD curl -I -s -f http://localhost:${configuration.publish.port}${configuration.publish.path} || exit 1`,
const publishNodejsDocker = (configuration) => {
return [
'FROM node:lts',
'WORKDIR /usr/src/app',
configuration.build.command.build
? `COPY --from=${configuration.build.container.name}:${configuration.build.container.tag} /usr/src/app/${configuration.publish.directory} ./`
: `
COPY ${configuration.build.directory}/package*.json ./
RUN ${configuration.build.command.installation}
COPY ./${configuration.build.directory} ./`,
`EXPOSE ${configuration.publish.port}`,
'CMD [ "yarn", "start" ]'
].join('\n')
}

module.exports = async function (configuration) {
await buildImage(configuration)
await fs.writeFile(`${configuration.general.workdir}/Dockerfile`, publishNodejsDocker(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)
}
28 changes: 28 additions & 0 deletions api/buildPacks/nuxtjs/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const fs = require('fs').promises
const { buildImage } = require('../helpers')
const { streamEvents, docker } = require('../../libs/docker')
// `HEALTHCHECK --timeout=10s --start-period=10s --interval=5s CMD curl -I -s -f http://localhost:${configuration.publish.port}${configuration.publish.path} || exit 1`,
const publishNodejsDocker = (configuration) => {
return [
'FROM node:lts',
'WORKDIR /usr/src/app',
configuration.build.command.build
? `COPY --from=${configuration.build.container.name}:${configuration.build.container.tag} /usr/src/app/${configuration.publish.directory} ./`
: `
COPY ${configuration.build.directory}/package*.json ./
RUN ${configuration.build.command.installation}
COPY ./${configuration.build.directory} ./`,
`EXPOSE ${configuration.publish.port}`,
'CMD [ "yarn", "start" ]'
].join('\n')
}

module.exports = async function (configuration) {
await buildImage(configuration)
await fs.writeFile(`${configuration.general.workdir}/Dockerfile`, publishNodejsDocker(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)
}
25 changes: 25 additions & 0 deletions api/buildPacks/react/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const fs = require('fs').promises
const { buildImage } = require('../helpers')
const { streamEvents, docker } = require('../../libs/docker')

// 'HEALTHCHECK --timeout=10s --start-period=10s --interval=5s CMD curl -I -s -f http://localhost/ || exit 1',
const publishStaticDocker = (configuration) => {
return [
'FROM nginx:stable-alpine',
'COPY nginx.conf /etc/nginx/nginx.conf',
'WORKDIR /usr/share/nginx/html',
`COPY --from=${configuration.build.container.name}:${configuration.build.container.tag}-cache /usr/src/app/${configuration.publish.directory} ./`,
'EXPOSE 80',
'CMD ["nginx", "-g", "daemon off;"]'
].join('\n')
}

module.exports = async function (configuration) {
await buildImage(configuration, true)
await fs.writeFile(`${configuration.general.workdir}/Dockerfile`, publishStaticDocker(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)
}
5 changes: 2 additions & 3 deletions api/buildPacks/static/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,16 @@ const publishStaticDocker = (configuration) => {
'COPY nginx.conf /etc/nginx/nginx.conf',
'WORKDIR /usr/share/nginx/html',
configuration.build.command.build
? `COPY --from=${configuration.build.container.name}:${configuration.build.container.tag} /usr/src/app/${configuration.publish.directory} ./`
? `COPY --from=${configuration.build.container.name}:${configuration.build.container.tag}-cache /usr/src/app/${configuration.publish.directory} ./`
: `COPY ./${configuration.build.directory} ./`,
'EXPOSE 80',
'CMD ["nginx", "-g", "daemon off;"]'
].join('\n')
}

module.exports = async function (configuration) {
if (configuration.build.command.build) await buildImage(configuration)
if (configuration.build.command.build) await buildImage(configuration, true)
await fs.writeFile(`${configuration.general.workdir}/Dockerfile`, publishStaticDocker(configuration))

const stream = await docker.engine.buildImage(
{ src: ['.'], context: configuration.general.workdir },
{ t: `${configuration.build.container.name}:${configuration.build.container.tag}` }
Expand Down
25 changes: 25 additions & 0 deletions api/buildPacks/svelte/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const fs = require('fs').promises
const { buildImage } = require('../helpers')
const { streamEvents, docker } = require('../../libs/docker')

// 'HEALTHCHECK --timeout=10s --start-period=10s --interval=5s CMD curl -I -s -f http://localhost/ || exit 1',
const publishStaticDocker = (configuration) => {
return [
'FROM nginx:stable-alpine',
'COPY nginx.conf /etc/nginx/nginx.conf',
'WORKDIR /usr/share/nginx/html',
`COPY --from=${configuration.build.container.name}:${configuration.build.container.tag}-cache /usr/src/app/${configuration.publish.directory} ./`,
'EXPOSE 80',
'CMD ["nginx", "-g", "daemon off;"]'
].join('\n')
}

module.exports = async function (configuration) {
await buildImage(configuration, true)
await fs.writeFile(`${configuration.general.workdir}/Dockerfile`, publishStaticDocker(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)
}
25 changes: 25 additions & 0 deletions api/buildPacks/vuejs/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const fs = require('fs').promises
const { buildImage } = require('../helpers')
const { streamEvents, docker } = require('../../libs/docker')

// 'HEALTHCHECK --timeout=10s --start-period=10s --interval=5s CMD curl -I -s -f http://localhost/ || exit 1',
const publishStaticDocker = (configuration) => {
return [
'FROM nginx:stable-alpine',
'COPY nginx.conf /etc/nginx/nginx.conf',
'WORKDIR /usr/share/nginx/html',
`COPY --from=${configuration.build.container.name}:${configuration.build.container.tag}-cache /usr/src/app/${configuration.publish.directory} ./`,
'EXPOSE 80',
'CMD ["nginx", "-g", "daemon off;"]'
].join('\n')
}

module.exports = async function (configuration) {
await buildImage(configuration, true)
await fs.writeFile(`${configuration.general.workdir}/Dockerfile`, publishStaticDocker(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)
}
11 changes: 8 additions & 3 deletions api/libs/applications/cleanup/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ const { docker } = require('../../docker')
const { execShellAsync } = require('../../common')
const Deployment = require('../../../models/Deployment')

async function purgeImagesContainers (configuration) {
async function purgeImagesContainers (configuration, deleteAll = false) {
const { name, tag } = configuration.build.container
await execShellAsync('docker container prune -f')
const IDsToDelete = (await execShellAsync(`docker images ls --filter=reference='${name}' --filter=before='${name}:${tag}' --format '{{json .ID }}'`)).trim().replace(/"/g, '').split('\n')
if (IDsToDelete.length !== 0) for (const id of IDsToDelete) await execShellAsync(`docker rmi -f ${id}`)
if (deleteAll) {
const IDsToDelete = (await execShellAsync(`docker images ls --filter=reference='${name}' --format '{{json .ID }}'`)).trim().replace(/"/g, '').split('\n')
if (IDsToDelete.length > 0) await execShellAsync(`docker rmi -f ${IDsToDelete.toString().replace(',', ' ')}`)
} else {
const IDsToDelete = (await execShellAsync(`docker images ls --filter=reference='${name}' --filter=before='${name}:${tag}' --format '{{json .ID }}'`)).trim().replace(/"/g, '').split('\n')
if (IDsToDelete.length > 1) await execShellAsync(`docker rmi -f ${IDsToDelete.toString().replace(',', ' ')}`)
}
await execShellAsync('docker image prune -f')
}

Expand Down
10 changes: 3 additions & 7 deletions api/libs/applications/configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,10 @@ function setDefaultConfiguration (configuration) {

if (!configuration.publish.path) configuration.publish.path = '/'
if (!configuration.publish.port) {
if (configuration.build.pack === 'php') {
configuration.publish.port = 80
} else if (configuration.build.pack === 'static') {
configuration.publish.port = 80
} else if (configuration.build.pack === 'nodejs') {
configuration.publish.port = 3000
} else if (configuration.build.pack === 'rust') {
if (configuration.build.pack === 'nodejs' && configuration.build.pack === 'vuejs' && configuration.build.pack === 'nuxtjs' && configuration.build.pack === 'rust' && configuration.build.pack === 'nextjs') {
configuration.publish.port = 3000
} else {
configuration.publish.port = 80
}
}

Expand Down
Loading

0 comments on commit cccb9a5

Please sign in to comment.