Skip to content

Commit becd2c8

Browse files
committed
Merge branch 'develop', prepare 2.0.1
2 parents b55f7bf + c24d215 commit becd2c8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+4144
-2375
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
language: node_js
22

3-
node_js: 8
3+
node_js: node
44

55
cache: yarn
66

README.md

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,24 @@
44
55
[![Build Status](https://travis-ci.org/exoframejs/exoframe.svg?branch=master)](https://travis-ci.org/exoframejs/exoframe)
66
[![Coverage Status](https://coveralls.io/repos/github/exoframejs/exoframe/badge.svg?branch=master)](https://coveralls.io/github/exoframejs/exoframe?branch=master)
7-
[![Greenkeeper badge](https://badges.greenkeeper.io/exoframejs/exoframe.svg)](https://greenkeeper.io/)
87
[![npm](https://img.shields.io/npm/v/exoframe.svg)](https://www.npmjs.com/package/exoframe)
98
[![license](https://img.shields.io/github/license/mashape/apistatus.svg?maxAge=2592000)](https://opensource.org/licenses/MIT)
109

1110
Exoframe is a self-hosted tool that allows simple one-command deployments using Docker.
1211

1312
## Features
1413

15-
- One-command project deployment
16-
- SSH key based auth
17-
- Rolling updates
18-
- Deploy tokens (e.g. to deploy from CI)
19-
- Automated HTTPS setup via letsencrypt *
20-
- Automated gzip compression *
21-
- Simple access to the logs of deployments
22-
- Docker-compose support
23-
- Multiple deployment endpoints and multi-user support
24-
- Simple update procedure for client, server and Traefik
25-
- Optional automatic subdomain assignment (i.e. every deployment gets its own subdomain)
14+
* One-command project deployment
15+
* SSH key based auth
16+
* Rolling updates
17+
* Deploy tokens (e.g. to deploy from CI)
18+
* Automated HTTPS setup via letsencrypt \*
19+
* Automated gzip compression \*
20+
* Simple access to the logs of deployments
21+
* Docker-compose support
22+
* Multiple deployment endpoints and multi-user support
23+
* Simple update procedure for client, server and Traefik
24+
* Optional automatic subdomain assignment (i.e. every deployment gets its own subdomain)
2625

2726
\* Feature provided by [Traefik](https://traefik.io/)
2827

@@ -63,7 +62,12 @@ You can find a list of all commands and options in the [docs](./docs/README.md).
6362

6463
## Docs
6564

66-
You can find project documentation in the [docs folder](./docs/README.md).
65+
* [Basics](Basics.md)
66+
* [FAQ](FAQ.md)
67+
* [Templates guide](TemplatesGuide.md)
68+
* [Using nightly versions](Nightly.md)
69+
* [Articles, video and related links](Links.md)
70+
* [Change Log](../CHANGELOG.md)
6771

6872
## License
6973

docs/Basics.md

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,48 +2,54 @@
22

33
## Concepts
44

5-
- **Project** - one or more deployments grouped together (e.g. started via docker-compose)
6-
- **Deployment** - one and only one deployed service
5+
* **Project** - one or more deployments grouped together (e.g. started via docker-compose)
6+
* **Deployment** - one and only one deployed service
77

88
## Requirements
99

1010
Exoframe CLI is not particularly demanding and consumes at max ~50mb of RAM.
1111
Most intensive task from CLI side is packaging the project and streaming that to the server - it doesn't affect RAM usage that much and mostly relies on CPU and network.
1212

1313
Running Exoframe server on its own also doesn't require too much resources:
14-
- Exoframe Server consumes ~50mb of RAM
15-
- Traefik started along with server consumes ~60mb of RAM
14+
15+
* Exoframe Server consumes ~50mb of RAM
16+
* Traefik started along with server consumes ~60mb of RAM
1617

1718
Be aware though - execution of deployments will result in (1) new Docker images being built and (2) new Docker containers being started.
1819
Depending on your project's complexity, this might require significant amount of resources during both steps resulting in failed deployments (note: if Docker goes out-of-memory during build, you will not get any specific error - just a failed deployment).
1920
It is recommended to run Exoframe on a server with at least 1GB of RAM.
2021

21-
## Supported project types
22+
## Supported project types & deployment templates
2223

23-
Currently, Exoframe understands and can deploy the following project types:
24+
By default, Exoframe understands and can deploy the following project types:
2425

2526
1. Static html based projects - will be deployed using [nginx](http://hub.docker.com/_/nginx) image
26-
2. Node.js based projects - will be deployed using [node:latest](https://hub.docker.com/_/node) image *
27+
2. Node.js based projects - will be deployed using [node:latest](https://hub.docker.com/_/node) image \*
2728
3. Docker based project - will be deployed using your [Dockerfile](https://docs.docker.com/engine/reference/builder/)
2829
4. Docker-Compose based projects - will be deployed using your [docker-compose](https://docs.docker.com/compose/compose-file/) file
2930

3031
\* There are two things to keep in mind for Node.js projects: (1) they are started via `npm start`, so make sure you have specified start script in your `package.json`; (2) by default port 80 is exposed, so you need to make your app listen on that port. If you'd like to execute your app in any different way or expose more ports - please use Dockerfile deployment method.
3132

33+
This list can be extended via deployment templates.
34+
You can find the list of available templates [on npm](https://www.npmjs.com/search?q=exoframe-template).
35+
Templates can be installed by executing `exoframe template` command and entering complete template package name.
36+
3237
## Commands
3338

34-
| Command | Description |
35-
| ---------------------- | ----------- |
36-
| deploy [path] | Deploy specified path |
37-
| config | Generate or update project config for current path |
38-
| list | List currently deployed projects |
39-
| rm <id> | Remove existing deployment or project |
40-
| log <id> | Get logs for existing deployment or project |
41-
| token [ls|rm] | Generate, list or remove deployment tokens |
42-
| login | Login into Exoframe server |
43-
| endpoint [url] | Selects or adds the endpoint of Exoframe server |
44-
| rm-endpoint [url] | Removes an existing endpoint of Exoframe server |
45-
| update [target] | Gets current versions or updates given target (server | traefik | all) |
46-
| completion | Generates bash completion script |
39+
| Command | Description |
40+
| ----------------- | -------------------------------------------------------------------- |
41+
| deploy [path] | Deploy specified path |
42+
| config | Generate or update project config for current path |
43+
| list | List currently deployed projects |
44+
| rm <id> | Remove existing deployment or project |
45+
| log <id> | Get logs for existing deployment or project |
46+
| template [ls, rm] | Add, list or remove deployment templates from the server |
47+
| token [ls, rm] | Generate, list or remove deployment tokens |
48+
| login | Login into Exoframe server |
49+
| endpoint [url] | Selects or adds the endpoint of Exoframe server |
50+
| rm-endpoint [url] | Removes an existing endpoint of Exoframe server |
51+
| update [target] | Gets current versions or updates given target (server, traefik, all) |
52+
| completion | Generates bash completion script |
4753

4854
## Project config file
4955

@@ -52,6 +58,7 @@ It can either be generated/updated using `exoframe config` command or created ma
5258
If it doesn't exist during deployment, Exoframe will generate simple config file that only contains name of the current project.
5359

5460
Config file has the following structure:
61+
5562
```js
5663
{
5764
// deployment name
@@ -76,7 +83,14 @@ Config file has the following structure:
7683
// internal hostname for container [optional]
7784
// see docker docs for more info
7885
// no hostname is assigned by default
79-
"hostname": "hostname"
86+
"hostname": "hostname",
87+
// Add additional docker labels to your container [optional]
88+
"labels": {
89+
"my.custom.label": "value"
90+
},
91+
// template to be used for project deployment
92+
// undefined by default, detected by server based on file structure
93+
"template": "my-template"
8094
}
8195
```
8296

@@ -91,7 +105,7 @@ endpoint: 'http://localhost:8080' # your endpoint URL, defaults to localhost
91105
92106
## Deployment tokens
93107
94-
Sometimes you might need to deploy things from environments that don't have your private key (e.g. CI/CD services).
108+
Sometimes you might need to deploy things from environments that don't have your private key (e.g. CI/CD services).
95109
For this cases you can use deployment tokens. Here's how it works:
96110
97111
1. Make sure you are logged in to your Exoframe server
@@ -105,7 +119,7 @@ This can be done by passing `--update` (or `-u`) flag to deploy command.
105119
The way it works is quite simple:
106120

107121
1. Exoframe deploys new version of the given project
108-
2. Exoframe then waits for them to start up
122+
2. Exoframe then waits for them to start up
109123
3. Exoframe removes the old running deployments for current project
110124

111125
This can be used together with deployment tokens to achieve simple continuous deployment for your projects.

docs/FAQ.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Is it ready for production?
44

5-
Yes. We've been using it to deploy our project since May 2017 without any issues.
5+
Yes. We've been using it to deploy our project since May 2017 without any issues.
66

77
## Why do I need to enter username during login?
88

docs/Links.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
## Articles
44

5-
- [Introducing Exoframe (beta) — self-hosted alternative to Now.sh](https://hackernoon.com/introducing-exoframe-beta-self-hosted-alternative-to-now-sh-80643f96b84b)
6-
- [Continuous deployment for your Node.js projects in 10 minutes with Exoframe](https://hackernoon.com/continuous-deployment-for-your-node-js-projects-in-10-minutes-with-exoframe-bdf48340c1be)
7-
- [Simplifying Docker management with Exoframe](https://hackernoon.com/simplifying-docker-management-with-exoframe-9275e92c7406)
5+
* [Introducing Exoframe (beta) — self-hosted alternative to Now.sh](https://hackernoon.com/introducing-exoframe-beta-self-hosted-alternative-to-now-sh-80643f96b84b)
6+
* [Continuous deployment for your Node.js projects in 10 minutes with Exoframe](https://hackernoon.com/continuous-deployment-for-your-node-js-projects-in-10-minutes-with-exoframe-bdf48340c1be)
7+
* [Simplifying Docker management with Exoframe](https://hackernoon.com/simplifying-docker-management-with-exoframe-9275e92c7406)
88

99
## Videos
1010

11-
- [Introducing Exoframe - self-hosted Now.sh alternative](https://www.youtube.com/watch?v=VZnYKIoh5oA)
12-
- [Continuous Deployment for Node.js projects in 10 mins using Exoframe](https://www.youtube.com/watch?v=AEwLt5hmKYo)
11+
* [Introducing Exoframe - self-hosted Now.sh alternative](https://www.youtube.com/watch?v=VZnYKIoh5oA)
12+
* [Continuous Deployment for Node.js projects in 10 mins using Exoframe](https://www.youtube.com/watch?v=AEwLt5hmKYo)

docs/Nightly.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Using Nightly Versions
2+
3+
You can optionally use nightly version of Exoframe CLI and Server.
4+
While they do provide latest features, it is not recommended to use them for production.
5+
6+
## Nightly CLI builds
7+
8+
You can install nightly CLI builds using the following command:
9+
10+
```
11+
npm install -g exoframe@next
12+
```
13+
14+
## Nightly Exoframe-server builds
15+
16+
You can install nightly server builds by following two steps.
17+
First, you need to modify server config and add the following line:
18+
19+
```yaml
20+
updateChannel: nightly
21+
```
22+
23+
Then, you need to run `exoframe server update` against the endpoint you've configured to update to latest nightly build of server.

docs/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,7 @@
22

33
* [Basics](Basics.md)
44
* [FAQ](FAQ.md)
5+
* [Templates guide](TemplatesGuide.md)
6+
* [Using nightly versions](Nightly.md)
57
* [Articles, video and related links](Links.md)
68
* [Change Log](../CHANGELOG.md)

docs/TemplatesGuide.md

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# Templates guide
2+
3+
Exoframe allows extending the types of deployments it supports using third party plugins.
4+
This guide aims to explain basics you need to know to create your own templates.
5+
If you are looking for template usage - please see [Basics](Basics.md) part of the docs.
6+
7+
## Basics
8+
9+
Exoframe uses [yarn](https://yarnpkg.com/) to install and remove third-party templates.
10+
The templates then are added to Exoframe server using Node.js `require()` method.
11+
So, make sure that your template's `package.json` has correct `main` attribute.
12+
13+
Your template main script needs to export the following variables and methods:
14+
15+
```js
16+
// template name
17+
// can be used by user to specify the template in config
18+
exports.name = 'mytemplate';
19+
20+
// function to check if the template fits the project
21+
// will be executed unless template is specified by user explicitly
22+
exports.checkTemplate = async props => {};
23+
24+
// function to execute current template
25+
// handle building and starting the containers
26+
exports.executeTemplate = async props => {};
27+
```
28+
29+
## Template props
30+
31+
Both `checkTemplate` and `executeTemplate` get the same properties object upon execution.
32+
This object contains all data and methods required to build and execute new docker containers.
33+
Here's a snippet from the Exoframe server code that shows the props object being assembled:
34+
35+
```js
36+
// generate template props
37+
const templateProps = {
38+
// user project config
39+
config,
40+
// current user username
41+
username,
42+
// response stream, used to send log back to user
43+
resultStream,
44+
// temp dir that contains the project
45+
tempDockerDir,
46+
// docker-related things
47+
docker: {
48+
// docker daemon, instance of dockerode
49+
daemon: docker,
50+
// exoframe build function
51+
// has following signature: async ({username, resultStream}) => {}
52+
// executes `docker build` in project temp dir
53+
// returns following object: {log, image}
54+
build,
55+
// exoframe start function
56+
// has the following signature: async ({image, username, resultStream}) => {}
57+
// executes `docker start` with given image while setting all required labels, env vars, etc
58+
// returns inspect info from started container
59+
start,
60+
},
61+
// exoframe utilities & logger
62+
// see code here: https://github.com/exoframejs/exoframe-server/blob/master/src/util/index.js
63+
util: Object.assign({}, util, {
64+
logger,
65+
}),
66+
};
67+
```
68+
69+
## Checking if the projects fit your template
70+
71+
First thing Exoframe server will do is execute your `checkTemplate` function to see if your template fits the current project.
72+
Typically you'd want to read the list of files in temporary project folder and see if it contains files related to your template type.
73+
Here's an example of the core static HTML template, it check whether folder contains `index.html` file:
74+
75+
```js
76+
// function to check if the template fits this recipe
77+
exports.checkTemplate = async ({tempDockerDir}) => {
78+
// if project already has dockerfile - just exit
79+
try {
80+
const filesList = fs.readdirSync(tempDockerDir);
81+
if (filesList.includes('index.html')) {
82+
return true;
83+
}
84+
return false;
85+
} catch (e) {
86+
return false;
87+
}
88+
};
89+
```
90+
91+
## Executing the template
92+
93+
Once you've determined that the project is indeed supported by your template, you will need to execute it.
94+
It is up to you to build _and_ start a docker image.
95+
Here's an example for the same static HTML core template that deploys current project using Nginx Dockerfile:
96+
97+
```js
98+
const nginxDockerfile = `FROM nginx:latest
99+
COPY . /usr/share/nginx/html
100+
RUN chmod -R 755 /usr/share/nginx/html
101+
`;
102+
103+
// function to execute current template
104+
exports.executeTemplate = async ({username, tempDockerDir, resultStream, util, docker}) => {
105+
try {
106+
// generate new dockerfile
107+
const dockerfile = nginxDockerfile;
108+
// write the file to project temp dir
109+
const dfPath = path.join(tempDockerDir, 'Dockerfile');
110+
fs.writeFileSync(dfPath, dockerfile, 'utf-8');
111+
// send log to user
112+
util.writeStatus(resultStream, {message: 'Deploying Static HTML project..', level: 'info'});
113+
114+
// build docker image
115+
const buildRes = await docker.build({username, resultStream});
116+
// send results to user
117+
util.logger.debug('Build result:', buildRes);
118+
119+
// check for errors in build log
120+
if (
121+
buildRes.log
122+
.map(it => it.toLowerCase())
123+
.some(it => it.includes('error') || (it.includes('failed') && !it.includes('optional')))
124+
) {
125+
// if there are - add to server log
126+
util.logger.debug('Build log conains error!');
127+
// and report to user
128+
util.writeStatus(resultStream, {message: 'Build log contains errors!', level: 'error'});
129+
// and end the result stream immediately
130+
resultStream.end('');
131+
return;
132+
}
133+
134+
// start image
135+
const containerInfo = await docker.start(Object.assign({}, buildRes, {username, resultStream}));
136+
// log results in server logs
137+
util.logger.debug(containerInfo.Name);
138+
139+
// clean temp folder
140+
await util.cleanTemp();
141+
142+
// get container info
143+
const containerData = docker.daemon.getContainer(containerInfo.Id);
144+
const container = await containerData.inspect();
145+
// return new deployments to user
146+
util.writeStatus(resultStream, {message: 'Deployment success!', deployments: [container], level: 'info'});
147+
// end result stream
148+
resultStream.end('');
149+
} catch (e) {
150+
// if there was an error - log it in server log
151+
util.logger.debug('build failed!', e);
152+
// return it to user
153+
util.writeStatus(resultStream, {message: e.error, error: e.error, log: e.log, level: 'error'});
154+
// end result stream
155+
resultStream.end('');
156+
}
157+
};
158+
```
159+
160+
## Examples
161+
162+
* [Core templates](https://github.com/exoframejs/exoframe-server/tree/master/src/docker/templates) (incl. node, nginx, dockerfile and docker-compose)
163+
* [Maven template](https://github.com/exoframejs/exoframe-template-maven)
164+
* [Java template](https://github.com/exoframejs/exoframe-template-java)
165+
* [Tomcat template](https://github.com/exoframejs/exoframe-template-tomcat)

0 commit comments

Comments
 (0)