Backstage by Example (Part 3)


To keep things simple, we will follow the Backstage instructions on building a single container image that serves both the frontend and backend applications. The instructions amount to running the following commands from the project’s root folder; but we need read further before proceeding.

$ yarn install
$ yarn tsc
$ yarn build
$ yarn build-image
  • We no longer need to expose the PostgreSQL database port to our workstation
  • We mount the github-app-backstage-mybackstageapp-credentials.yaml file into the container
  • Here we pass our workstation environment variables into the container
  • Not shown is that we need to change the POSTGRES_HOST in our from localhost to db; this is because the backstage container access the PostgreSQL database over the Docker network

Fixing Profile Image

One oddity when running the Backstage App from a container is that our profile image no longer is visible.

Refused to load the image '' because it violates the following Content Security Policy directive: "img-src 'self' data:".
Content-Security-Policy: default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self' 'unsafe-eval';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests;connect-src 'self' http: https:
$ yarn clean

Only Using Environment Variables

While most, if not all, container runtimes support environment variables, many do not support mounting files as we did with Docker Compose and the github-app-backstage-mybackstageapp-credentials.yaml file. So, here we convert to only using environment variables.

CMD ["sh", "-c", "echo \"$GITHUB_APP_CREDENTIALS\" > github-app-backstage-mybackstageapp-credentials.yaml & node packages/backend --config app-config.yaml"]

PostgreSQL Connection String

Rather than using the PostgreSQL host, port, user, and password as separate strings, it is more common to use a PostgreSQL Connection String. We make the following changes.

# config options:
client: pg
connection: ${DATABASE_URL}
export DATABASE_URL=postgresql://postgres:example@db:5432

Deploying to an Example Cloud Container Runtime (Google Cloud Run)

Now that we have a containerized application there are numerous ways to run our Backstage App in the cloud. Here I chose to use Google Cloud Run.

  • Because I was using Cloud Run with Cloud SQL with a Public IP, I had to switch back to using the POSTGRES_HOST, POSTGRES_USER, and POSTGRES_PASSWORD (POSTGRES_PORT is not needed) environment variables because I could not figure out how to supply a PostgreSQL connection string for a Unix domain socket
  • Because Cloud Run supplies the environment variable PORT that our application is to run on, I changed the port from 7007 to ${PORT} in app-config.yaml
  • Updated the three references of http://localhost:7007 to the Cloud Run Service URL in app-config.yaml, i.e., two baseURL and one origin key
  • Updated the home and callback values in the GitHub OAuth App using the Cloud Run Service URL

Wrap Up

While there is plenty of features to explore, e.g, Kubernetes, Software Templates, Search, TechDocs, and Plugins, will wrap up with series as we have accomplished our goal of standing a production-worthy Backstage App.



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
John Tucker

John Tucker


Broad infrastructure, development, and soft-skill background