Getting Started with Artifact Registry: Deploying to Cloud Run
If you can hardly *contain* your excitement when it comes to containers, then this post is for you! If you disliked that pun, then this post is still for you, but don’t expect me to apologize for the dad jokes.
I’m going to talk about my living room
I started out this series of blogs by celebrating the purchase of my first home. Due to shelter in place orders, I’ve spent a lot more time here over the past few weeks than I originally imagined I would. There is one room in particular that I end up spending the most time in: the great room. I guess you could call it the living room, but given its size and the fact that it opens right to the kitchen, I think of it as pretty great.
When it comes to building apps, Cloud Run is my great room. It’s the first place I think to go for my serverless needs. That’s because the Cloud Run (fully managed) platform allows you to deploy stateless containers without having to worry about the underlying infrastructure. Your workloads are automatically scaled up or down to zero depending on the traffic to your app. You only pay when your app is running, billed to the nearest 100 milliseconds.
And when it comes to building apps, Artifact Registry is my roof: it brings all the pieces together. I can store my artifacts [like Cloud Run images] and my build dependencies [like npm packages] all under one roof while giving each room the unique environment and security it requires!
Ok, at this point I really can’t tell if these metaphors are getting better or worse, but I’m pretty pleased with this one. I wish I’d thought of it when I wrote that blog on Google Kubernetes Engine! Anyway…let’s get to the good stuff: deploying from Artifact Registry to Cloud Run!
Create a repository
Be sure that Artifact Registry is enabled for your Cloud project. Start with an existing repository or create a new repository . I’ll include the command here as a refresher, but if you’re not familiar with this command, I suggest you check out the docs or my blog post.
gcloud beta artifacts repositories create REPOSITORY \
--repository-format=FORMAT [--location=LOCATION] \
[--description="DESCRIPTION"] [--async]
I’ll showcase sample commands from my hypothetical company: Drayne. Drayne is autonomous, artificially intelligent, voice‑enabled plumbing for the modern home. I’ll make Drayne part of your pipeline using Artifact Registry in the software pipeline!
As an aside, I got this company idea from a list of joke sample companies made by one of my colleagues. I think it’s super funny but also actually somehow a good idea! I’ve heard worse ideas from founders making pitches while walking through San Francisco. But that’s a story for another blog!
Anyway, for my app Drayne, this is the command for creating my repository:
gcloud beta artifacts repositories create hellodraynerepo \
--repository-format=docker --location=us-central1 \
--description="helloworld node.js app"
Build an image
Build a container image and store it in the repository. If you have a container you already want to use, feel free to do so. I’m using the Cloud Run docs example of a basic helloworld Node.js app. I’m building my image locally since I showcased using Cloud Build in my blog post on deploying to Google Kubernetes Engine. I actually recommend using Cloud Build because it can define custom workflows for building, testing, and deploying across multiple environments. But I like to mix things up and I realize not everyone is going to use Cloud Build, so here’s another way.
Tag the build image with LOCATION-docker.pkg.dev/PROJECT-ID/REPOSITORY/IMAGE
. The build command will be in this format:
docker build -t LOCATION-docker.pkg.dev/PROJECT-ID/REPOSITORY/IMAGE
So the entire build command for my Drayne node.js app looks like this:
docker build -t hellodrayne:us-central1-docker.pkg.dev/drayne/hellodraynerepo/hellodrayne .
Push image to Artifact Registry
Once the image is built, push it to Artifact Registry. If you’re using Cloud Build, you can skip this step since the image is automatically pushed after being built. Yet another reason to use Cloud Build!
docker push LOCATION-docker.pkg.dev/PROJECT-ID/REPOSITORY/IMAGE:TAG
Here is the command for pushing my Drayne app to Artifact Registry:
docker push \
us-central1-docker.pkg.dev/drayne/hellodraynerepo/hellodrayne
Run it, run it!
Now that you have a container built and stored in Artifact Registry, you’re ready to deploy to Cloud Run. First, if you have not already done so, enable Cloud Run on your project in the Cloud Console.
Permissions required to deploy
To deploy to Cloud Run, you must have the Owner or Editor role, or both the Cloud Run Admin and Service Account User roles, or any custom role that includes this specific list of permissions. I’m not going to spell out that list here because every time I try to summarize some documentation in a blog, it changes. Seriously, that just happened the other day from a blog I wrote a year ago and now I have to go update it.
Deploying a new service
You can specify a container image with a tag or digest.
Deploying to a service for the first time creates its first revision. Note that revisions are immutable. If you deploy from a container image tag, it will be resolved to a digest and the revision will always serve this particular digest.
You can deploy a container using the Cloud Console or the gcloud command line. I’m using gcloud because I find it’s a more streamlined experience when you need to run a lot of Cloud actions back to back. The console is great too because you can view all sorts of information about your projects in one place and it includes links to documentation.
To deploy a container image, run this command:
gcloud run deploy SERVICE --image \
REPO-LOCATION-docker.pkg.dev/PROJECT-ID/IMAGE \
[--platform managed --region RUN-REGION]
Where:
- REPO-LOCATION is the location of the repository.
- SERVICE is the name of the service you want to deploy to. If the service does not exist yet, this command creates the service during the deployment. You can leave this parameter out, but if you do, you will be prompted for the service name.
- PROJECT-ID is the Google Cloud project ID.
- IMAGE is the name of your image
- RUN-REGION is the Cloud Run location for the deployment. If you set a default Cloud Run location set with the gcloud property run/region, you can omit — platform managed -region RUN-REGION]. Notice this means you can deploy to a different location than the one in which your repository is stored!
If you are creating a public API or website, you can allow unauthenticated invocations of your service using the --allow-unauthenticated
flag. This assigns the Cloud Run Invoker IAM role to allUsers. You can also specify--no-allow-unauthenticated
to not allow unauthenticated invocations. If you omit either of these flags, you are prompted to confirm when the deploy command runs. I’m including the flag in my sample command because I didn’t include it the first time and accidentally selected “N” instead of “y” when prompted to allow unauthenticated invocations. Including the flag ensures I don’t make that mistake again!
gcloud run deploy hellodrayne --image \
us-central1-docker.pkg.dev/drayne/hellodraynerepo/hellodrayne \
--platform managed --region us-central1 --allow-unauthenticated
Wait for the deployment to finish. Once completed, a success message is displayed along with the URL of the deployed service.
Mine looks like this:
Service [hellodrayne] revision [hellodrayne-00006-rup] has been deployed and is serving 100 percent of traffic at https://hellodrayne-xxxxxxxxx-uc.a.run.app
When I follow the link, I can see my app!
Yay!
Next Steps
Now that you know how to deploy an Artifact Registry container to Cloud Run, try uploading one of your own containers! And check out the docs to find out more about what Artifact Registry can do.