If you are installing Smile CDR in a Docker container, this page shows how you can also deploy NGINX and PostgreSQL in Docker containers and link all three together in a Docker stack.
The basic steps to creating a Smile CDR Docker stack are as follows:
The following sections will provide more details about each of the steps above.
Before proceeding with the configuration of the Docker containers that will make up the Smile CDR stack, it is a good idea to first review and/or complete a few preparatory steps.
If not already installed, the following link provides instructions for downloading and installing Docker Community Edition in a variety of environments including Windows, OSX, Linux and Cloud (e.g. AWS).
The port numbers will be needed for both the Smile CDR and NGINX configuration files and will also be referenced in the docker compose file used to build the Smile CDR stack.
When initializing PostgreSQL, you will want to specify:
This information will be needed for the Smile CDR configuration file and for environment settings used to initialize PostgreSQL in a Docker container.
Docker requires that you specify a single "context" path which contains all of the configuration and other files that are referenced when building the containers and stack. This path can have any name or location, but for the purposes of this document, it will be assumed that a folder named "docker" will be used for this purpose.
In this step we will prepare Docker to create a container for Smile CDR.
docker image load --input="/path/to/smilecdr-2019.05.R01-image.tar.bz2"
The Smile CDR image is delivered with a default cdr-config-Master.properties configured to use a H2 database and http protocol. As such an updated properties file will be required for use in the Smile CDR container.
Copy the default cdr-config-Master.properties file to the "docker" context folder, renaming it to cdr-config-Master-postgresql.properties. Modify the property values as shown below:
module.clustermgr.config.db.driver =POSTGRES_9_4
module.persistence.config.db.driver =POSTGRES_9_4
module.clustermgr.config.db.url =jdbc:postgresql://postgresdb:5432/cdr
module.persistence.config.db.url =jdbc:postgresql://postgresdb:5432/cdr
module.clustermgr.config.db.username =cdr
module.clustermgr.config.db.password =somepassword
module.persistence.config.db.username =cdr
module.persistence.config.db.password =somepassword
module.fhir_endpoint.config.port =8000
module.fhir_endpoint.config.base_url.fixed =https://localhost:8000
module.admin_json.config.port =9000
module.admin_web.config.port =9100
module.fhirweb_endpoint.config.port =8001
module.smart_auth.config.port =9200
module.smart_app_demo_host.config.port =9201
Create a file named "Dockerfile" in the "docker" context folder with the following contents:
# Use base Smile CDR image as parent image
FROM smilecdr
# Set working directory
WORKDIR /home/smile/smilecdr/classes
# Copy the customized properties file from the context folder to the WORKDIR in the container.
copy ./cdr-config-Master-postgresql.properties ./cdr-config-Master.properties
The above Dockerfile will essentially instruct Docker to create a new image based on the "smilecdr" image loaded previously copying the properties file from the docker context folder to the "/home/smile/smilecdr/classes" folder inside the new image.
The ssl folder will be used to hold certificate, key and Diffie-Hellman group files that will be used by NGINX for TLS/SSL encryption.
When configuring a secure proxy, NGINX requires a certificate and key file in PEM format.
There are multiple ways to create a certificate and key file. You can find instructions on this page for creating a certificate and key for Ubuntu environments using letsencrypt.
Note the names of the certificate and key files and copy the files to the docker/ssl folder.
For additional security, also create a Diffie-Hellman group file and copy this to the docker/ssl folder. Note the name of the resulting file.
$ sudo mkdir -p /etc/nginx/ssl/
$ sudo openssl dhparam -out /path/to/docker/ssl/dhparams.pem 2048
Create a new file in the docker folder named "proxy.conf" and add the following (replace [fullchain.pem]
, [privkey.pem]
, and [dhparams.pem]
with your actual certificate file, key file and Diffie-Hellman group file names respectively):
server_name localhost;
ssl_certificate /etc/nginx/ssl/[fullchain.pem];
ssl_certificate_key /etc/nginx/ssl/[privkey.pem];
ssl_stapling on;
ssl_stapling_verify on;
ssl_dhparam /etc/nginx/ssl/[dhparams.pem];
ssl_ciphers 'kEECDH+ECDSA+AES128 kEECDH+ECDSA+AES256 kEECDH+AES128 kEECDH+AES256 kEDH+AES128 kEDH+AES256 DES-CBC3-SHA +SHA !aNULL !eNULL !LOW !kECDH !DSS !MD5 !EXP !PSK !SRP !CAMELLIA !SEED !3DES';
access_log /var/log/nginx/access.log;
Create a new file in the docker folder, "smilecdr_server.conf", and add the following:
#######################################
# Redirect http to https
#######################################
server {
server_name localhost;
listen 80;
include proxy.conf;
return 301 https://$host$request_uri;
}
#######################################
# FHIR Endpoint
#######################################
server {
server_name localhost;
listen 8000 ssl default_server;
include proxy.conf;
location / {
proxy_set_header Host $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-Host $host:8000;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Port 8000;
proxy_set_header X-Forwarded-Proto https;
proxy_pass http://smilecdr:8000/;
}
}
#######################################
# FHIRWeb Console
#######################################
server {
server_name localhost;
listen 8001 ssl default_server;
include proxy.conf;
location / {
proxy_set_header Host $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-Host $host:8001;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Port 8001;
proxy_set_header X-Forwarded-Proto https;
proxy_pass http://smilecdr:8001/;
}
}
#######################################
# Web Admin Console
#######################################
server {
server_name localhost;
listen 443 ssl default_server;
include proxy.conf;
location / {
proxy_set_header Host $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-Host $host:443;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header X-Forwarded-Proto https;
proxy_pass http://smilecdr:9100/;
}
}
server {
server_name localhost;
listen 9100 ssl default_server;
include proxy.conf;
location / {
proxy_set_header Host $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-Host $host:9100;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Port 9100;
proxy_set_header X-Forwarded-Proto https;
proxy_pass http://smilecdr:9100/;
}
}
#######################################
# JSON Admin API
#######################################
server {
server_name localhost;
listen 9000 ssl default_server;
include proxy.conf;
location / {
proxy_set_header Host $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-Host $host:9000;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Port 9000;
proxy_set_header X-Forwarded-Proto https;
proxy_pass http://smilecdr:9000/;
}
}
#######################################
# SMART OAuth2 / OpenID Connect Server
#######################################
server {
server_name localhost;
listen 9200 ssl default_server;
include proxy.conf;
location / {
proxy_set_header Host $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-Host $host:9200;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Port 9200;
proxy_set_header X-Forwarded-Proto https;
proxy_pass http://smilecdr:9200/;
}
}
#######################################
# SMART App Host
#######################################
server {
server_name localhost;
listen 9201 ssl default_server;
include proxy.conf;
location / {
proxy_set_header Host $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-Host $host:9201;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Port 9201;
proxy_set_header X-Forwarded-Proto https;
proxy_pass http://smilecdr:9201/;
}
}
NOTES:
In the docker folder create a Dockerfile for NGINX named "Dockerfile_NGINX" with contents set as shown below. This Dockerfile will be used to create a container for NGINX with the configurations created in the previous steps.
# Extend nginx image
FROM nginx
# Set the default NGINX folder as working directory
WORKDIR /etc/nginx
# Copy ssl files to nginx folder
COPY ./ssl ./ssl
# Copy common settings to nginx folder
COPY ./proxy.conf ./
# Copy server block file to sites-enabled folder
COPY ./smilecdr_server.conf ./conf.d/default.conf
# Make Smile CDR ports available outside this container
EXPOSE 80 443 8000 8001 9000 9100 9200 9201
NOTE: Review and update the port numbers listed in the "EXPOSE" instruction if necessary. The port numbers below are based on the out-of-the-box configuration and may not be applicable to your configuration.
Create a shell script, init_postgresdb.sh, in the docker folder which will be used to create the CDR database(s), userid(s) and password(s) in PostgreSQL as shown below.
#!/bin/bash
set -e
#POSTGRES_USER, POSTGRES_DB and POSTGRES_PASSWORD are environment variables defined by the parent postgres image.
#POSTGRES_USER is the DB superuser, POSTGRES_PASSWORD is superuser's password and POSTGRES_DB is the default DB.
#POSTGRES_USER and POSTGRES_DB both default to "postgres". POSTGRES_PASSWORD is blank by default.
#All three variables can be overridden by environment settings.
#The script below creates only a single DB for Smile CDR with name $CDR_DB_NAME with a single user ID and password "$CDR_USER_LOGIN" and "$CDR_PASSWORD"
#Additional CREATE and GRANT statements can be included if additional databases and/or user ids are required.
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<- EOSQL
CREATE ROLE $CDR_USER LOGIN password '$CDR_PASSWORD';
CREATE DATABASE $CDR_DB_NAME;
EOSQL
# Starting Postgres 15, users needs explicit permission to public SCHEMA.
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$CDR_DB_NAME" <<- EOSQL
GRANT ALL PRIVILEGES ON DATABASE $CDR_DB_NAME TO $CDR_USER;
GRANT ALL PRIVILEGES ON SCHEMA public TO $CDR_USER;
EOSQL
Values for the environment variables will be set when the Docker stack is launched.
In the docker folder create a Dockerfile for PostgreSQL named "Dockerfile_PostgreSQL" with contents set as shown below. This Dockerfile will be used to create a container for PostgreSQL initialized using the shell script above.
# Extend the postgres image provided by docker hub
FROM postgres:alpine
ADD ./init_postgresdb.sh /docker-entrypoint-initdb.d/init_postgresdb.sh
In the docker folder create a Docker compose file named "compose_smilecdr.yml" as follows:
version: "3.7"
services:
smilecdr:
container_name: smileCDR
build:
context: .
image: smilecdr_pg
depends_on:
- postgresdb
volumes:
- log:/home/smile/smilecdr/log
- mq:/home/smile/smilecdr/activemq-data
- lucene:/home/smile/smilecdr/database/lucene_fhir_persistence
restart: unless-stopped
postgresdb:
container_name: postgres_cdr
build:
context: .
dockerfile: Dockerfile_PostgreSQL
image: postgres_cdr
ports:
- "5432:5432"
environment:
- POSTGRES_USER=${DB_SUPER_USER_ID}
- POSTGRES_PASSWORD=${DB_SUPER_USER_PASSWORD}
- CDR_DB_NAME=${DB_CDR_NAME}
- CDR_USER=${DB_CDR_USERID}
- CDR_PASSWORD=${DB_CDR_PASSWORD}
volumes:
- db:/var/lib/postgresql/data
restart: unless-stopped
nginx:
container_name: nginx_cdr
build:
context: .
dockerfile: Dockerfile_NGINX
image: nginx_cdr
depends_on:
- smilecdr
ports:
- "80:80"
- "443:443"
- "8000:8000"
- "9000:9000"
- "9100:9100"
- "8001:8001"
- "9200:9200"
- "9201:9201"
restart: unless-stopped
volumes:
db:
mq:
log:
lucene:
NOTES:
$ export DB_SUPER_USER_ID=postgres
$ export DB_SUPER_USER_PASSWORD=MySecretPassword
$ export DB_CDR_NAME=cdr
$ export DB_CDR_USERID=cdr
$ export DB_CDR_PASSWORD=somepassword
docker-compose -f /path/to/docker/compose_smilecdr.yml -p smilecdr up -d
docker-compose -f /path/to/docker/compose_smilecdr.yml -p smilecdr logs -f smilecdr
docker-compose -f /path/to/docker/compose_smilecdr.yml -p smilecdr stop
docker-compose -f /path/to/docker/compose_smilecdr.yml -p smilecdr down --rmi all -v