Hosting Xeditor in Docker

In this chapter we show you two options to host Xeditor in a docker container.

AtomicService

In the following, we will package each Xeditor component in one Docker image. This has some advantages and disadvantages.

We created a sample project for this case which can be found here.

We recommend using this for a productive configuration, as the main advantage is simplicity for high availability and high performance. However, to host this in a truly productive way, we recommend using Kubernetes instead of "docker-compose". However, Kubernetes will not be covered in this section, since it's not really related to Xeditor.

In order to handle the requests correctly we are using the reverse proxy nginx. Nginx will pass all calls to <url>/api/** to the middleware server and tries to load static files for <url>/**. For this reason in the editor we have to adjust that all requests should go to <url>/api. In there change the following line (Marked with -) like the following (Marked with +) in /src/js/index.js:

- var provider = Ext.ux.xeditor.provider.AjaxProvider.forMiddleware(BLACKBOX_URL);
+ var provider = Ext.ux.xeditor.provider.AjaxProvider.forMiddleware(BUILD_MODE === "develop" ? BLACKBOX_URL: (location.origin + "/api"));

In addition, we need the possibility to determine the build mode used and also the possibility to configure the license key later. To achieve this add the BUILD_MODE and LICENSE env variable (Marked with +) to your /xepack.config.js:

// define environment variables
const env = {
+ 'BUILD_MODE': process.env.XEDITOR_BUILD_MODE || "develop",
+ 'LICENSE': process.env.XEDITOR_LICENSE || "",
// ...
};

Once this is done, you can add the folder env from this project to your project at top level. This folder now contains almost everything needed to build all Docker images. You will need a current version of docker and docker-compose on your system.

The folder env/middleware contains a package.json to define the version of the middleware for productive use and a Dockerfile to build the image for the middleware. The env/mock-server contains a small backend server which can be used for test/demo purposes. For a productive use this is not needed. The nginx configuration can be found in env/nginx. This will build a very simple nginx image to work as reverse proxy. Last but not least you will find the configuration for xeditor in env/xeditor.

You can build the image itself using the following commands. Make sure to replace the --build-arg values with your arguments. Each command is building one image:

# build the xeditor itself
docker build -t xeditor -f ./env/xeditor/Dockerfile \
--build-arg NPM_USER=YOUR_NPM_USERNAME \
--build-arg NPM_PASSWORD=YOUR_NPM_PASSWORD \
--build-arg XEDITOR_LICENSE_KEY=YOUR_LICENSE_KEY \
.
# Build your middleware server
docker build -t middleware -f ./env/middleware/Dockerfile \
--build-arg NPM_USER=YOUR_NPM_USERNAME \
--build-arg NPM_PASSWORD=YOUR_NPM_PASSWORD \
.
docker build -t nginx -f ./env/nginx/Dockerfile . # Optional - You can also add this part to your reverse proxy

Afterwards, this containers can be published. When publishing, please always make sure not to publish it publicly, but always privately (DockerHub requires a paid account for this).

To run Xeditor later you need to added a docker-compose.yml here and use the following code in there:

version: '3'
services:
middleware:
container_name: middleware
restart: unless-stopped
# image: middleware # the name of your "docker build -t" option. As soon you use "image", remove "build".
build:
context: ..
dockerfile: ./env/middleware/Dockerfile
args:
- NPM_USER="<YOUR_NPM_USER>"
- NPM_PASSWORD="<YOUR_NPM_PASSWORD>"
environment:
- XEDITOR_SERVER_HOST=mock-server # Your server host
- XEDITOR_SERVER_PORT=3001 # Your server port
mock-server: # Remove for production use
container_name: mock-server
restart: unless-stopped
build:
context: ..
dockerfile: ./env/mock-server/Dockerfile
args:
- NPM_USER="<YOUR_NPM_USER>"
- NPM_PASSWORD="<YOUR_NPM_PASSWORD>"
xeditor:
container_name: xeditor
restart: unless-stopped
# image: xeditor # the name of your "docker build -t" option. As soon you use "image", remove "build".
build:
context: ..
dockerfile: ./env/xeditor/Dockerfile
args:
- NPM_USER="<YOUR_NPM_USER>"
- NPM_PASSWORD="<YOUR_NPM_PASSWORD>"
- XEDITOR_LICENSE_KEY="<YOUR_LICENSE_KEY>"
nginx:
container_name: nginx
restart: unless-stopped
build:
context: ./nginx
ports:
- '7070:80' # Will be available under "http://localhost:7070"

Using this file you can now also start the editor locally by executing the command: docker-compose -f ./env/docker-compose.yml up.

If this is to be run on a server later, you can simply publish the image (or export/import as .tar.gz) and then comment out the build part and use the image part. Also, you can run this in the background using the -d argument.

MonoService

In the following, we will package all relevant Xeditor components in one Docker image. This has some advantages and disadvantages. We recommend using this for a very "simple" configuration, as the main advantage is simplicity. For later production use, we recommend using individual Docker images per service (AtomicServices).

We created a sample project for this case which can be found here.

In order to handle the requests correctly we are using the reverse proxy nginx. Nginx will pass all calls to <url>/api/** to the middleware server and tries to load static files for <url>/**. For this reason we have to adjust that all requests should go to <url>/api. In there change the following line (Marked with -) like following (Marked with +) in /src/js/index.js:

- var provider = Ext.ux.xeditor.provider.AjaxProvider.forMiddleware(BLACKBOX_URL);
+ var provider = Ext.ux.xeditor.provider.AjaxProvider.forMiddleware(BUILD_MODE === "develop" ? BLACKBOX_URL: (location.origin + "/api"));

In addition, we need the possibility to determine the build mode used and also to be able to configure the license key later. For this add the BUILD_MODE and LICENSE env variable (Marked with +) to your /xepack.config.js:

// define environment variables
const env = {
+ 'BUILD_MODE': process.env.XEDITOR_BUILD_MODE || "develop",
+ 'LICENSE': process.env.XEDITOR_LICENSE || "",
// ...
};

Once this is done, you can add the folder env from this project to your project at top level. This folder now contains almost everything needed for Docker. You will of course need a current version of docker and docker-compose on your system. The folder env/middleware contains only a package.json. This defines the version of the middleware for productive use. The env/mock-server contains a small backend server which can be used for test/demo purposes. For a productive use this is not to be used. This can be deactivated by an environment variable XEDITOR_ENABLE_MOCK_SERVER=false. The nginx configuration can be found in env/nginx. There is also a small NodeJs script that takes care of starting multiple services at once and crashes when one fails. This can be found in env/runner

In addition, there is a Dockerfile, this is the most important file for the Docker build. Here you define how the image has to look like. Here, everything from the project is copied into the image, then built productively and then linked with the other services in the next step, so that the runner can be started at the end, which in turn starts the middleware, the mock-server and the nginx.

You can build the image itself using the following command (Make sure to replace the --build-arg values with your arguments):

docker build -t xeditor-demo -f ./env/Dockerfile \
--build-arg NPM_USER=YOUR_NPM_USERNAME \
--build-arg NPM_PASSWORD=YOUR_NPM_PASSWORD \
--build-arg XEDITOR_LICENSE_KEY=YOUR_LICENSE_KEY \
.

Afterwards, this container can be published. When publishing, please always make sure not to publish it publicly, but always privately (DockerHub requires a paid account for this).

To run the Xeditor later I added a docker-compose.yml here. Using this file you can now also start the editor locally by executing the command: docker-compose -f ./env/docker-compose.yml up.

If this is to be run on a server later, you can simply publish the image (or export/import as .tar.gz) and then comment out the build part and use the image part. Also, you can run this in the background using the -d argument.