There may be times when you need to connect your application to an external service such as an existing database or an external API. You’ll still need to create a service definition in your architect.yml file, but you’ll include a host property on the interface for the service. When this property is set, Architect routes all traffic to this service via the host rather than trying to provision the service.

Existing database

There are many reasons why a service may need to access an external database such as when you are first migrating your application to Architect and need to maintain production data or when you are using a managed database service. Architect can easily route traffic to the external service and can even pass secrets.

This is an example configuration for an external database using the host property:

name: example-component
description: |
  An example component showing how to create a dockerized postgres instance for
  on-demand environments while enabling the production environment to use an
  existing database instance.

secrets:
  existing_pg_host:
    required: false
    description: |
      The address of an existing database host that houses data specific to the
      deployed environment. If left blank, a new database will be provisioned using
      Docker.
  db_user:
    default: architect
    description: |
      Username of the account used to access the database. When a new database is
      provisioned, this will act as the root username.
  db_pass:
    default: password
    description: |
      Password for the account used to access the database. When a new database is
      provisioned, this will act as the root password.
  db_name:
    default: example
    description:
      The name of the database containing the tables for this application.

services:
  db:
    image: postgres:13
    interfaces:
      main:
        host: ${{ secrets.existing_pg_host }}
        port: 5432
    environment:
      POSTGRES_USER: ${{ secrets.db_user }}
      POSTGRES_PASSWORD: ${{ secrets.db_pass }}
      POSTGRES_DB: ${{ secrets.db_name }}

  api:
    build:
      context: ./
    interfaces:
      main: 8080
    environment:
      DB_ADDR: ${{ services.db.interfaces.main.url }}

By default, the above component will be deployed as a Dockerized service with a new Postgres instance since we’ve set the host value to false in the architect.yml file. . You can then override this value when you deploy the component, allowing you to easily change the database to the appropriate service for the environment you are deploying to.

$ architect deploy example-component -s existing_pg_host=<id>.rds.amazonaws.com

Non-containerized application

Another use case for wrapping an external service in an Architect component is to connect to legacy or otherwise non-containerized applications and workloads. By creating components for externally managed services, your team can more easily extend those services and create new cloud-native apps and APIs around them.

Here’s an example configuration:

name: example-virtual-component
description:
  An example component showing how to declare an externally managed service.

services:
  legacy-monolith:
    interfaces:
      main:
        protocol: https
        host: external-api.example.com
        port: 443

Now that you’ve wrapped this external application in a component, other developers can simply cite it as a dependency and extend it as they see fit:

name: example-consumer
description:
  Connects to and extends the functionality of the legacy application.

depenedencies:
  example-virtual-component: v1

services:
  api:
    build:
      context: ./
    interfaces:
      main: 8080
    environment:
      LEGACY_API_ADDR:
        ${{
        dependencies['example-virtual-component'].services.legacy-monolith.interfaces.main.url
        }}