How to obtain service URLs for non-default services
In a microservices or decoupled stack, you may have the need for each service to know the public URL of the other service. For example, if you have a NextJS frontend and Drupal backend, the frontend will need to know the backend URL, and the backend may need to know the frontend URL.
One of the Tugboat services will be the default
service. What this means is that that service has an exposed port (80
by default). All services will then have an environment variable with the public domain name of the default service.
(See our docs for a list of all the environment
variables)
$TUGBOAT_DEFAULT_SERVICE_URL=https://pr381-jkm6qcfq2nutbqjrqdlo66n7zmwbnubb.tugboatqa.com/
$TUGBOAT_DEFAULT_SERVICE_URL_HOST=pr381-jkm6qcfq2nutbqjrqdlo66n7zmwbnubb.tugboatqa.com
$TUGBOAT_DEFAULT_SERVICE_URL_PROTOCOL=https
$TUGBOAT_DEFAULT_SERVICE_URL_PATH=/
For example, in the case of a NextJS frontend and Drupal backend, if you have the Drupal backend as the default
service in your config.yml, then the frontend can use the TUGBOAT_DEFAULT_SERVICE_URL
or
TUGBOAT_DEFAULT_SERVICE_URL_HOST
environment variables to retrieve the public URL for the Drupal backend.
Let’s say your nextjs app has a .env.local.template
that looks something like this:
NEXT_PUBLIC_DRUPAL_BASE_URL=https://oms.lndo.site
NEXT_IMAGE_DOMAIN=oms.lndo.site
You could use sed
to replace those values with the associated Drupal URL:
cat .env.local.template |
sed -e "s@^NEXT_PUBLIC_DRUPAL_BASE_URL=.*\$@NEXT_PUBLIC_DRUPAL_BASE_URL=${TUGBOAT_DEFAULT_SERVICE_URL}@" \
-e "s@^NEXT_IMAGE_DOMAIN=.*\$@NEXT_IMAGE_DOMAIN=${TUGBOAT_DEFAULT_SERVICE_URL_HOST}@" \
> .env.local
In config.yml, that might look like this:
services:
storybook:
...
commands:
...
build:
- cat path/to/.env.local.template |
sed -e "s@^NEXT_PUBLIC_DRUPAL_BASE_URL=.*\$@NEXT_PUBLIC_DRUPAL_BASE_URL=${TUGBOAT_DEFAULT_SERVICE_URL}@"
-e "s@^NEXT_IMAGE_DOMAIN=.*\$@NEXT_IMAGE_DOMAIN=${TUGBOAT_DEFAULT_SERVICE_URL_HOST}@"
> path/to/.env.local
How to retrieve a non-default URL from another service
You may also need to know the public URL for another service that is not the default service. In this instance, you can
use the Tugboat API with curl
and jq
to determine the URL of the other service.
Using our same example above, let’s say the Drupal backend needs to know the public URL for the frontend application.
From within the Tugboat config.yml
, you may have something like this:
services:
drupal:
image: tugboatqa/php:8.3-apache
default: true
commands: ...
storybook:
image: tugboatqa/node:18
expose: 3000
checkout: true
depends:
- drupal
commands: ...
Since the storybook
nodejs service is exposing port 3000 to the Tugboat proxy, it will receive a public URL. From the
drupal
service, you can use the $TUGBOAT_SERVICE_TOKEN
environment variable as
Token-based authentication to the Tugboat API
to retrieve the URL of the other service:
In a Terminal on the drupal
service, you could test this out with the following command:
# Install jq
apt-get update && apt-get install -y jq
# Curl the API and retrieve the public storybook URL
curl --silent --header "Authorization: Token $TUGBOAT_SERVICE_TOKEN" \
https://api.tugboat.qa/v3/previews/$TUGBOAT_PREVIEW_ID/services |
jq -r '.[] | select(.name == "storybook") | .urls[0]'
You might translate that into a config.yml
like so:
services:
drupal:
...
commands:
init:
# Install jq in the init steps
- apt-get update && apt-get install jq
...
build:
# Use yaml literal notation to support multiline commands
- |
set -e
STORYBOOK_URL=$(curl --silent -H "Authorization: Token $TUGBOAT_SERVICE_TOKEN"
https://api.tugboat.qa/v3/previews/$TUGBOAT_PREVIEW_ID/services |
jq -r '.[] | select(.name == "storybook") | .urls[0]')
# Run command to use the STORYBOOK_URL in Drupal settings.php
printf "\$settings['YOUR_VARIABLE'] = '%s';\n" "$STORYBOOK_URL" >> path/to/settings.local.php
We use yaml literal notation (the pipe |
turns this on) to allow multiline yaml
commands so we can store the storybook url into a temporary environment variable. Then we are appending a Drupal
settings.php file with a Drupal setting with that URL. You might prefer to use sed
or some other means to achieve
this.
Tugboat provides flexible solutions for service-to-service communication in complex environments. By leveraging environment variables and the Tugboat API, you can easily configure your services to communicate with each other, whether they’re default or non-default services. These approaches ensure that your microservices or decoupled applications can reliably find and connect to each other, maintaining proper functionality in your Tugboat preview environments. With the techniques outlined in this document, you can confidently set up communication between your various services, enabling comprehensive testing and development in isolated environments that closely mirror your production setup. If you have any questions on how to adapt this to your needs, please reach out to Tugboat Support.