Subdomain port mapping

For reference, here is how Squash handles subdomains and multi-level subdomains.

Subdomain port mapping is a great way to define HTTP endpoints for microservices to facilitate the communication between apps and APIs. This feature works for Dockerfiles, docker-compose and any apps without Docker.

Example using Docker

For this example we will use a repository with the following file:

  • src/CRM/docker-compose.yml
  • This docker-compose file has two containers

In the example above we have a CRM application consuming an API running on its own container/microservice.

Here is how the .squash.yml would look like:

deployments:
  CRM:
    filename:
      ./src/CRM/docker-compose.yml
    context_path:
      ./src
    vm_size:
      2GB
    subdomain_port_mapping:
      # this docker-compose has two containers, one container runs the
      # API on port 8080. "api" below can be any name and it represents
      # the subdomain itself.
      - api:8080
    ready_wait:
      # This will tell Squash to wait up to 20 min (1200 seconds) for a
      # success response from the app. The count down only starts after
      # the build process is finished.
      1200
  

And the docker-compose.yml would look like this:

version: '3.4'
services:
  api:
    image: myapp/api
    ports:
      - 8080:8080
  crm:
    image: myapp/crm-app
    ports:
      - 8000:80

Now, let's assume you have a branch named "lib_upgrades" in the same repository mentioned above. Squash will create a URL like this for this branch (more info on Squash URLs):

https://lib-upgrades-i3xg7.squash.io

And since you have defined the subdomain_port_mapping field in the .squash.yml file above, now you can access the API endpoint like this (note the double dashes on  api-- ):

https://api--lib-upgrades-i3xg7.squash.io

Example using a regular app (no Docker)

This example is going to be very similar except that we are not expecting any Docker file. All the build and launch steps are specified in the .squash.yml file below. Summary:

  • We are defining two apps in the YAML file: API and CRM app
  • API is listening to port 3000
  • We have defined a subdomain_port_mapping field within the API service
  • The CRM app is consuming the API service

deployments:
  API:
    dockerimage:
      # This is the base OS image we want to use for this app
      ubuntu:14.04
    vm_size:
      1GB
    build_steps:
      # This is where we install all the essential packages needed
      - DEBIAN_FRONTEND=noninteractive apt-get update
      - DEBIAN_FRONTEND=noninteractive apt-get install -y 
      software-properties-common
      - DEBIAN_FRONTEND=noninteractive add-apt-repository 
      ppa:ubuntugis/ubuntugis-unstable
      - DEBIAN_FRONTEND=noninteractive apt-get install -y 
      python python-dev python3.5 python3.5-dev python-pip
        python-virtualenv libssl-dev libpq-dev git ssh 
        build-essential libfontconfig1 libfontconfig1-dev
        locales gcc postgresql postgresql-contrib 
        postgresql-9.3-postgis-2.1 sudo supervisor
      - COPY . /code
      - cd /code
      - bash ./create_venv.sh
    launch_steps:
      # This is where we run the services and our app
      - service postgresql start
      - sleep 90
      - cd /code
      - /code/venv/bin/python /code/manage.py migrate
      - /code/venv/bin/python /code/manage.py runserver 0.0.0.0:3000
    subdomain_port_mapping:
       # this will associate the "api" subdomain with port 3000 running
       # in this specific container
      - api:3000
  CRM:
    dockerimage: python:latest
    build_steps:
      - apt-get update && apt-get install -y libssl-dev libpq-dev git
      build-essential libfontconfig1 libfontconfig1-dev curl
      - pip install setuptools pip --upgrade --force-reinstall
      - cd /code
      - pip install /code
      - python manage.py migrate
    launch_steps:
      - cd /myproject/mysite
      - python manage.py runserver 0.0.0.0:80
    ready_wait:
      # This will tell Squash to wait up to 20 min (1200 seconds) for a
      # success response from the app. The count down only starts after
      # the build process is finished.
      1200
    vm_size:
      2GB

Using the setup above in Squash is exactly the same as with the Docker setup. Let's assume you have a branch named "lib_upgrades" in the same repository mentioned above. Squash will create a URL like this for this branch (more info on Squash URLs):

https://lib-upgrades-i3xg7.squash.io

And since you have defined the subdomain_port_mapping field in the .squash.yml file above, now you can access the API endpoint like this (note the double dashes on  api-- ):

https://api--lib-upgrades-i3xg7.squash.io

How to access the subdomain with the dynamic Squash URL inside my app

A question that arises from the examples above is regarding how to actually use the "api--" endpoint within the CRM app since the Squash URL is unique per branch. In the example above the "i3xg7" part from the URL will be unique per branch.

The solution is using environment variables. Squash will always set a small number of default environment variables on each deployment and container. For instance, you can use the SQUASH_DOMAIN environment variable within the CRM app to get a reference of the actual URL of that specific deployment.

Then it's just a matter of appending the  api-- bit to the value returned by the environment variable and you now have the reference to the actual API endpoint.

The value of SQUASH_DOMAIN would look like this for the examples above: lib-upgrades-i3xg7.squash.io