← Back to the hackathon home
Topic 2 of 18

Setting Up DHIS2 Locally

Step by Step Guide: Running DHIS2 and Its Database on Your Own Machine With Docker

Purpose of this guide

Every other topic needs a DHIS2 to work in. This one gives you your own, running on your laptop, with two files and a handful of commands. It covers both situations: the machine that has never seen DHIS2 and has to download it, and the machine where the image is already there.

Step 1: What You Are About to Build

Two containers run side by side on your own machine. One is the database, the other is DHIS2 itself. They talk to each other over a private network, and your browser reaches DHIS2 on one port.

Figure 1. The two containers and the port you open. This picture was drawn for the guide. Your terminal will show your own paths and timings.
  1. 1The database. PostGIS, which is PostgreSQL with the map extension DHIS2 needs.
  2. 2DHIS2. The application itself, version 2.42.1 here.
  3. 3The network. A private bridge. DHIS2 finds the database by the name database.
  4. 4Your browser. http://localhost:8010, which is the port opened in the compose file.
Step 2: Install Docker Desktop

Docker is the only thing you install. DHIS2 and the database then run inside it, and nothing else is added to your machine.

Your machineDownload fromWhat to install
Windows 10 or 11https://www.docker.com/products/docker-desktop/Docker Desktop for Windows, AMD64 build
Mac, Apple siliconhttps://www.docker.com/products/docker-desktop/Docker Desktop for Mac, Apple chip
Mac, Intelhttps://www.docker.com/products/docker-desktop/Docker Desktop for Mac, Intel chip
Ubuntu or Debianhttps://docs.docker.com/engine/install/ubuntu/Docker Engine and the compose plugin
On Windows, in this order: open PowerShell as administrator and run wsl --install, restart the machine, then run the Docker Desktop installer, keep the box for WSL2 ticked, and start Docker Desktop from the Start menu. The whale icon in the system tray must say Running.
On a Mac: open the .dmg, drag Docker to Applications, start it, and accept the permission prompt.
On Ubuntu: follow the page above, then add yourself to the docker group with sudo usermod -aG docker $USER and log out and in again, so you do not need sudo for every command.
Give Docker enough memory: Docker Desktop → Settings → Resources → Memory, at least 4 GB. DHIS2 stops with exit code 137 when it runs out.
Step 3: Install Git

Git is only used to copy the two setup files onto your machine.

Your machineDownload fromNotes
Windowshttps://git-scm.com/download/winAccept every default. It installs Git Bash, which is a good terminal for these commands
Machttps://git-scm.com/download/macOr run xcode-select --install, which also gives you git
Ubuntu or DebianTerminalsudo apt update && sudo apt install git
If you would rather not install git at all: open the repository in a browser, click the green Code button, choose Download ZIP, and unzip it. The two files are the same, and every command after this works the same way.
Step 4: Start Docker Desktop Before Anything Else

Every command below talks to Docker. If Docker Desktop is not running, the terminal answers with an error no matter how correct your file is, so open Docker first and wait for it to finish starting, then open PowerShell or your terminal.

Open Docker Desktop → wait for the whale icon to say Running → then open PowerShell
MachineHow to start itHow you know it is ready
WindowsStart menu → Docker DesktopThe whale in the system tray stops animating and the app says Engine running
MacApplications → DockerThe whale in the menu bar is steady
Ubuntusudo systemctl start dockerdocker info answers without an error
The usual error when you forget: error during connect: ... the docker daemon is not running. Nothing is broken. Start Docker Desktop, wait, and run the command again.
After a restart of your machine: Docker Desktop may not start by itself. Turn on Start Docker Desktop when you sign in in its settings, or make opening it the first thing you do each morning.
Step 5: Check What Is Already Installed

You need Docker Desktop and git. On Windows, Docker Desktop needs WSL2 turned on.

Figure 2. Two commands that must answer. This picture was drawn for the guide. Your terminal will show your own paths and timings.
  1. 1docker --version. If this fails, install Docker Desktop first.
  2. 2docker compose version. Note the space. Old installations use docker-compose with a hyphen.
WhatWhyHow much
Docker DesktopRuns both containersLatest version
WSL2, on WindowsDocker needs itTurned on in Docker settings
MemoryDHIS2 and the database together8 GB, with at least 4 GB given to Docker
DiskImages and dataAbout 5 GB free
gitTo fetch the two filesAny version
Step 6: Get the Files
Clone the repository, then move into the folder
git clone https://github.com/mohamedsillahkanu/dhis2-local-set-up.git
cd dhis2-local-set-up
Figure 3. The two files you need. This picture was drawn for the guide. Your terminal will show your own paths and timings.
  1. 1git clone. Copies the folder to your machine.
  2. 2cd. Every command below is run from inside this folder.
  3. 3The files. docker-compose.yml describes the containers, dhis.conf tells DHIS2 how to reach the database.
Step 7: docker-compose.yml, Line by Line

This file is the whole setup. Nothing is installed on your machine except Docker.

services:
  database:
    image: postgis/postgis:13-3.3-alpine
    container_name: dhis2_test_db
    environment:
      POSTGRES_USER: dhis
      POSTGRES_PASSWORD: dhis
      POSTGRES_DB: dhis2
      PGDATA: /var/lib/postgresql/data/pgdata
    volumes:
      - dhis2-test-db-data:/var/lib/postgresql/data
    ports:
      - "5433:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U dhis -d dhis2"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped
    networks:
      - dhis2-test-network

  dhis2:
    image: dhis2/core:2.42.1
    container_name: dhis2_test
    depends_on:
      database:
        condition: service_healthy
    environment:
      DHIS2_DATABASE_HOST: database
      DHIS2_DATABASE_NAME: dhis2
      DHIS2_DATABASE_USERNAME: dhis
      DHIS2_DATABASE_PASSWORD: dhis
      DHIS2_HOME: /DHIS2_home
    ports:
      - "8010:8080"
    volumes:
      - dhis2-test-data:/DHIS2_home
      - ./dhis.conf:/opt/dhis2/dhis.conf
    restart: unless-stopped
    networks:
      - dhis2-test-network

volumes:
  dhis2-test-db-data:
    name: dhis2-test-db-data
  dhis2-test-data:
    name: dhis2-test-data

networks:
  dhis2-test-network:
    name: dhis2-test-network
    driver: bridge
LineWhat it does
services:Everything under it is one container
image: postgis/postgis:13-3.3-alpinePostgreSQL 13 with PostGIS 3.3, the small Alpine build. DHIS2 needs PostGIS for maps
container_name: dhis2_test_dbA fixed name, so commands and logs are readable
POSTGRES_USER / PASSWORD / DBCreates the database dhis2 and the user dhis on first start. These must match dhis.conf
PGDATAWhere the database writes its files inside the container
volumes: dhis2-test-db-dataKeeps those files outside the container, so data survives a restart
ports: "5433:5432"Left is your machine, right is inside. 5433 avoids clashing with a PostgreSQL you already run
healthcheckRuns pg_isready every 10 seconds until the database answers
restart: unless-stoppedComes back after a reboot, unless you stopped it yourself
image: dhis2/core:2.42.1The DHIS2 version. Change this number to try another release
depends_on: condition: service_healthyDHIS2 waits for the healthcheck to pass. Without it, DHIS2 starts too early and dies
DHIS2_DATABASE_HOST: databaseThe service name above, which is also its hostname on the network
DHIS2_HOME: /DHIS2_homeWhere DHIS2 keeps its configuration and files
ports: "8010:8080"DHIS2 listens on 8080 inside, you reach it on 8010. Change the left number if 8010 is busy
./dhis.conf:/opt/dhis2/dhis.confPuts your file inside the container. The dot means the folder you cloned
volumes: at the endDeclares the two named volumes where everything is kept
networks: driver: bridgeA private network for the two containers only
Step 8: dhis.conf, Line by Line

Five lines. They tell DHIS2 which database to use and how to sign in to it.

connection.dialect = org.hibernate.dialect.PostgreSQLDialect
connection.driver_class = org.postgresql.Driver
connection.url = jdbc:postgresql://database:5432/dhis2
connection.username = dhis
connection.password = dhis
LineWhat it does
connection.dialectTells Hibernate it is talking to PostgreSQL
connection.driver_classThe JDBC driver DHIS2 loads
connection.urldatabase is the service name, 5432 is the port inside the network, dhis2 is the database name
connection.usernamedhis, the same as POSTGRES_USER
connection.passworddhis, the same as POSTGRES_PASSWORD
Two things people get wrong here: using localhost instead of database in the url, which fails because localhost inside a container is the container itself, and using 5433, which is the port on your machine rather than the port on the private network.
Step 9: Which Scenario Are You In

Everything from here depends on one question: is the DHIS2 image already on this machine? Ask Docker rather than guessing.

docker images | grep -E "dhis2|postgis"
Figure 4. Two lines back means the images are already there. This picture was drawn for the guide. Your terminal will show your own paths and timings.
  1. 1The command. Lists the images stored on your machine.
  2. 2dhis2/core 2.42.1. The version the compose file asks for. It must match exactly.
  3. 3postgis 13-3.3-alpine. The database image.
What comes backGo to
Nothing, or a different versionScenario 1, the next step
Both lines, with 2.42.1Scenario 2, the step after that
Step 10: Scenario 1: the Image Is Not on the Machine

The whole sequence, run from inside the cloned folder. The pull is the slow part, about 1 GB, and it happens once on this machine.

#CommandWhat it doesHow long
0Open Docker Desktop and wait for RunningNothing else works until the engine is upHalf a minute
1cd dhis2-local-set-upMoves into the folder with the two filesInstant
2docker compose pullDownloads the DHIS2 and database imagesFive to fifteen minutes
3docker compose up -dCreates the network, the volumes and both containersUnder a minute
4docker compose psDatabase healthy, DHIS2 startedInstant
5docker compose logs -f dhis2Follows the first start, which builds every tableThree to ten minutes
6Wait for Server startup in ... msThe line that says DHIS2 is listening, then Ctrl + CThen you are done waiting
7Open http://localhost:8010Sign in as admin, districtInstant
Figure 5. Command 2, the download. This picture was drawn for the guide. Your terminal will show your own paths and timings.
  1. 1docker compose pull. Fetches both images named in the compose file.
  2. 2The database image. Small, under 300 MB.
  3. 3The DHIS2 image. About 1 GB. This is the line that takes the time.
Figure 6. Commands 3 and 4, starting the containers. This picture was drawn for the guide. Your terminal will show your own paths and timings.
  1. 1up -d. Starts both in the background.
  2. 2The database. Healthy before DHIS2 is allowed to start.
  3. 3DHIS2. Started, but not ready yet.
  4. 4ps. The quickest check on what is running.
Figure 7. Commands 5 and 6, waiting for the first start. This picture was drawn for the guide. Your terminal will show your own paths and timings.
  1. 1logs -f. Follows the log as it is written.
  2. 2Connected to database. Proof that dhis.conf is right.
  3. 3Server startup. The line you are waiting for.
  4. 4Ctrl + C. Stops watching. The containers keep running.
Figure 8. Command 7, signing in. This picture was drawn for the guide. Your terminal will show your own paths and timings.
  1. 1The address. localhost with the left port from the compose file.
  2. 2Username. admin.
  3. 3Password. district.
  4. 4Log in. An empty DHIS2, ready for Topic 1.
Step 11: Scenario 2: the Image Is Already There

Nothing is downloaded. The same commands as Scenario 1 without the pull. If the volume already holds a database, the start takes seconds rather than minutes.

#CommandWhat it doesHow long
0Open Docker Desktop and wait for RunningNothing else works until the engine is upHalf a minute
1cd dhis2-local-set-upMoves into the folderInstant
2docker images | grep dhis2Confirms the version matches the compose fileInstant
3docker compose up -dStarts both containers from the images you already haveUnder a minute
4docker compose psDatabase healthy, DHIS2 upInstant
5docker compose logs -f dhis2Minutes for a new database, seconds for one that already existsSeconds to minutes
6Open http://localhost:8010Sign in as admin, districtInstant
Figure 9. Command 2, the images are on the machine. This picture was drawn for the guide. Your terminal will show your own paths and timings.
  1. 1The command. Lists what is stored locally.
  2. 2The version. 2.42.1 must match the image line in docker-compose.yml.
  3. 3up -d. Straight to starting, with no download.
Figure 10. Commands 3 and 4, starting the containers. This picture was drawn for the guide. Your terminal will show your own paths and timings.
  1. 1up -d. The same command as Scenario 1.
  2. 2The database. Healthy first.
  3. 3DHIS2. Started.
  4. 4ps. Both containers listed.
If the version does not match: either edit the image line in docker-compose.yml to the version you have, or run docker compose pull once and follow Scenario 1.
Sharing the image at a workshop: on a machine that has it, run docker save dhis2/core:2.42.1 -o dhis2.tar, copy the file across, and on each other machine run docker load -i dhis2.tar. Everyone is then in Scenario 2 and nobody waits for the download.
Step 12: Everyday Commands

Four commands cover almost everything.

docker compose up -d        # start
docker compose down         # stop, keep the data
docker compose logs -f dhis2 # watch the log
docker compose restart dhis2 # restart DHIS2 only
Figure 11. Stopping, starting and the one to be careful with. This picture was drawn for the guide. Your terminal will show your own paths and timings.
  1. 1down. Stops and removes the containers. The volumes, and therefore the data, stay.
  2. 2up -d again. Starts from where you left off, in seconds this time.
  3. 3down -v. Removes the volumes too. Everything you entered is gone. Use it only to start clean.
Step 13: When Something Does Not Work
Figure 12. The most common message of all. This picture was drawn for the guide. Your terminal will show your own paths and timings.
  1. 1Ports are not available. Another program already uses 8010.
  2. 2The fix. Change the left number only, for example 8011:8080, then up -d again.
What you seeWhyWhat to do
The docker daemon is not runningDocker Desktop is closedOpen it, wait for Running, run the command again
Ports are not available8010 or 5433 is in useChange the left number in the ports line
DHIS2 keeps restartingIt cannot reach the databaseCheck the url line in dhis.conf says database:5432
Exit code 137Docker ran out of memoryGive Docker at least 4 GB in its settings
Blank page on 8010Startup is not finishedWait for the Server startup line in the log
dhis.conf not foundThe command was run from another foldercd into the cloned folder first
Password authentication faileddhis.conf and the compose file disagreeMake both say dhis and dhis
Step 14: What to Do Next

The instance is empty. Nothing in DHIS2 can be built until the organisation unit hierarchy exists, so go on to Topic 1 and create it, by hand or from the CSV file provided there.

OrderTopic
1Organisation units
2Data elements
3Category combinations
4The data set, then the form and data entry
Before anyone else uses it: change the admin password, and keep in mind that this instance is for learning. A production server needs a proper database password, backups and https.

Final Checklist