Using BAO's DHIS2-in-Docker
Intro
This Guide will cover the pre-requisites and steps necessary for BAO employees to:
- Install the requirements: Docker and Docker Compose
- Stand up a local instance of DHIS2 using BAO’s DHIS2 Docker Image
- This guide is based the README from the repository and will attempt to fill in some of the gaps to make it more approachable for first time Terminal users, for example.
Requirements
- Familiarity with using the terminal/command line.
- Docker Desktop - available for MacOS, Windows, or Linux.
- Follow this link and Docker will help you find the right install for you.
- BAO’s DHIS2 Container Image
For Mac Users - If you don’t know what processor chip you have follow these steps:
- Head to the menu bar and click the Apple logo.
- Click About This Mac.
- Mac computers with Intel processors will show an item labeled Processor, while Mac computers with Apple silicon will show an item labeled Chip.
Download & Open Docker Desktop
Skip if already installed
For Windows Users - If you need more information than what Docker provides, follow the guidance in the video here, starting at 14:40.
For Linux Users - You’re on your own (per usual). Just follow the instructions/intro Docker gives you.
- Use the link in the Requirements section above to download Docker Desktop to your computer.
- Open the Docker Application.
- The Whale Icon (looks like a container ship) will appear on your dock or the taskbar/app tray. On a Mac it will appear in the header bar in the top right of your screen as well and has a drop down menu.
- Agree to the licensing terms when prompted.
- The Docker Dashboard will appear and it will prompt you to do a tutorial - do so if you like.
Validate Installation & Intro Commands
Optional but recommended for first-timers
- Open the your terminal (
cmd + space
, then typeterminal
and pressreturn
)
docker info
- Enter
docker info
and see the result- This information is about images that are downloaded, what is running, and some information about architecture (CPU, Memory, etc).
docker run
hello-world
- Enter
docker run hello-world
and see the result. - This is simple exercise to see that everything is working.
- As the text says, here is what that command did:
- The Docker client contacted the Docker daemon.
- The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64)
- The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading.
- The Docker daemon streamed that output to the Docker client, which sent it to your terminal.
- You can verify success in the Docker Desktop app as well as manage containers.
- Select the Docker Desktop application window, click on
Images
from the menu on the left, find one with the blue text “hello-world”. Click on it, see the mirrored output, and remove the hello-world container that was created by clicking on the trash bin icon and selectingremove
.
docker images
- Enter
docker images
and see the result.- The response is a list of images and some metadata about them.
docker rmi (Remove Image)
- Enter
docker rmi hello-world
and see the result. - Verify in the desktop app.
docker ps -a
- Enter
docker ps -a
and see the result.
Command | Description |
docker info | Information about the Docker client and the Docker server |
docker run hello-world | A.) Unless previously downloaded, pull the hello-world image from Docker Hub B.) Run the container. If the image command does not keep running, the container will stop |
docker images | Shows images downloaded to the Docker server |
docker rmi hello-world | Removes the hello-world image |
docker ps -a | Shows all running and stopped containers |
Downloading BAO’s DHIS2 Container Image
- You Need Two Files from the repository:
docker-compose.yml
and.env.exmaple
- Download, extract or copy the “compose file” -
docker-compose.yml
- from BAO's Github Repository.yml
is called a YAML file. Originally Yet Another Markup Language, now reinterpreted as YAML Ain't Markup Language. Pronunciation rhymes with Camel 🐫- https://github.com/baosystems/docker-dhis2/blob/main/docker-compose.yml
- There are multiple ways you can acquire the compose file:
- You can download and extract a zip file, or use one of the other options like HTTP/ &
git clone
to retrieve the file and then isolate the compose file. - Navigate to the file in your browser using the link above and copy the “raw” contents of the file and paste in a document you name
docker-compose.yml
- You can download and extract a zip file, or use one of the other options like HTTP/ &
- Whichever method you use, make sure the file is named
docker-compose.yml
when you’re done - docker will be looking for that file name.
- Download, extract, or copy the
.env.example
file to the same directory as the compose file.- The example
.env
file is a template for creating a valid file to setup our environment - The
.env
file that we will create is a place where we can setup some environment variables - it will mainly be used for changing the version of DHIS2.
- The example
Tip: If you chose to download the whole repository you can simply delete the other files and keep the docker-compose.yml
and the .env.example
files.
- ⭐ Copy the
.env.example
file to a new file called.env
- In your terminal navigate to the directory where the two files are and enter
java cp .env.example .env
- This will preserve the template while creating a useable
.env
.
- This will preserve the template while creating a useable
- On Mac - Files that start with
.
are hidden. You can display them with the-a
flag i.e.ls -a
- You can remove any other hidden files you don’t need.
- In your terminal navigate to the directory where the two files are and enter
cat .env
will display the contents of the file in your terminal - NoticeDHIS2_TAG
denotes the DHIS2 version as 2.36.3DHIS2_TAG
holds the value we will change to change DHIS2 versions.
Docker Compose Intro
Docker Compose is a “batteries included” tool that makes using docker easier for end-users. It reads the docker-compose.yml
file and takes care of wiring together the different services that make DHIS2 run, which are included in the BAO DHIS2 image. To summarize:
Docker Compose will:
- Download container images for DHIS2 with Tomcat and PostgreSQL
- Generate passwords for the database connection
- Initialize the database for DHIS2
- Start DHIS2
- Show logs from each containerized service
Startup “the Server”
“The Server” in this instances is really a group of containerized services - simultaneously much more and much less than a typical server. Anyway, we’re firing up DHIS2.
docker compose up -d
In the same directory that contains your two files (.env
& docker-compose.yml
) and the .env.example
template, follow the commands below:
docker compose up -d && docker compose logs -f
- The first command (
up
) is telling docker to read the compose file and standup the virtual network, services and infrastructure according to the directions in the associated files and docker images. - The
-d
flag is specifying that it is detached – we let DHIS2 go on in the background and we don’t need to see output in the terminal because…… - The second command is telling docker compose to follow (-f) the logs as they are output by our server until we tell it to stop the log stream via another command (
ctrl + c
).
- The first command (
Command | Description |
* docker compose up -d | * Start all services in the docker-compose.yml file * The -d/--detach option will return you to the terminal when finished |
* docker compose logs -f | * Show log lines for all services in the docker-compose.yml file * The -f/--follow option will continue to show log output until you quit with Ctrl+c |
Localhost:8080
With docker running our containerized services, you can now go to localhost:8080 in your browser and log into DHIS2 using the default admin:district credentials.
- Open the About page to verify your version and see other information about the environment
Additional Administration
docker compose down
This command will stop the services that you previously started. This command alone only stops the services in place – the containers remain as they were and everything is intact. If you wanted to take other actions here is a list of optional flags that can be passed with down
.
Flag | Description |
--rmi type | Remove images. Type must be one of: 'all': Remove all images used by any service. 'local': Remove only images that don't have a custom tag set by the image field. |
-v, --volumes | Remove named volumes declared in the volumes section of the Compose file and anonymous volumes attached to containers. |
--remove-orphans | Remove containers for services not defined in the Compose file |
-t, --timeout TIMEOUT | Specify a shutdown timeout in seconds. (default: 10) |
docker compose rm
This command removes stopped service containers and includes some optional flags as well.
Flag | Description |
-f, --force | Don't ask to confirm removal |
-s, --stop | Stop the containers, if required, before removing |
-v | Remove any anonymous volumes attached to containers |
Changing DHIS2 Version
For this step, there is no need to stop your containers when making a change to .env
. Docker will detect the difference in the environment for the container image and recreate the DHIS2 Service using the new environment you create. Give it a shot!
See the section below for Loading Custom Builds or Secured Hot Fixes
- In the .env file, find your DHIS2_TAG variable and notice the version number.
- Now, change the value to one minor version higher (or major version -- its your test after all!)
- (Re-)create the required containers with
docker compose up -d && docker compose logs -f --tail=3
(“tail=3” is to shorten logs from existing containers to not see everything from before) - Switch back to the browser and refresh, then verify via the “About” page.
Import Database From File
- Download a database export file BAO Manager (dhis2training for example) and save in the same directory as the docker-compose.yml file.
- Create a stack with
docker compose up -d
if one does not already exist - ⭐ In order to work on the database we need to stop the "dhis2" service.
- Use
docker compose stop dhis2
to stop the service named “dhis2”.
- Use
- ⭐ Drop and re-create the DHIS2 database
- Use
docker compose run --rm dhis2_init db-empty.sh
- This command is telling docker compose to “run” a an executable script from within the
dhis2_init
service -- this is all packaged within the BAO DHIS2 Docker Image. - This process drops the database, recreates a new one, and installs postGIS again.
- This command is telling docker compose to “run” a an executable script from within the
- Use
- ⭐ Load the database export file into the "database" service
gunzip -c <YOUR_DATABASE_FILE>.sql.gz | docker compose exec -T database psql -q -v 'ON_ERROR_STOP=1' --username='postgres' --dbname='dhis2'
- Take note of the part where you need to specify your database file name – make sure you account for
.sql.gz
- Restart the "dhis2" service
docker compose up -d && docker compose logs -f --tail=3
Export a DHIS2 Database From Your Docker Instance
You may experience some strange line breaks in your terminal when executing the export script. These seem to be a bug with Docker Compose.
- Stop the "dhis2" service
- Use
docker compose stop dhis2
to stop the service named “dhis2”.
- Use
- Export the database with the helper script db-export.sh
docker compose run --rm --entrypoint db-export.sh dhis2_init | gzip > output.sql.gz
- We specify the entry point to override the default so that we don’t have extra output form the
dhis2_init
script. The>
sign is capturing the output and putting it tooutput.sql.gz
- We specify the entry point to override the default so that we don’t have extra output form the
- (Re)Start the "dhis2" service
docker compose up -d && docker compose logs -f --tail=3
Loading Custom Builds or Secured Hot Fixes
Sometimes there are cases when you need to load a DHIS2 War File that is no the our standard repository. To do so, you’ll need to talk with Alan Aivey. Below are commands to run that will enable 2.36.10.1
and 2.37.6.1
to be specified in the .env
file:
⭐ This is only necessary until the releases are made public and added to BAO’s build repository
test -d docker-dhis2 || git clone 'https://github.com/baosystems/docker-dhis2.git'
cd docker-dhis2
git pull
wget -O 'dhis.war' 'https://s3.amazonaws.com/dhis2-builds/2.37/57f2dac/dhis.war'
docker buildx build --pull --load --tag 'ghcr.io/baosystems/dhis2:2.37.6.1' .
wget -O 'dhis.war' 'https://s3.amazonaws.com/dhis2-builds/2.36/0a0d8e3/dhis.war'
docker buildx build --pull --load --tag 'ghcr.io/baosystems/dhis2:2.36.10.1' .
# If you want to reclaim some disk space afterwards:
#docker buildx prune -f
#rm dhis.war
Connect to Postgres in Container
To connect to postgres in the container you can run the following command. It is for the super user and should be used for local testing/development needs.
docker compose exec database psql --username='postgres' --dbname='dhis2'
Troubleshooting
Database Import Failed
Try the alternate import which copies the database file to the container first.
KERROR: function "gen_random_uuid" already exists with same argument types
If you get this error it means you need to run the db-empty
script again. You probably had a failed import or something. Either way, a partial DB is still loaded and needs to be removed before you try to import a new one. docker compose run --rm dhis2_init db-empty.sh
Alternate
These steps below which will copy the file into the container before importing \
docker cp dhis2-db-sierra-leone-2.36.sql.gz "$( docker compose ps -q 'database' | head -n1 )":/tmp/db.sql.gz #docker compose exec database bash -c "gunzip -c /tmp/db.sql.gz | psql -v 'ON_ERROR_STOP=1' --username='postgres' --dbname='dhis2' && rm -v /tmp/db.sql.gz"
Docker Usage Tips
Stop / remove all Docker containers
Two lines to stop an/or remove all of Docker containers:
docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)