App Developer Hosting in CHT 4.x
This guide assumes you are a CHT app developer wanting to either run concurrent instances of the CHT, or easily be able to switch between different instances without losing any data while doing so. To do development on the CHT Core Framework itself, see the development guide.
To deploy the CHT 3.x in production, see either AWS hosting or Self hosting. To deploy 4.x in production see the 4.x documentation.
Getting started
First, decide which way to run the CHT: Docker Helper or manually it via docker compose
. Since they both achieve the same result, it is recommended to use Docker Helper as shown in the next section as it’s very easy to run. Alternately, the manual process is covered at the bottom of the page.
CHT Docker Helper for 4.x
Note
This is for CHT 4.x. To use a CHT 3.x version, see the earlier CHT Docker Helper pageThe cht-docker-compose.sh
scripts downloads 3 compose files and builds an .env
file. This greatly eases starting your first CHT instance with a simple text based GUI which works on Windows (WSL2), macOS (both x86 and Apple Silicon) and Linux.
This script brings a lot of benefits with it:
- You only have to download one bash script
- All compose files and images will be downloaded automatically for you
- All networks, storage volumes and containers will be created
- A valid TLS certificate will be installed, allowing you to easily test on with CHT Android natively on a mobile device
- An unused port is automatically chosen for you when creating a new project. No more manually looking at your existing
.env
files!
Installing
To get started using it:
- Meet all CHT hosting requirements
- Clone the CHT Core repo
- When you want to check for updates, just run
git pull origin
in thecht-core
directory.
An alternate to steps 2 and 3 above, if a more stand-alone version is desired, the bash script can be curl
ed directly, but you can’t use git
to easily update it then:
curl -s -o cht-docker-compose.sh https://raw.githubusercontent.com/medic/cht-core/master/scripts/docker-helper-4.x/cht-docker-compose.sh
Usage
Always run the script from the directory where it lives. If you launch it from a different directory, relative paths will fail:
Do | Don’t |
---|---|
./cht-docker-compose.sh | ./docker-helper-4.x/cht-docker-compose.sh |
Launching
Run the script with:
./cht-docker-compose.sh
The first time you run, you will be prompted to create a new project. Here’s what that looks like:
./cht-docker-compose.sh
Would you like to initialize a new project [y/N]? y
How do you want to name the project? 4 OH The First
Downloading compose files ... done
Creating network "4_oh_the_first-cht-net" with the default driver
Creating my_first_cht_project-dir_cht-upgrade-service_1 ... done
Starting project "4_oh_the_first". First run takes a while. Will try for up to five minutes........
--------------------------------------------------------
Success! "4_oh_the_first" is set up:
https://127-0-0-1.local-ip.medicmobile.org:10444/ (CHT)
https://127-0-0-1.local-ip.medicmobile.org:10444/_utils/ (Fauxton)
Login: medic
Password: password
--------------------------------------------------------
Start existing project
./cht-docker-compose.sh ENV-FILE.env
Stop and keep project:
./cht-docker-compose.sh ENV-FILE.env stop
Stop and destroy all project data:
./cht-docker-compose.sh ENV-FILE.env destroy
https://docs.communityhealthtoolkit.org/apps/guides/hosting/4.x/app-developer/
Have a great day!
If you have many existing projects, you can specify them to launch them directly. If you had a project called 4_oh_the_first
you would run:
./cht-docker-compose.sh 4_oh_the_first.env
Stopping
When you’re done with a project, it’s good to stop all the containers to reduce load on your computer. Do this by specifying the project and the stop
command. This command will simply stop the active Docker containers, and not delete any data. Using our existing example 4_oh_the_first
project, you would call:
./cht-docker-compose.sh 4_oh_the_first.env stop
Destroying
When you want to permanently delete all files and all data for a project, specify the project and the destroy
command. Using our existing example 4_oh_the_first
project, you would call:
./cht-docker-compose.sh 4_oh_the_first.env destroy
Be sure you want to do this, there is no “are you sure?” prompt and it will delete all your data.
Also note that this command will use the sudo
command when deleting the CouchDB data, so it may prompt for your password.
Debugging
To get debug output while running the docker helper, you can prepend the DEBUG=true
flag like this:
DEBUG=true ./cht-docker-compose.sh
This shows load average, CHT container count, global container count, and a table of services with their status like this:
---DEBUG INFO---
Load: 3.75 2.92 2.93
CHT Containers: 7
Global Containers 15
Service Status Container Image
cht-upgrade-service running 400_deleteme-dir-cht-upgrade-service-1 public.ecr.aws/s5s3h4s7/cht-upgrade-service:latest
haproxy NA NA public.ecr.aws/medic/cht-haproxy:4.4.0-8229-outbound-push
healthcheck running 400_deleteme_healthcheck_1 public.ecr.aws/medic/cht-haproxy-healthcheck:4.4.0-8229-outbound-push
api running 400_deleteme_api_1 public.ecr.aws/medic/cht-api:4.4.0-8229-outbound-push
sentinel running 400_deleteme_sentinel_1 public.ecr.aws/medic/cht-sentinel:4.4.0-8229-outbound-push
nginx running 400_deleteme_nginx_1 public.ecr.aws/medic/cht-nginx:4.4.0-8229-outbound-push
couchdb running 400_deleteme_couchdb_1 public.ecr.aws/medic/cht-couchdb:4.4.0-8229-outbound-push
Troubleshooting
When you are starting a CHT Core instance using Docker Helper 4.x and don’t have any containers created, images downloaded, or storage volumes created - the *.local-ip.medicmobile.org
TLS certificate fails to install, which leads to a browser Your connection is not private
message.
To solve this issue, follow the steps below:
- First, find the name of the
nginx
container with:docker ps --filter "name=nginx" --format '{{ .Names }}'
. - After cloning the CHT Core repo,
cd
into thescripts
directory:cd ./cht-core/scripts
. - Using the container name from the first command, call the script to update the certificate:
./add-local-ip-certs-to-docker-4.x.sh CONTAINER_NAME
.
These three steps look like as following assuming that CONTAINER_NAME
is equal to 4_3_0_nginx_1
. Note that CONTAINER_NAME
will be different for each instance of CHT you run with Docker Helper:
$ docker ps --filter "name=nginx" --format '{{ .Names }}'
4_3_0_nginx_1
$ cd Documents/MedicMobile/cht-core/scripts/
scripts $ ./add-local-ip-certs-to-docker-4.x.sh 4_3_0_nginx_1
4_3_0_nginx_1
If just container name is shown above, a fresh local-ip.medicmobile.org certificate was downloaded fresh local-ip.medicmobile.org.
File locations
The bash script keeps files in two places:
*.env
files - the same directory as the bash script.~/medic/cht-docker/
files - in your home directory, a sub-directory is created for each project. Within each project directory, acompose
directory has the two compose files and thecouch
directory has the CouchDB datafiles.
While you can manually remove any of these, it’s best to use the destroy
command above to ensure all related data files are deleted too.
Video
Here is a video of the helper being run on 1 Dec 2022. The video references lazydocker
which is a great way to monitor and control your local docker environment:
Manual docker compose
method
This process achieves the same result as Docker Helper, but is a more manual process. Be sure the CHT hosting requirements are all met first.
To avoid conflicts, ensure that all other CHT 4.x instances are stopped. To stop ALL containers, you can use
docker kill $(docker ps -q)
After meeting these requirements, create a directory and download the developer YAML files in the directory you want to store them. This example uses ~/cht-4-app-developer
as the directory:
mkdir -p ~/cht_4_app_developer-dir/{compose,couchdb} && cd ~/cht_4_app_developer-dir
curl -s -o ./compose.yml https://raw.githubusercontent.com/medic/cht-upgrade-service/main/docker-compose.yml
curl -s -o ./compose/cht-core.yml https://staging.dev.medicmobile.org/_couch/builds_4/medic%3Amedic%3Amaster/docker-compose/cht-core.yml
curl -s -o ./compose/cht-couchdb.yml https://staging.dev.medicmobile.org/_couch/builds_4/medic%3Amedic%3Amaster/docker-compose/cht-couchdb.yml
You should now have 3 compose files and 2 directories which we can check with ls -R
:
ls -R
compose compose.yml couch
./compose:
cht-core.yml cht-couchdb.yml
./couch:
To prepare for the first developer CHT instance, write all environment variables to the .env
file with this code:
cat > ~/cht_4_app_developer-dir/.env << EOF
NGINX_HTTP_PORT=8080
NGINX_HTTPS_PORT=8443
COUCHDB_USER=medic
COUCHDB_PASSWORD=password
CHT_COMPOSE_PROJECT_NAME=cht_4_app_developer
DOCKER_CONFIG_PATH=${HOME}/cht_4_app_developer-dir
COUCHDB_SECRET=19f3b9fb1d7aba1ef4d1c5ed709512ee
COUCHDB_UUID=e7122b1e463de4449fb05b0c494b0224
COUCHDB_DATA=${HOME}/cht_4_app_developer-dir/couch
CHT_COMPOSE_PATH=${HOME}/cht_4_app_developer-dir/compose
CHT_NETWORK=cht_4_app_developer
EOF
Start the first CHT instance by calling docker
:
cd ~/cht_4_app_developer-dir && docker compose up
This may take some minutes to fully start depending on the speed of the internet connection and speed of the host. This is because docker needs to download all the storage layers for all the containers and the CHT needs to run the first run set up. After downloads and setup has completed, the CHT should be accessible on https://localhost:8443. You can log in with username medic
and password password
.
When connecting to a new dev CHT instance for the first time, an error will be shown, “Your connection is not private” with NET::ERR_CERT_AUTHORITY_INVALID
(see screenshot). To get past this, click “Advanced” and then click “Proceed to localhost”.
Running the Nth CHT instance
After running the first instance of the CHT, it’s easy to run as many more as are needed. This is achieved by specifying different:
- port for
HTTP
redirects (CHT_HTTP
) - port for
HTTPS
traffic (NGINX_HTTP_PORT
) - directory for storing the compose files and CouchDB files
Assuming you want to start a new project called the_second
and start the instance on HTTP
port 8081
and HTTPS
port 8443
, we would first create a new directory and download the same files:
mkdir -p ~/cht_4_app_developer-2nd-dir/{compose,couchdb} && cd ~/cht_4_app_developer-2nd-dir
curl -s -o ./compose.yml https://raw.githubusercontent.com/medic/cht-upgrade-service/main/docker-compose.yml
curl -s -o ./compose/cht-core.yml https://staging.dev.medicmobile.org/_couch/builds_4/medic%3Amedic%3Amaster/docker-compose/cht-core.yml
curl -s -o ./compose/cht-couchdb.yml https://staging.dev.medicmobile.org/_couch/builds_4/medic%3Amedic%3Amaster/docker-compose/cht-couchdb.yml
Then, we would create an .env
file like before
cat > ~/cht_4_app_developer-2nd-dir/.env << EOF
NGINX_HTTP_PORT=8081
NGINX_HTTPS_PORT=8444
COUCHDB_USER=medic
COUCHDB_PASSWORD=password
CHT_COMPOSE_PROJECT_NAME=cht_4_app_developer-2nd
DOCKER_CONFIG_PATH=${HOME}/cht_4_app_developer-2nd-dir
COUCHDB_SECRET=19f3b9fb1d7aba1ef4d1c5ed709512ee
COUCHDB_UUID=e7122b1e463de4449fb05b0c494b0224
COUCHDB_DATA=${HOME}/cht_4_app_developer-2nd-dir/couch
CHT_COMPOSE_PATH=${HOME}/cht_4_app_developer-2nd-dir/compose
CHT_NETWORK=cht_4_app_developer-2nd
EOF
And finally use the same docker compose
command as above:
cd ~/cht_4_app_developer-2nd-dir && docker compose up
The second instance is now accessible at https://localhost:8444 and again using username medic
and password password
to login.
Switching & concurrent projects
The easiest way to switch between projects is to stop the first set of containers and start the second set. Cancel the first project running in the foreground with ctrl + c
and stop
all the project’s services. Here any container named cht_4_app_developer-2nd*
is stopped:
docker stop $(docker ps -q --filter "name=cht_4_app_developer-2nd*")
Alternately, you can stop ALL containers (even non-CHT ones!) with docker kill $(docker ps -q)
. Then start the other CHT project using either the .env
file or use the explicit command with ports and other environment variables as shown above.
To run projects concurrently open a second terminal and start the second project so you don’t have to cancel and stop
the first project. Remember to avoid port conflicts!
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.