Creating your own FHIR Server: revised

So I’ve written an earlier post describing how you can use the excellent HAPI FHIR engine to host your own FHIR server. This used the CLI (Command Line Interface) tool, and has worked well for me in the past – for example most of the clinFHIR modules have used this as the back end storage.

However, this is definitely only useful for development and testing, and recently there have been some issues running the more recent versions of the CLI so I decided to take a closer look at other options – in particular using Docker to host the server.

For those unfamiliar with Docker (as I was at the start of this journey), it’s a technology for creating light weight containers that host some particular application along with its direct dependencies in a way that makes them simple to set up and deploy at scale. Similar to Virtual Servers, though use the hosts operating system rather than a complete virtualized system.

A Container is created from an Image – kind of like a template that defines what’s in the Container – so you can think of a Container as an instantiation of an Image as we’ll see below.

What’s especially nice is that there is a freely available online registry of container images that people have created that you can just download and use. Of course, you can create your own – or extend the publicly available containers, but the registry makes it trivial to deploy containerized apps (as they are called).

There’s a ton of information online about Docker, so I won’t go into it any further here. The following instructions assume that you have Docker set up on your machine of choice (which can be Linux, Windows or Mac).

Let’s take the simplest case – we just want to set up a FHIR server on your local machine. The following command will do the trick.

docker container run -dit -p 8080:8080 –name myHapiServer hapiproject/hapi:latest

This will download the latest version of the HAPI server (technically the JPA Starter kit maintained by the HAPI project), and start the server using the command line parameters you supply. (No need to download Java – everything needed is in the Image). Speaking of those parameters:

  • “docker container run” instructs the docker run-time to create a new container
  • -dit means to start the container in the background (so you don’t see the console output on the screen) but support an interactive terminal if needed. Actually, only the ‘-d’ (detached) is needed
  • -p 8080:8080 is a mapping command that exposes the HAPI server endpoint from inside the container to the outside world. Without this parameter, you wouldn’t be able to access the server from outside the container
  • –name sets the container name
  • hapiproject/hapi:latest describes the image that we want to use to create the container.

Once the Container has been created, you can see it running using the command “docker ps” (or “docker container ls”)- as shown in the image below:

As you can see, I’ve got 3 containers running at the moment – the HAPI server we just created plus mongoDb and a Node-Red container.

If we want to stop the container, we use the ‘docker stop’ command:

docker container stop myHapiServer

This halts the container (so the hapi server no longer works), but keeps it around. You can see the stopped container using docker ps -a which lists all containers, including those not currently running.

It can be started again using docker container start

docker container start myHapiServer

Or, if you are finished with it then you can remove it as follows:

docker container rm myHapiServer

But there’s a catch. When we start the container in this way, the data is stored within the container (by default, HAPI uses the H2 database) so when we remove the container, we also remove all the data. This may or may not be an issue for you. Note that stopping the container doesn’t lose the data – it’s only when it is removed that it disappears.

If we want to be able to keep the data even if we remove the container (eg we might want to update the HAPI version) then we need to save the data outside of the container (which is considered best practice in the container world).

There are a number of ways to do this – for example using an external SQL server like postgres which is probably the best in a production environment – but an easy way is to continue to use the H2 server, but specify a directory on the host machine rather than inside the container. That way, you can create a new container, and it will use the existing data (obviously only one container at a time).

Here are the steps (and my thanks to Jens Villadsen for his help here). Briefly, we need to update the HAPI configuration file to use a differently named path, and associate a folder with that path when starting the Container.

First, create a root folder to execute the container start command from. In that folder create a sub folder called ‘YourLocalFolder’ (can be anything of course, but that’s what Jens called it). In the ‘YourLocalFolder’ subfolder place a copy of the HAPI config file (we called it another.application.yaml).

Next, edit the config file replacing the line:

url: ‘jdbc:h2:file:./target/database/h2’


 url: ‘jdbc:h2:file:/configs/database/h2’

Now, you can execute the following instruction (all on one line from within the root folder) to start up hapi and tell it to use the folders you just created to store the data

docker run -p 8080:8080 –name myhapi  -v $(pwd)/yourLocalFolder:/configs -e “–spring.config.location=file:///configs/another.application.yaml” hapiproject/hapi:latest

This uses the -v docker parameter to specify an external volume (yourLocalFolder) to store the data, and the -e parameter to specify the location of the updated config file.  (I created a small batch file so I didn’t need to type all that stuff in!)

And that’s it! You now have your HAPI server, to use as you see fit! 

So this post has covered the basics of setting up a HAPI server in docker. It is really only the basics – there are many other ways that you can do this depending on your individual needs.

And speaking of production, if you don’t want to do this all yourself, there is a commercially supported version – the Smile CDR server – that you can use, and which adds a ton of other functionality such as SMART security and user management.

About David Hay
I'm an independent contractor working with a number of Organizations in the health IT space. I'm an HL7 Fellow, Chair Emeritus of HL7 New Zealand and a co-chair of the FHIR Management Group. I have a keen interest in health IT, especially health interoperability with HL7 and the FHIR standard. I'm the author of a FHIR training and design tool - clinFHIR - which is sponsored by InterSystems Ltd.

3 Responses to Creating your own FHIR Server: revised

  1. Pingback: Dew Drop – February 20, 2023 (#3883) – Morning Dew by Alvin Ashcraft

  2. oskiwi says:

    Configuring the application.yaml to import the NZ FHIR Base appears to crash a fresh install right now, other FHIR Bases are also experiencing the same problem…

    version: 2.0.0

    There’s a bug that covers this.

Leave a Reply

%d bloggers like this: