The following guide outlines recommended practices for using Docker Compose with Healthcare Blocks. If you need additional documentation about specific Compose features, please refer to Docker's official documentation site.

Environment-Specific Docker Compose YAML

On your local machine, your configuration might differ compared to your Healthcare Blocks environment. For development, maintain a docker-compose.yml, whereas for Healthcare Blocks, use a docker-compose-prod.yml. Some of the differences between environments will include:

  • Additional services* (e.g. Healthcare Blocks database-as-a-service)
  • Environment variables
  • Port mappings
  • Specifying a restart policy to avoid downtime
  • Volume mounts

SSH to your Healthcare Blocks server and save your docker-compose-prod.yml to any directory on the encrypted data volume, e.g. /data/myapp. Now you can start your container(s) via:

cd /data/myapp && docker-compose up -f docker-compose-prod.yml

*If you're using our database-as-a-service, you do not need to define a database container in your Docker Compose YAML. Instead, using the credentials we shared with you, include them in the "environment" section in your application's configuration in the YAML file, and also set a DATABASE_HOST variable to the database service URL we provided.

Sample docker-compose-production.yml

Running Remote Compose Commands

Rather than exposing the Docker port externally and relying on Docker Machine, it's easy to run compose commands over SSH:

ssh username@machine 'cd /some/path; sudo docker-compose up -f docker-compose-prod.yml'

Persistent Volumes

To preserve data and/or files between container restarts and machine reboots, you can create directories on the encrypted data volume (mounted at /data) and then define a volume mount in your YAML file:

volumes:
  - /data/myapp/files:/app/storage
  - /data/log/myapp:/app/log

...where the first item in the pair is a path on the server, and the second item is the path inside the container.

Notes

  • Be sure you create the path on the server first, e.g. /data/mysql
  • Depending on your application, you might need to edit the permissions of the directory:
    chmod 0776 /data/myapp/files

SSL Certificates

Assuming you are using a Web server, you will need to provision an SSL certificate to encrypt protected health information (PHI) in transit per HIPAA requirements.

Using a Test Certificate

The Healthcare Blocks Nginx Docker image is bundled with a test certificate. Since it is a self-signed certificate, your Web browser will display an SSL/TLS error, so while it is useful for testing HTTPS based URL's, it should not be used for live, customer-facing applications.

Using a Certificate from a Certificate Authority

If you've already purchased a third-party SSL certificate from a known certificate authority, here's what you need to do to use it in your Healthcare Blocks environment:

  1. SSH to your server and create a directory for storing your certificate and key:
    mkdir -p /data/ssl
  2. In your docker-compose-prod.yml, define a volume mount from server path above to the Web server ssl path:
    volumes:
      - /data/ssl/domain.crt:/nginx/ssl/app.crt
      - /data/ssl/domain.key:/nginx/ssl/app.key

Note that you might need to set specific permissions on the directory, cert, and key via chmod.

Reference: Generating a certificate signing request when purchasing a cerficate from a third-party vendor

Using Free Certificates from Let's Encrypt

Let's Encrypt provides a limited number of free certificates that expire every 90 days. You can use their official Docker image to provision certificates. And by configuring a cron job, you can automate certificate renewals. Here's how:

  1. SSH to your Healthcare Blocks server
  2. If you have a Web application already running on port 80 and 443, you will need to temporarily stop it. The Let's Encrypt certificate provisioner API validates the requested certificate domain over the same ports.
  3. Run the following command:
    docker run -it --rm \
      -p 80:80 -p 443:443 \
      --name certbot \
      -v "/data/ssl/letsencrypt:/etc/letsencrypt" \
      -v "/data/ssl/letsencrypt/lib:/var/lib/letsencrypt" \
      certbot/certbot certonly -d SUBDOMAIN.healthcareblocks.com \
      --authenticator standalone \
      --email EMAIL_ADDRESS \
      --agree-tos
     (SUBDOMAIN is your unique server subdomain and EMAIL_ADDRESS is your preferred contact email)
  4. The previous command will save the cert and key to /data/ssl/letsencrypt/live. So if you are using our Nginx Docker image, be sure your docker-compose-prod.yml uses a volume mount pointing to the same location:
    volumes:
      - /data/ssl/letsencrypt/live/SUBDOMAIN.healthcareblocks.com/fullchain.pem::/nginx/ssl/app.crt
      - /data/ssl/letsencrypt/live/SUBDOMAIN.healthcareblocks.com/privkey.pem:/nginx/ssl/app.key

Automatically Renewing Certificates

  1. Write a simple bash script with the following contents and save it to /data/ssl/renewal.sh:
    #!/bin/bash
    set -euo pipefail
    
    docker run -it --rm --name renew_cert -v "/data/ssl/letsencrypt:/etc/letsencrypt" -v "/data/ssl/letsencrypt/lib:/var/lib/letsencrypt" quay.io/letsencrypt/letsencrypt:latest renew
    cd /data/myapp && docker-compose -f docker-compose-prod.yml exec nginx nginx -s reload
     Note: /data/myapp and app should be set to your actual values. The first nginx refers to the name of the image, and nginx -s reload is the actual command being passed to the container.
  2. Set execute permissions on the script:
    chmod +x /data/ssl/renewal.sh
  3. Edit the crontab:
    crontab -e
  4. Specify when you want the above script to execute, for example, every Sunday at 1 AM:
    0 1 * * 0 /data/ssl/renewal.sh
     Reference: Crontab Guru