In order to easily package, ship, and run applications as lightweight, portable, and self-sufficient as possible, there is Docker. Docker allows us to run applications virtually everywhere. Therefore this blog post gives some guidance on how Thinkwise applications can be containerized.
There are numerous approaches in how you might want to set up your Docker environment, so we will mainly focus on:
- Running Universal independently;
 - Running Indicium independently;
 - Running Indicium and Universal together.
 
At the end of this post, we will uncover our future plans and what we're currently researching/developing.
Prerequisites
To follow along, you'll need to have:
- Docker installed on your desktop or server (for Linux containers);
 - Universal downloaded from TCP;
 - Indicium downloaded from TCP.
 
Please note that for certain scenario’s with Docker you’ll need a license. The Docker FAQ is a good source to read upon these questions.
Scenario's
The scenarios covered here can be followed separately.
1. Running Universal Independently
In this scenario you might want to serve Universal from a Docker container. The steps to accomplish this are:
- Create a new folder 
universal; - Open the new folder 
universal; - Create a new folder 
app; - Unzip the downloaded Universal from TCP in the 
appfolder; - Adjust the 
app/config.jsonwith the Indicium URL (e.g.http://localhost/indicium); - 	
Create a
Dockerfilein the createduniversalfolder;# ./universal/
FROM nginx:latest
EXPOSE 80
WORKDIR /app
COPY ./app /usr/share/nginx/html - 	
Run from the command-line, which will build the Docker image with Universal included:
docker build ./ -t universal:latest - 	
Run from the command-line, which will run the Docker container with the Universal image, You may want to change the port mapping based on your operating system.
docker run -p 80:80 universal:latest 
Now Universal will be running on http://localhost.
2. Running Indicium independently
We can also run Indicium in a Docker environment, with the following steps:
- Create a new folder 
indicium; - Open the new folder 
indicium; - Create a new folder 
app; - Unzip the downloaded Indicium from TCP in the 
appfolder; - Create a 
Dockerfilein the createdindiciumfolder;# ./indicium/
FROM mcr.microsoft.com/dotnet/aspnet:6.0
ENV ASPNETCORE_URLS http://+:5000
EXPOSE 5000
WORKDIR /app
COPY ./app /app/
CMD dotnet Indicium.dll - 	
Adjust the
app/appsettings.jsonwith the necessary database information; - 	
Run from the command-line, which will build the Docker image with Indicium included:
docker build ./ -t indicium:latest - 	
Run from the command-line, which will run the Docker container with the Indicium image.
docker run -p 5000:5000 indicium:latest 
Now Indicium will be running on http://localhost:5000.
3. Running Universal and Indicium together
At last, we will cover how you can run Universal and Indicium together from separate Docker containers. This setup makes Universal available at the root and Indicium as a subfolder (/indicium), which will be reversed proxied to the actual running container.
- Create a new folder 
universal; - Open the new folder 
universal; - Create a new folder 
app; - Unzip the downloaded Universal from TCP in the 
appfolder; - Adjust the 
app/config.jsonwith the Indicium URL; - Create a 
Dockerfilein the createduniversalfolder;# ./universal/
FROM nginx:latest
EXPOSE 80
WORKDIR /app
COPY ./app /usr/share/nginx/html
COPY ./nginx.conf /etc/nginx/nginx.conf - Create a 
nginx.conffileuser nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
gzip on;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name localhost;
location / {
root /var/www/html/universal;
index index.html index.htm;
}
location /indicium/ {
proxy_pass http://indicium:5000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
} - Create a new folder 
indicium; - Open the new folder 
indicium; - Create a new folder 
app; - Unzip the downloaded Indicium from TCP in the 
appfolder; - Create a 
Dockerfilein the just createdapp/folder;# ./indicium/
FROM mcr.microsoft.com/dotnet/aspnet:6.0
ENV ASPNETCORE_URLS http://+:5000
EXPOSE 5000
WORKDIR /app
COPY ./app /app/
CMD dotnet Indicium.dll - Adjust the 
app/appsettings.jsonwith the necessary database information; - Append the following snippet to the 
app/appsettings.jsonto setup the ReverseProxy and make it available at/indicium."ReverseProxy": {
"Enabled": true,
"ExternalPathBase": "/indicium",
"AllowedHeaders": [
"XForwardedHost",
"XForwardedProto"
]
}, - 	
Run from the command-line to build the Universal image:
docker build ./universal -t universal:latest - 	
Run from the command-line to build the Indicium image:
docker build ./indicium -t indicium:latest - 	
Run from the command-line to run both Universal and Indicium:
docker run --name indicium -h indicium -p 5000:5000 indicium:latest
docker run --name universal -h universal --link indicium -p 80:80 universal:latest 
Congrats, you'll now have Universal available at http://localhost and have Indicium available at http://localhost/indicium.
Future plans
In the future we want to make Universal and Indicium available as images via a Container Registry, so it will no longer be necessary to build them on your own. Also, we're researching multiple methods for making the SQLServer available. For allowing the databases to run in containers without compromising on ease of back-up and upgrades.
