Sign up for our newsletter! →

Deploying Elixir/Phoenix Application on GCP Cloud Run

Written By
HanaByte blog, elixir, phoenix, google cloud partner, GCP, hanabyte

In this blog post, we will be deploying a containerized Elixir/Phoenix application to Google Cloud Run. Cloud Run is a managed compute platform that lets you run containers directly on top of Google’s scalable infrastructure. You may be asking yourself, why choose Cloud Run when there are so many serverless platforms? Well I’d say they’re all pretty similar but Cloud Run is one of the easiest to get started on with many benefits integrated. After a successful deployment, you get a fully-qualified domain URL, logging, metrics, and managed deployments. Cloud Run does have its caveats like any other serverless platform. The big one is that Cloud Run requires you to deploy a containerized application. While many of our workloads are containerized, there’s still plenty that are not. Ok–that’s enough about Cloud Run and its pros and cons. If you need more info on whether your specific workload will work on Cloud Run see the official GCP documentation. The goal of this post is to give a general overview of the steps required to get a functional phoenix application running on GCP Cloud Run.

Deployment Steps Overview

Let’s take a look at the steps required to get our application deployed.

  1. Create Elixir/Phoenix application

  2. Containerized application

  3. Build Container and Publish to Registry

  4. Deploy Containerized Application to Cloud Run

  5. Inject Environment Variables and Secrets

Create Elixir Application

The first step is hopefully the easiest (or hardest): get an elixir/phoenix application. I’ll be using a generic Phoenix application generated using mix “mix phx.new test_app –no-ecto”. Mix is the build tool for working with Elixir projects. I’ve chosen not to include a database connection for brevity. I’ll leave adding a database connection as an exercise for the user.

Containerize The Application

Step 2 is to containerize our application. You can write your own Dockerfile, or maybe like me, prefer to generate one using the mix command “mix phx.gen.release –docker” command. I have found that the generated dockerfile works in most cases. It also has the added benefit of providing a multi-stage docker build that can be useful in a CI/CD pipeline for caching the builder layer of our application.

Build Container And Publish To Registry

With both of the first 2 steps completed, we can move on to building and publishing the container image to a registry. I’ll be using Google’s Artifact Registry in this blog, but Google’s Container Registry and Docker Hub are also supported.

See https://cloud.google.com/run/docs/deploying for more information on supported repositories.

First, we need to login to the project we’re working on using gcloud.

				
					> gcloud auth login
> gcloud config set project PROJECT_ID

				
			

Next, we need to have the artifact registry API enabled for our project. This may take several minutes to complete.

				
					gcloud services enable artifactregistry.googleapis.com
				
			

After we have enabled the artifact registry, we need to create a repository. I’ll be naming it `my-phoenix-app`.

				
					gcloud artifacts repositories create my-phoenix-app \
	--repository-format=docker \
	--location=us-east1 \
	--description="phoenix-elixir-app" \
	--immutable-tags   
Create request issued for: [my-phoenix-app]
Waiting for operation [projects/blogs-407517/locations/us-east1/operations/9b1174ed-0006-4804-ad11-e2fc792b05b8] to complete...done.                                                                                                      	 
Created repository [my-phoenix-app].
				
			

Once created, grab the registry url. It will be in the structure of The URL has the shape

REGION-docker.pkg.dev/PROJECT_ID/REPO_NAME/PATH:TAG
				
					> gcloud artifacts repositories describe my-phoenix-app --location us-east1

Encryption: Google-managed key
Registry URL: us-east1-docker.pkg.dev/blogs-407517/my-phoenix-app
Repository Size: 0.000MB
createTime: '2023-12-08T18:01:57.112912Z'
description: phoenix-elixir-app
dockerConfig:
  immutableTags: true
format: DOCKER
mode: STANDARD_REPOSITORY
name: projects/blogs-407517/locations/us-east1/repositories/my-phoenix-app
				
			

To build the docker image, I’ll be using Cloud Build. (Using Cloud Build to build our image is not a requirement. You can build the image locally and push it to the registry). I’ll include a quick snippet on how to do that below. The only requirement for the image is for it to target the amd64 architecture. Images not targeting amd64 will fail to start in the Cloud Run environment.

 

Ok, let’s enable Cloud Build and use it to build our container.

				
					> gcloud services enable cloudbuild.googleapis.com
Operation "operations/acf.p2-182047168193-22266cc4-2e7a-4fe4-8008-ab0a1ea2a0b9" finished successfully.
				
			

Create a Cloud Build job with your registry URL as the tag.

				
					gcloud builds submit --tag 
us-east1-docker.pkg.dev/blogs-407517/my-phoenix-app/phoenix-app:latest
				
			

To build and create the docker image locally, you first need to configure the registry. Then, using docker, build the image and finally push it up. If you are building locally, make sure to target the amd64 architecture. You can read more about that in the official docker multi-platform documentation.

				
					> gcloud auth configure-docker us-east1-docker.pkg.dev
				
			
				
					> docker build . \
--tag us-east1-docker.pkg.dev/blogs-407517/my-phoenix-app/phoenix-app

> docker push us-east1-docker.pkg.dev/blogs-407517/my-phoenix-app/phoenix-app
				
			

Deploy Containerized Application to Cloud Run

With our image built and published we can now deploy it to Cloud Run. To deploy our image we need to reference it using its registry and tag. For Phoenix applications, we are also required to pass in the SECRET_KEY_BASE environment variable, which is a required environment variable to start Phoenix applications. You’ll also see –allow-unauthenicated flag set, this tells Cloud Run that we want to expose our application to the internet. If you want to deploy an internal service you will not want to set this flag.

				
					> gcloud run deploy phoenix-service --image us-east1-docker.pkg.dev/blogs-407517/my-phoenix-app/phoenix-app:latest --region us-east1 --allow-unauthenticated --set-env-vars "SECRET_KEY_BASE=va2g7x4g99VQWGqmpACxD9j9tFMfQMKRyzhA3ZkWExKISsZbn/Z+eB7GwUKCTQZC"

Deploying container to Cloud Run service [phoenix-service] in project [blogs-407517] region [us-east1]
✓ Deploying... Done.
  ✓ Creating Revision...
  ✓ Routing traffic...
  ✓ Setting IAM Policy...
Done.
Service [phoenix-service] revision [phoenix-service-00005-c8x] has been deployed and is serving 100 percent of traffic.
Service URL: https://phoenix-service-o3f2fulppq-ue.a.run.app
				
			

That’s it. With a successfully deployed application, it is now accessible using the Service URL, and we have logging and reporting metrics being reported.

Conclusion

In a couple of steps we can get a phoenix/elixir application running in Cloud Run. We get many of the benefits of serverless with our application for a relatively low level of complexity. Hopefully this has demonstrated how easy it is to deploy your containerized application to Cloud Run. This post has barely scratched the surface of Cloud Run’s capability. There’re plenty of avenues to expand on the basic service we deployed i.e. traffic splitting, rolling/gradual deployments, and custom domains. Cloud Run can be the middle group between using kubernetes or self-hosting your application. Thanks for reading and happy coding!

Relevant Blogs

hanabyte blog, snowflake, haabyte, Patrick Davis
Cloud Security

Decoupling Security Data with Snowflake

By harnessing the power of a security data lake on a data platform like Snowflake, you can leverage near-infinitely scalable compute and storage capacity to change the story. With Snowflake’s ecosystem, you can ingest security data in any format and store it together…

Read More →
rise against hunger, hanabyte hearts, corporate outreach
HanaByte Culture

HanaByte Hearts: Rise Against Hunger Rechallenge

During the holiday season, HanaByte had the opportunity to coordinate with Rise Against Hunger for a second time. The first time that HanaByte met at the warehouse location, there was a small group with only 5 employees. A year later, a boisterous group of excited team members with their friends and family stood together waiting…

Read More →
Shea Nangle for HanaByte blog on Bill of materials cybersecurity
Cloud Security

Cloud Services Bill of Materials: An Idea Whose Time Has Come

A Cloud Services Bill Of Materials (CSBOM) is a comprehensive listing of each cloud-based asset utilized by a service that you run. For instance, if your company has a SaaS offering, it is very likely that the offering is dependent on a number of services provided by one or more cloud providers…

Read More →