Deploying Simplicité with Docker images tutorial
For this tutorial we use an out-of-the-box CentOS 7, CentOS 8+/AlmaLinux/RockyLinux or Debian host but this can be transposed to any other host OS.
By following the steps below you should have an easily-maintainable production-grade deployment of Simplicité up and running in a few minutes.
Installation
System upgrade
This step is required to make sure your host system is up-to-date.
Update system on CentOS 7:
sudo yum -y update && sudo yum clean all
sudo reboot
Update system on CentOS 8+/AlmaLinux/RockyLinux:
sudo dnf -y update && sudo dnf clean all
sudo reboot
Update system on Debian:
sudo apt-get update && sudo apt-get upgrade
sudo reboot
Firewall setup
Although it is highly recommended, this step is not required if you have an external firewall which already filters the access to your host.
Install and enable firewall on CentOS 7:
sudo yum -y install firewalld && sudo yum clean all
sudo systemctl enable firewalld
sudo systemctl start firewalld
Install and enable firewall on CentOS 8+/AlmaLinux/RockyLinux:
sudo dnf -y install firewalld && sudo dnf clean all
sudo systemctl enable firewalld
sudo systemctl start firewalld
Install firewall on Debian:
sudo apt update
sudo apt -y install firewalld
Configure firewall:
sudo firewall-cmd --add-service=ssh --permanent
sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --add-service=https --permanent
sudo firewall-cmd --remove-service=cockpit --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --list-all
Optional: Install other useful packages
This step is not required but provides various useful tools and aliases on your host.
Install other useful packages on CentOS 7:
sudo yum -y install vim-enhanced git wget curl zip unzip && sudo yum clean all
sudo yum -y install epel-release && sudo yum -y install certbot htop && sudo yum clean all
Install other useful packages on CentOS 8+/AlmaLinux/RockyLinux:
sudo dnf -y install vim-enhanced git wget curl zip unzip && sudo dnf clean all
sudo dnf -y install epel-release && sudo dnf -y install certbot htop && sudo dnf clean all
Add these useful aliases to ~/.bashrc
:
cat << EOF >> .bashrc
alias vi=vim
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias dir='ls -alF'
alias d='sudo docker'
alias di='sudo docker images'
alias dp='sudo docker ps --all'
alias dv='sudo docker volume'
alias dc='sudo /usr/bin/docker-compose'
alias k='sudo kubectl'
EOF
. .bashrc
Optional: Install database clients packages
This step is not required if you don't plan to connect to the deployed databases from your host.
Install database clients on CentOS 7:
sudo yum -y install mariadb postgresql && sudo yum clean all
Install database clients on CentOS 8+/AlmaLinux/RockyLinux:
sudo dnf -y install mariadb postgresql && sudo dnf clean all
Install database clients on Debian:
sudo apt install mariadb-client postgresql-client
Docker
Install Docker on CentOS 7:
sudo yum -y install docker && sudo yum clean all
sudo systemctl enable docker
sudo systemctl start docker
Install Docker on CentOS 8+/AlmaLinux/RockyLinux:
sudo dnf -y install 'dnf-command(config-manager)'
sudo dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo
sudo dnf -y install docker-ce && sudo dnf clean all
sudo docker --version
sudo systemctl enable docker
sudo systemctl start docker
Install Docker on Debian:
sudo apt update && sudo apt-get install apt-transport-https ca-certificates curl gnupg2 software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
sudo apt update && sudo apt install docker-ce
sudo docker --version
sudo systemctl status docker
Note: By default Docker is allowed to change the firewall rules to open exposed ports. To disable this default behavior you need to edit
/usr/lib/systemd/system/docker.service
cartridge file and add--iptables=false
(or similar if usingnftables
) to theExecStart
command.
Sign-in to our private Docker registry:
sudo docker login https://registry.simplicite.io
Note: The images' prefix is
registry.simplicite.io/
(e.g.registry.simplicite.io/platform:5-x
).
To test if everything works fine you can try starting a Tomcat-only ephemeral container with:
sudo docker run -it --rm -p 80:8080 registry.simplicite.io/server:<tag>
Where <tag>
is one of the available tags. E.g. 6-latest
= 6
or 5-latest
= 5
, etc.
Docker compose
Install the Docker compose tool on CentOS 7:
sudo yum -y install epel-release && sudo yum -y install docker-compose && sudo yum clean all
Install the Docker compose tool on CentOS 8+/AlmaLinux/RockyLinux or Debian:
Check the latest X.Y.Z
version on GitHub.
sudo curl -L "https://github.com/docker/compose/releases/download/vX.Y.Z/docker-compose-$(uname -s)-$(uname -m)" -o /usr/bin/docker-compose
sudo chmod +x /usr/bin/docker-compose
sudo docker-compose --version
Docker compose descriptors
The sample docker-compose.yml
files below are using different databases.
Create a folder for your instance (e.g. myinstance
), all following files must be created in this folder.
Note: Alternatively you can add
--project-name=myinstance
to alldocker-compose
command invokations.
Embedded HSQL database (1 container)
services:
simplicite:
image: registry.simplicite.io/platform:<tag>
restart: unless-stopped
container_name: myinstance-hsqldb
ports:
- 80:8080
volumes:
- myinstance-hsqldb-db:/usr/local/tomcat/webapps/ROOT/WEB-INF/db
- myinstance-hsqldb-dbdoc:/usr/local/tomcat/webapps/ROOT/WEB-INF/dbdoc
- myinstance-hsqldb-git:/usr/local/tomcat/webapps/ROOT/WEB-INF/git
volumes:
myinstance-hsqldb-db:
myinstance-hsqldb-dbdoc:
myinstance-hsqldb-git:
Warning: if you are planning to use a reverse proxy and/or to expose simplicite in HTTPS, make sure you use the apppropriate port mapping and configuration see this document for more details.
MySQL database (2 containers)
services:
db:
image: mysql:latest
restart: unless-stoped
container_name: myinstance-mysql-database
command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
environment:
MYSQL_ROOT_PASSWORD: "simplicite"
MYSQL_DATABASE: "simplicite"
MYSQL_USER: "simplicite"
MYSQL_PASSWORD: "simplicite"
# ZZZ Uncomment these 2 lines only if you want to access to the database from the host machine ZZZ
#ports:
# - 127.0.0.1:3306:3306
volumes:
- myinstance-mysql-db:/var/lib/mysql
simplicite:
image: registry.simplicite.io/platform:<tag>
restart: unless-stopped
container_name: myinstance-mysql-webapp
environment:
DB_SETUP: "true"
DB_VENDOR: "mysql"
DB_HOST: db
DB_USER: "simplicite"
DB_PASSWORD: "simplicite"
DB_NAME: "simplicite"
DB_WAIT: 10
ports:
- 80:8080
volumes:
- myinstance-mysql-git:/usr/local/tomcat/webapps/ROOT/WEB-INF/git
depends_on:
- db
volumes:
myinstance-mysql-db:
myinstance-mysql-git:
Note: that the
DB_HOST
environment variable of thesimplicite
is using the name of thedb
service as hostname.
Warning: if you are planning to use a reverse proxy and/or to expose simplicite in HTTPS, make sure you use the apppropriate port mapping and configuration see this document for more details.
PostgreSQL database (2 containers)
services:
db:
image: postgres:latest
restart: unless-stopped
container_name: myinstance-postgres-database
environment:
POSTGRES_USER: "simplicite"
POSTGRES_PASSWORD: "simplicite"
POSTGRES_DB: "simplicite"
# ZZZ Uncomment these 2 lines only if you want to access to the database from the host machine ZZZ
#ports:
# - 127.0.0.1:5432:5432
volumes:
- myinstance-postgres-db:/var/lib/postgresql/data
simplicite:
image: platform:<tag>
restart: unless-stopped
container_name: myinstance-postgres-webapp
environment:
DB_SETUP: "true"
DB_VENDOR: "postgresql"
DB_HOST: db
DB_USER: "simplicite"
DB_PASSWORD: "simplicite"
DB_NAME: "simplicite"
DB_WAIT: 10
ports:
- 80:8080
volumes:
- myinstance-postgres-git:/usr/local/tomcat/webapps/ROOT/WEB-INF/git
depends_on:
- db
volumes:
myinstance-postgres-db:
myinstance-postgres-git:
Note: that the
DB_HOST
environment variable of thesimplicite
is using the name of thedb
service as hostname.
Warning: if you are planning to use a reverse proxy and/or to expose simplicite in HTTPS, make sure you use the apppropriate port mapping and configuration see this document for more details.
Oracle or SQLServer database
For Oracle/SQLServer databases you need to build a custom Docker image in which you add the appropriate Oracle/SQLServer client and JDBC driver (for these two databases these components are not redistribuables and must correspond to the database server version you are using).
Check this GitHub repository for examples.
Start/stop/upgrade
To start the container(s):
sudo docker-compose up [-d]
To stop the container(s):
sudo docker-compose down
To update the images (after stopping the containers(s)):
sudo docker-compose pull
Optional: Add an SSL-enabled NGINX reverse proxy
To add an NGINX reverse proxy to expose your instances over SSL do the following changes
to the docker-compose.yml
file:
services:
(...)
nginx:
image: nginx:latest
restart: unless-stopped
container_name: myinstance-reverseproxy
ports:
- 80:80
- 443:443
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./server.crt:/etc/ssl/server.crt
- ./server.key:/etc/ssl/server.key
(...)
And, of course, remove the exposed 80
port from the simplicite
and expose the 8443
locally olny
(i.e. remove the -80:8080
and add - 127.0.0.1:8443:8443
in the ports
section of your deployment descriptors).
Warning: As explained in this document the
8080
port is for an HTTP enpoint of the reverse proxy and the8443
port is for an HTTPS endpoint of the reverse proxy. If you don't use the right port for the right usage (typically if you misuse the8080
for an HTTPS endpoint of the reverse proxy) it will result in unexpected behaviors
Where nginx.conf
is like:
events {
}
http {
gzip on;
gzip_types text/plain text/css text/javascript text/xml application/json application/javascript application/x-javascript;
server_names_hash_bucket_size 128;
client_max_body_size 0;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
location / {
return 301 https://$http_host$request_uri;
}
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name _;
ssl_certificate "/etc/ssl/server.crt";
ssl_certificate_key "/etc/ssl/server.key";
location / {
# Uncomment this block if you need to enable CORS
#if ($request_method = 'OPTIONS') {
# add_header Access-Control-Allow-Origin $http_origin;
# add_header Access-Control-Allow-Credentials true;
# add_header Access-Control-Allow-Headers Content-Type,Authorization,X-Requested-With,X-HTTP-Method-Override,X-Simplicite-Authorization;
# add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,HEAD,OPTIONS;
# add_header Access-Control-Max-Age 1728000;
# add_header Content-Type text/plain;
# add_header Content-Length 0;
# return 204;
#}
if ($request_method ~ '(GET|POST)') {
# Uncomment these 3 lines if you need to enable CORS
# add_header Access-Control-Allow-Origin $http_origin always;
# add_header Access-Control-Allow-Credentials true always;
# Uncomment these 3 lines if you need to enable CSP and other security directives (make sure to add specific directives for external services your application may use e.g. Google Maps, ..)
# add_header Content-Security-Policy "default-src 'self'; img-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob:; style-src 'self' 'unsafe-inline'; font-src 'self' data:" always;
# add_header X-Frame-Options SAMEORIGIN always;
# add_header X-XSS-Protection "1; mode=block" always;
}
proxy_redirect off;
proxy_buffering off;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_pass http://simplicite:8443;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}
Note: that the
proxy_pass
statement is using the name of thesimplicite
service as hostname and the secured8443
port (not the unsecured8080
port) as explained above using the right port here is mandatory to avoid unexpected behaviors
The mapped /etc/sslserver.crt
and /etc/sslserver.key
are the SSL certificate and corresponding key
that you have obtained/bought for your hostname(s).
GZIP compression
In all cases you should configure GZIP compression. Depending on your deployment strategy it can be done at different level.
- it can be done directly by the Tomcat of the Simplicité container using the
GZIP=true
environment variable. - it can be done (and in most case it is preferrable) at the reverse proxy level
(see, for instance, the
gzip on;
statement in the above NGINX configuration file)
Websockets
Websockets-based features (such as pushing servers logs to the browser's console) can be totally inhibited using the WEBSOCKETS=false
.
This may be required on some networks (e.g. with old proxies) where websockets are filtered or forced closed after a given timeout.
Java compiler
The Java compiler can be totally inhibited using the COMPILER=false
.
This may be required in some particular cases (e.g. security reasons).
Note that this means that any Java compiled class must be provided otherwise, e.g. by mounting/copying externally built JARs in the WEB-INF/lib
of the webapp.
Generate a self-signed certificate
You can generate them as a self-signed certficate with the following commands:
openssl genrsa -des3 -out server.key 4096
openssl req -new -key server.key -out server.csr
cp server.key server-pwd.key
openssl rsa -in server-pwd.key -out server.key
openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt
Note: a self-signed certificate will generate warnings in your browser
Use a LetsEncrypt certificate
You can obtain a free signed certificate from the LetsEncrypt service, there are some steps to go thru:
- Add this to the HTTP server config in
nginx.conf
(before thelocation / {...}
block):
(...)
location ^~ /.well-known/acme-challenge/ {
root /usr/local/tomcat/webapps/ROOT;
}
(...)
-
Comment the HTTPS config in the
nginx.conf
file. -
Create a
.well-known
dir:
mkdir .well-known
- Add a new volume mapping to the
simplicite
service in thedocker-compose.yml
file:
(...)
- ./.well-known:/usr/local/tomcat/webapps/ROOT/.well-known
(...)
-
Restart
-
Request the LetEncrypt certificate by:
sudo certbot certonly --webroot -w . -d <myhostname>
-
Uncomment the HTTPS config in the
nginx.conf
file. -
Change the certificat and key volume mappings in the
docker-compose.yml
file to:
(...)
- /etc/letsencrypt/live/<myhostname>/fullchain.pem:/etc/ssl/server.crt
- /etc/letsencrypt/live/<myhostname>/privkey.pem:/etc/ssl/server.key
(...)
- Restart.
Note: the above step are not required when you renew the certificate by
sudo certbot renew
.
Connecting to a running container
List the running containers with:
sudo docker ps
Look for the container ID or name of the Simplicité container and execute a bash shell into this container:
sudo docker exec -it <container ID or name> bash
Inside the container the Tomcat base folder is /usr/local/tomcat
.
Reviewing logs of a running container
List the running containers with:
sudo docker ps
Look for the container ID or name of the Simplicité container and execute standard Docker logs commands such as:
sudo docker logs -f <container ID or name>
Deploying wih a license key
See Auto Setup
Deploying with business modules
See Auto Setup