Deploying Simplicité with Docker images tutorial
For this tutorial we use an out-of-the-box AlmaLinux 8, 9 or 10 (or legacy CentOS 7 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.
- AlmaLinux 8, 9 or 10
- CentOS 7
- Debian
sudo dnf -y update && sudo dnf clean all
sudo reboot
sudo yum -y update && sudo yum clean all
sudo reboot
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 :
- AlmaLinux 8, 9 or 10
- CentOS 7
- Debian
sudo dnf -y install firewalld && sudo dnf clean all
sudo systemctl enable firewalld
sudo systemctl start firewalld
sudo yum -y install firewalld && sudo yum clean all
sudo systemctl enable firewalld
sudo systemctl start firewalld
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.
- AlmaLinux 8, 9 or 10
- CentOS 7
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
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
Add these useful aliases to ~/.bashrc:
- AlmaLinux 9 or 10
- AlmaLinux 8
- CentOS 7
cat << EOF >> .bashrc
alias vi=vim
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias dir='ls -alF'
alias d='podman'
alias di='podman images'
alias dp='podman ps --all'
alias dv='podman volume'
alias dc='podman compose'
EOF
. .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 docker compose'
EOF
. .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'
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.
- AlmaLinux 8, 9 or 10
- CentOS 7
- Debian
sudo dnf -y install postgresql && sudo dnf clean all
sudo dnf -y install mariadb && sudo dnf clean all
sudo yum -y install postgresql && sudo yum clean all
sudo yum -y install mariadb && sudo yum clean all
sudo apt install postgresql-client
sudo apt install mariadb-client
Docker
- AlmaLinux 9 or 10
- AlmaLinux 8
- CentOS 7
- Debian
Here we install the distribution's Podman
sudo dnf -y install podman-docker.noarch
sudo podman --version
loginctl enable-linger
If you prefer to use docker instead of podman, you can but you should do
sudo touch /etc/containers/nodocker to avoid the annoying warning.
Here we install Docker CE (Community edition)
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
Here we install the distribution's Docker
sudo yum -y install docker && sudo yum clean all
sudo systemctl enable docker
sudo systemctl start docker
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
Sign-in to our private Docker registry
- AlmaLinux 9 or 10
- AlmaLinux 8 or CentOS 7 or Debian
podman login registry.simplicite.io
sudo docker login registry.simplicite.io
The images' prefix is registry.simplicite.io/ (e.g. registry.simplicite.io/platform:6-latest).
To test if everything works fine you can try starting a Tomcat-only ephemeral container with:
- AlmaLinux 9 or 10
- AlmaLinux 8 or CentOS 7 or Debian
podman run -it --rm -p 80:8080 registry.simplicite.io/server:<tag>
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
- AlmaLinux 9 or 10
- AlmaLinux 8 or Debian
- CentOS 7
sudo dnf -y install epel-release && sudo dnf -y install podman-compose.noarch
To avoid the annoying warning when running podman compose you should add
export PODMAN_COMPOSE_WARNING_LOGS=false to your .bashrc
The compose plugin is installed by default.
sudo yum -y install epel-release && sudo yum -y install docker-compose && sudo yum clean all
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.
Alternatively you can add --project-name=myinstance to all Docker compose` command invocations.
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:
If you are planning to use a reverse proxy and/or to expose simplicite in HTTPS, make sure you use the appropriate 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 the simplicite is using the name of the db service as hostname.
If you are planning to use a reverse proxy and/or to expose simplicite in HTTPS, make sure you use the appropriate port mapping and configuration see this document for more details.
MySQL database (2 containers)
services:
db:
image: mysql:latest
restart: unless-stopped
container_name: myinstance-mysql-database
command: --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 the simplicite is using the name of the db service as hostname.
If you are planning to use a reverse proxy and/or to expose simplicite in HTTPS, make sure you use the appropriate 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 redistributable 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):
- AlmaLinux 9 or 10
- AlmaLinux 8 or Debian
- CentOS 7
podman compose up [-d]
sudo docker compose up [-d]
sudo docker-compose up [-d]
To stop the container(s):
- AlmaLinux 9 or 10
- AlmaLinux 8
- CentOS 7 or Debian
podman compose down
sudo docker compose down
sudo docker-compose down
To update the images (after stopping the containers(s)):
- AlmaLinux 9 or 10
- AlmaLinux 8 or Debian
- CentOS 7
podman compose pull
sudo docker compose pull
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 only
(i.e. remove the -80:8080 and add - 127.0.0.1:8443:8443 in the ports section of your deployment descriptors).
As explained in this document the 8080 port is for an HTTP endpoint of the reverse proxy
and the 8443 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 the 8080 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 the simplicite service as hostname
and the secured 8443 port (not the unsecured 8080 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=trueenvironment variable. - it can be done (and in most case it is preferable) 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 certificate 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.conffile. -
Create a
.well-knowndir:mkdir .well-known -
Add a new volume mapping to the
simpliciteservice in thedocker-compose.ymlfile:(...)
- ./.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.conffile. -
Change the certificate and key volume mappings in the
docker-compose.ymlfile to:(...)
- /etc/letsencrypt/live/<myhostname>/fullchain.pem:/etc/ssl/server.crt
- /etc/letsencrypt/live/<myhostname>/privkey.pem:/etc/ssl/server.key
(...) -
Restart
Thee above last 3 steps are not required when you renew the certificate by sudo certbot renew.
Connecting to a running container
List the running containers with:
- AlmaLinux 9 or 10
- Almalinux 8 or CentOS 7 or Debian
podman ps
sudo docker ps
Look for the container ID or name of the Simplicité container and execute a bash shell into this container:
- AlmaLinux 9 or 10
- Almalinux 8 or CentOS 7 or Debian
podman exec -it <container ID or name> bash
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
Look for the container ID or name of the Simplicité container and execute standard Docker logs commands such as:
- AlmaLinux 9 or 10
- Almalinux 8 or CentOS 7 or Debian
podman logs -f <container ID or name>
sudo docker logs -f <container ID or name>
Deploying wih a license key
See Auto Setup
Deploying with business modules
See Auto Setup