Skip to content

Commit

Permalink
Adding gcp typescript example for deploy of image to gcr and cloud run (
Browse files Browse the repository at this point in the history
pulumi#652)

Co-Authored-By: Mikhail Shilkov <[email protected]>
  • Loading branch information
danfhernandez and mikhailshilkov committed Apr 26, 2020
1 parent e61079e commit 05ae8e1
Show file tree
Hide file tree
Showing 15 changed files with 335 additions and 0 deletions.
135 changes: 135 additions & 0 deletions gcp-ts-docker-gcr-cloudrun/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
[![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new)

# Docker Build and Push to GCR and Deploy to Google Cloud Run using separate projects

An example of building a custom Docker image and pushing it into a Google Cloud Container Registry and then in a separate project deploying that image with the Google Cloud Run service using TypeScript.

> Note this is an adaptation of the [gcp-ts-cloudrun example](../gcp-ts-cloudrun)
## Prerequisites

1. [Ensure you have the latest Node.js and NPM](https://nodejs.org/en/download/)
2. [Install the Pulumi CLI](https://www.pulumi.com/docs/get-started/install/)
3. [Configure Pulumi to access your GCP account](https://www.pulumi.com/docs/intro/cloud-providers/gcp/setup/)
4. [Install Docker](https://docs.docker.com/install/)
5. Enable Docker to deploy to Google Container Registry with `gcloud auth configure-docker`
6. [Setup Docker auth with a JSON key to get image from GCR](https://cloud.google.com/container-registry/docs/advanced-authentication#json-key)

## Build and Push Docker Image

1. Navigate to the `docker-build-push-gcr` directory

2. Restore NPM dependencies:

```
$ npm install
```

3. Create a new stack:

```
$ pulumi stack init dev
```

4. Configure your GCP project and region:

```
$ pulumi config set gcp:project <projectname>
$ pulumi config set gcp:region <region>
```

5. Run `pulumi up` to preview and deploy changes:

```
$ pulumi up
Previewing update (dev):
...
Updating (dev):
Type Name Status
+ pulumi:pulumi:Stack gcr-build-image-dev created
+ └─ docker:image:Image ruby-app created
Outputs:
digest: "gcr.io/velvety-rock-274215/ruby-app:latest-fee86d3d35fccf2ad4d86bbfcdd489acf7b1e4db0ebb8166378bd1fb0ca9cee6"
Resources:
+ 2 created
Duration: 16s
```


## Deploy Cloud Run

1. Navigate to the `cloud-run-deploy` directory


2. Restore NPM dependencies:

```
$ npm install
```

3. Create a new stack:

```
$ pulumi stack init dev
```

4. Configure your GCP project, region and docker config file:

```
$ pulumi config set gcp:project <projectname>
$ pulumi config set gcp:region <region>
$ pulumi config set docker-config-file <location of ~/.docker/config.json>
```

5. Run `pulumi up` to preview and deploy changes:

```
$ pulumi up
Previewing update (dev):
Type Name Plan
+ pulumi:pulumi:Stack cloud-run-deploy-dev create
+ ├─ pulumi:providers:docker gcr create
+ ├─ docker:index:RemoteImage ruby-app-docker-image create
+ ├─ gcp:cloudrun:Service ruby create
+ └─ gcp:cloudrun:IamMember ruby-everyone create
Resources:
+ 5 to create
Do you want to perform this update? yes
Updating (dev):
Type Name Status
+ pulumi:pulumi:Stack cloud-run-deploy-dev created
+ ├─ pulumi:providers:docker gcr created
+ ├─ docker:index:RemoteImage ruby-app-docker-image created
+ ├─ gcp:cloudrun:Service ruby created
+ └─ gcp:cloudrun:IamMember ruby-everyone created
Outputs:
rubyUrl: "https://ruby-app-7a54c5f5e006d5cf33c2-zgms4nzdba-uc.a.run.app"
Resources:
+ 5 created
Duration: 23s
```

5. Check the deployed Cloud Run endpoint:

```
$ curl "$(pulumi stack output rubyUrl)"
Hello Pulumi!
```

6. Clean up your GCP and Pulumi resources (run in both projects):

```
$ pulumi destroy
...
$ pulumi stack rm dev
...
```
2 changes: 2 additions & 0 deletions gcp-ts-docker-gcr-cloudrun/cloud-run-deploy/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/bin/
/node_modules/
3 changes: 3 additions & 0 deletions gcp-ts-docker-gcr-cloudrun/cloud-run-deploy/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: cloud-run-deploy
runtime: nodejs
description: A minimal Google Cloud TypeScript Pulumi program
62 changes: 62 additions & 0 deletions gcp-ts-docker-gcr-cloudrun/cloud-run-deploy/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2016-2020, Pulumi Corporation. All rights reserved.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
import * as docker from "@pulumi/docker";

const location = gcp.config.region || "us-central1";

const config = new pulumi.Config();

const configFile = config.require("docker-config-file");

// Default to using ruby-app since that is the name of the image for the example.
const imageName = config.get("image-name") ?? "ruby-app";

const gcrDockerProvider = new docker.Provider('gcr', {
registryAuth: [{
address: "gcr.io",
configFile: configFile
}],
});

// Used to get the image from the google cloud registry. Output is required to make sure that the provider is in sync with this call.
const registryImage = pulumi.output(
docker.getRegistryImage({
name: `gcr.io/${gcp.config.project}/${imageName}:latest`,
}, {provider: gcrDockerProvider}));


// Using the value from the registryImage to pull the image if it's new, pullTriggers looks for a new sha.
var dockerImage = registryImage.apply(r => new docker.RemoteImage(`${imageName}-docker-image`, {
name: r.name!,
pullTriggers: [registryImage.sha256Digest!],
keepLocally: true
}, {provider: gcrDockerProvider}));

// String used to force the update using the new image.
var truncatedSha = registryImage.sha256Digest.apply(d => imageName + "-" + d.substr(8,20));

// Deploy to Cloud Run if there is a difference in the sha, denoted above.
const rubyService = new gcp.cloudrun.Service("ruby", {
location,
name: truncatedSha,
template: {
spec: {
containers: [{
image: dockerImage.name,
}]
},
},
}, {dependsOn: dockerImage});

// Open the service to public unrestricted access
const iamRuby = new gcp.cloudrun.IamMember("ruby-everyone", {
service: rubyService.name,
location,
role: "roles/run.invoker",
member: "allUsers",
});

export const rubyUrl = rubyService.status.url;

11 changes: 11 additions & 0 deletions gcp-ts-docker-gcr-cloudrun/cloud-run-deploy/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "cloud-run-deploy",
"devDependencies": {
"@types/node": "^8.0.0"
},
"dependencies": {
"@pulumi/pulumi": "^1.0.0",
"@pulumi/gcp": "^2.0.0",
"@pulumi/docker": "^1.0.0"
}
}
18 changes: 18 additions & 0 deletions gcp-ts-docker-gcr-cloudrun/cloud-run-deploy/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"strict": true,
"outDir": "bin",
"target": "es2016",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"experimentalDecorators": true,
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.ts"
]
}
2 changes: 2 additions & 0 deletions gcp-ts-docker-gcr-cloudrun/docker-build-push-gcr/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/bin/
/node_modules/
3 changes: 3 additions & 0 deletions gcp-ts-docker-gcr-cloudrun/docker-build-push-gcr/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: gcr-build-image
runtime: nodejs
description: A minimal Google Cloud TypeScript Pulumi program
14 changes: 14 additions & 0 deletions gcp-ts-docker-gcr-cloudrun/docker-build-push-gcr/app/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Use the official lightweight Ruby image.
FROM ruby:2.7-slim

# Install production dependencies.
WORKDIR /usr/src/app
COPY Gemfile Gemfile.lock ./
ENV BUNDLE_FROZEN=true
RUN bundle install

# Copy local code to the container image.
COPY . ./

# Run the web service on container startup.
CMD ["ruby", "./app.rb"]
4 changes: 4 additions & 0 deletions gcp-ts-docker-gcr-cloudrun/docker-build-push-gcr/app/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source 'https://rubygems.org'

gem 'sinatra'
gem 'rack', '>= 2.0.6'
25 changes: 25 additions & 0 deletions gcp-ts-docker-gcr-cloudrun/docker-build-push-gcr/app/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
GEM
remote: https://rubygems.org/
specs:
mustermann (1.1.1)
ruby2_keywords (~> 0.0.1)
rack (2.1.1)
rack-protection (2.0.8.1)
rack
ruby2_keywords (0.0.2)
sinatra (2.0.8.1)
mustermann (~> 1.0)
rack (~> 2.0)
rack-protection (= 2.0.8.1)
tilt (~> 2.0)
tilt (2.0.10)

PLATFORMS
ruby

DEPENDENCIES
rack (>= 2.0.6)
sinatra

BUNDLED WITH
2.1.4
8 changes: 8 additions & 0 deletions gcp-ts-docker-gcr-cloudrun/docker-build-push-gcr/app/app.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
require 'sinatra'

set :bind, '0.0.0.0'

get '/' do
target = ENV['TARGET'] || 'Pulumi'
"Hello #{target}!\n"
end
19 changes: 19 additions & 0 deletions gcp-ts-docker-gcr-cloudrun/docker-build-push-gcr/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2016-2020, Pulumi Corporation. All rights reserved.

import * as docker from "@pulumi/docker";
import * as gcp from "@pulumi/gcp";
import * as pulumi from "@pulumi/pulumi";

// Build and push image to gcr repository

const imageName = "ruby-app";

const myImage = new docker.Image(imageName, {
imageName: pulumi.interpolate`gcr.io/${gcp.config.project}/${imageName}:latest`,
build: {
context: "./app",
},
});

// Digest exported so it's easy to match updates happening in cloud run project
export const digest = myImage.digest;
11 changes: 11 additions & 0 deletions gcp-ts-docker-gcr-cloudrun/docker-build-push-gcr/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "gcr-build-image",
"devDependencies": {
"@types/node": "^8.0.0"
},
"dependencies": {
"@pulumi/pulumi": "^1.0.0",
"@pulumi/docker": "^1.0.0",
"@pulumi/gcp": "^2.0.0"
}
}
18 changes: 18 additions & 0 deletions gcp-ts-docker-gcr-cloudrun/docker-build-push-gcr/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"strict": true,
"outDir": "bin",
"target": "es2016",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"experimentalDecorators": true,
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.ts"
]
}

0 comments on commit 05ae8e1

Please sign in to comment.