Skip to content

Commit

Permalink
Feature: docker-compose deployment (ToolJet#388)
Browse files Browse the repository at this point in the history
* separate dockerfile for tooljet client in development mode

* production dockerfile for tooljet client

* reference the tooljet clients dev dockerfile in the docker-compose file

* use a fallback url for API_URL in cases where TOOLJET_SERVER_URL is not defined

* nginx config file for the front-end

* docker-compose file for production deploys

* dont run postgres inside docker-compose

* use an entrypoint script for setting the server host for nginx

* separate volume for fallback certs

* add docs for docker-compose deployment

* add required database keys in the .env.example file

* address review comments
  • Loading branch information
ashishmax31 authored Jul 12, 2021
1 parent 2074fff commit 2c59616
Show file tree
Hide file tree
Showing 9 changed files with 266 additions and 13 deletions.
7 changes: 6 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
TOOLJET_HOST=http://localhost:8082
TOOLJET_HOST=http://<host_name>

LOCKBOX_MASTER_KEY=replace_with_encryption_key

SECRET_KEY_BASE=replace_with_secret_key_base

PG_DB=<db name>
PG_USER=<db username>
PG_HOST=<db host>
PG_PASS=<db password>

# Checks every 24 hours to see if a new version of ToolJet is available
CHECK_FOR_UPDATES=check_if_updates_are_available

Expand Down
35 changes: 35 additions & 0 deletions deploy/docker/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
version: '3'

services:
client:
tty: true
stdin_open: true
image: tooljet/tooljet-client-ce:latest
restart: always
depends_on:
- server
volumes:
- logs:/var/log/openresty/
- certs:/etc/resty-auto-ssl/
- fallbackcerts:/etc/fallback-certs
ports:
- 80:80
- 443:443
command: openresty -g "daemon off;"

server:
image: tooljet/tooljet-server-ce:latest
tty: true
stdin_open: true
restart: always
ports:
- 3000
env_file: .env
environment:
RAILS_LOG_TO_STDOUT: "true"
command: ["bundle", "exec", "rails", "s", "-p", "3000", "-b", "0.0.0.0"]

volumes:
certs:
logs:
fallbackcerts:
2 changes: 1 addition & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ services:
<<: *base
build:
context: ./frontend
dockerfile: ../docker/client.Dockerfile
dockerfile: ../docker/client.Dockerfile.dev
image: tooljet-client:development
volumes:
- ./frontend:/app:delegated
Expand Down
25 changes: 17 additions & 8 deletions docker/client.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# pull official base image
FROM node:14.17.0-alpine
FROM node:14.17.0-alpine AS builder

# set working directory
WORKDIR /app
Expand All @@ -12,14 +12,23 @@ ENV NODE_OPTIONS="--max-old-space-size=2048"

# install app dependencies
COPY package.json package-lock.json ./
RUN npm install
RUN npm install react-scripts@3.4.1 -g --silent
RUN npm install --only=production
COPY . .
RUN NODE_ENV=production npm run-script build

# add app
COPY . ./

FROM openresty/openresty:1.19.9.1rc1-buster-fat

# start app
CMD ["npm", "start"]
RUN apt-get update && apt-get -y install --no-install-recommends wget \
gnupg ca-certificates apt-utils curl luarocks \
make build-essential g++ gcc autoconf

EXPOSE 8082
RUN luarocks install lua-resty-auto-ssl

RUN mkdir /etc/resty-auto-ssl /var/log/openresty /var/www /etc/fallback-certs

COPY --from=builder /app/build /var/www

COPY ./config/nginx.conf.template /etc/openresty/nginx.conf.template
COPY ./config/entrypoint.sh /entrypoint.sh
ENTRYPOINT ["./entrypoint.sh"]
25 changes: 25 additions & 0 deletions docker/client.Dockerfile.dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# pull official base image
FROM node:14.17.0-alpine

# set working directory
WORKDIR /app

# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH

# Fix for heap limit allocation issue
ENV NODE_OPTIONS="--max-old-space-size=2048"

# install app dependencies
COPY package.json package-lock.json ./
RUN npm install
RUN npm install react-scripts@3.4.1 -g --silent

# add app
COPY . ./


# start app
CMD ["npm", "start"]

EXPOSE 8082
56 changes: 54 additions & 2 deletions docs/docs/deployment/docker.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,57 @@
---
sidebar_position: 3
sidebar_position: 2
sidebar_label: Docker
---

# Docker
# Deploying ToolJet using docker-compose

:::info
You should setup a PostgreSQL database manually to be used by the ToolJet server.
:::

Follow the steps below to deploy ToolJet ( both server & client ) on a server using docker-compose:

1. Setup a PostgreSQL database and make sure that the database is accessible.

2. Install docker and docker-compose on the server.
[Docker Installation](https://docs.docker.com/engine/install/)
[Docker Compose Installation](https://docs.docker.com/compose/install/)

3. Download our production docker-compose file into the server by running:
`curl -LO https://raw.githubusercontent.com/ToolJet/ToolJet/main/deploy/docker/docker-compose.yaml`

4. Download the example `.env` file in the current directory (where the docker-compose.yaml file is downloaded) by running:
`curl -LO https://raw.githubusercontent.com/ToolJet/ToolJet/main/.env.example `
Populate the keys in the `.env.example` file and run `mv .env.example .env ` to rename the file to `.env`.
(Read [environment variables reference](/docs/deployment/env-vars))
`TOOLJET_HOST` environment variable determines where you can access the ToolJet client. It can either be the public ipv4 address of your server or a custom domain that you want to use.

Examples:
`TOOLJET_HOST=http://12.34.56.78` or
`TOOLJET_HOST=https://yourdomain.com` or
`TOOLJET_HOST=https://tooljet.yourdomain.com`

:::info
We use a [lets encrypt](https://letsencrypt.org/) plugin on top of nginx to create TLS certificates on the fly.
:::

:::info
Please make sure that `TOOLJET_HOST` starts with either `http://` or `https://`
:::

5. Once you've populated the `.env` file, run `docker-compose up -d` to start all the required services.
:::info
If you're running on a linux server, `docker` might need sudo permissions. In that case you can either run:
`sudo docker-compose up -d`
OR
Setup docker to run without root privilages by following the instructions written here https://docs.docker.com/engine/install/linux-postinstall/
:::

6. If you've set a custom domain for `TOOLJET_HOST`, add a `A record` entry in your DNS settings to point to the IP address of the server.

7. Seed the database by running `docker-compose run server rake db:seed`. This seeds the database with a default user with the following credentials:
email : dev@tooljet.io
password: password


8. You're all done, ToolJet client would now be served at the URL you've set in `TOOLJET_HOST`.
13 changes: 13 additions & 0 deletions frontend/config/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env sh
set -eu
export SERVER_HOST="${SERVER_HOST:=server}"

if [ ! -f /etc/fallback-certs/resty-auto-ssl-fallback.crt ]; then
openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 \
-subj '/CN=sni-support-required-for-valid-ssl' \
-keyout /etc/fallback-certs/resty-auto-ssl-fallback.key \
-out /etc/fallback-certs/resty-auto-ssl-fallback.crt
fi
envsubst '${SERVER_HOST}' < /etc/openresty/nginx.conf.template > /etc/openresty/nginx.conf

exec "$@"
114 changes: 114 additions & 0 deletions frontend/config/nginx.conf.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
user root;
worker_processes auto;
pid /usr/local/openresty/nginx/logs/nginx.pid;

events
{
worker_connections 1024;
}

http
{
include mime.types;
default_type application/octet-stream;

sendfile on;
tcp_nopush on;
tcp_nodelay on;

keepalive_timeout 65;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

access_log /var/log/openresty/access.log;
error_log /var/log/openresty/error.log;

gzip on;
gzip_disable "msie6";

lua_shared_dict auto_ssl 1m;
lua_shared_dict auto_ssl_settings 64k;
resolver 8.8.8.8 ipv6=off;

init_by_lua_block
{
auto_ssl = (require "resty.auto-ssl").new()
auto_ssl:set("allow_domain", function(domain)
return true
end)
auto_ssl:init()
}

init_worker_by_lua_block
{
auto_ssl:init_worker()
}

server
{
listen 443 ssl;
ssl_certificate_by_lua_block
{
auto_ssl:ssl_certificate()
}
ssl_certificate /etc/fallback-certs/resty-auto-ssl-fallback.crt;
ssl_certificate_key /etc/fallback-certs/resty-auto-ssl-fallback.key;


location /
{
root /var/www;
try_files $uri $uri/ /index.html;
}

location /_backend_
{
rewrite /_backend_/(.*) /$1 break;
proxy_pass http://${SERVER_HOST}:3000;
proxy_redirect off;
proxy_set_header Host $host;
}
}

server
{
listen 80;
location /.well-known/acme-challenge/
{
content_by_lua_block
{
auto_ssl:challenge_server()
}
}

location /
{
root /var/www;
try_files $uri $uri/ /index.html;
}

location /_backend_
{
rewrite /_backend_/(.*) /$1 break;
proxy_pass http://${SERVER_HOST}:3000;
proxy_redirect off;
proxy_set_header Host $host;
}

}

server
{
listen 127.0.0.1:8999;
client_body_buffer_size 128k;
client_max_body_size 128k;

location /
{
content_by_lua_block
{
auto_ssl:hook_server()
}
}
}
}
2 changes: 1 addition & 1 deletion frontend/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const path = require('path');
const environment = process.env.NODE_ENV === 'production' ? 'production' : 'development';

const API_URL = {
production: process.env.TOOLJET_SERVER_URL,
production: process.env.TOOLJET_SERVER_URL || '/_backend_',
development: 'http://localhost:3000'
};

Expand Down

0 comments on commit 2c59616

Please sign in to comment.