Docker Swarm: Optional Embedded Database

For many applications, a database of some sort is required. A big question when packaging an on-prem app is whether to embed this database alongside the rest of your application, or to require an end customer to provide the connection details for a DB instance that they manage.

Tradeoffs

The key tradeoff is ease-of-setup for the customer vs. ease-of-maintainability for the application vendor, and often the answer is to allow both configurations. You can include an embedded database for trials and proof-of-concept installations, and then when your customer wants to set up a hardened production installation, they can supply connection details.

Docker Swarm Postgres Example

Configuration

First, we need some configuration items to allow the end customer to configure which mode they want to run in

config:
- name: db_settings_type
  title: Database Type
  description: Would you like to run an internal database or provide your own?
  items:
  - name: db_type
    type: select_one
    default: embedded
    items:
    - name: embedded
      title: Embedded
    - name: external
      title: External
- name: external_db_config
  title: External DB Settings
  description: DB connection settings
  when: db_type=external
  items:
  - name: database_connection_string
    type: text
    default: postgres://user:password@postgres.mycompany.com/some-database

Docker Swarm

On the swarm side, we need to reference those config options to control what runs in the cluster. We’ll toggle the number of postgres replicas that run, as well as the connection details for our example API server.

---
# kind: scheduler-swarm
version: '3.4'
services:
  postgres:
    image: postgres:10.4
    deploy:
      replicas: {{repl if ConfigOptionEquals "db_type" "embedded"}}1{{repl else}}0{{repl end}}
    environment:
      PG_PASSWORD: fake
      PG_USER: fake
      PG_DATABASE: my_app
  api:
   image: registry.replicated.com/my-app/api:1.0.1
   environment:
     POSTGRES_CONNSTRING: {{repl if ConfigOptionEquals "db_type" "external"}}{{repl ConfigOption "database_connection_string"}}{{repl else}}postgresql://postgres:postgres@postgres/my-app{{repl end}}

Note that this example omits (for brevity) how to securely create a persistent password/username for your postgres instance. A good guide for this can be found in Populating Config Values with Commands.

End to End

A full end-to-end example can be found in the optional-database branch of the replicated-starter-swarm repo.