So far we have worked mostly with concepts and with the web console. In this lesson we change gear: we will learn the tool with which Google Cloud is really administered day to day, the gcloud CLI, and the environment that makes it accessible from any browser without installing anything, Cloud Shell.
Mastering gcloud is not about memorising commands, but about understanding its structure, knowing how to ask it for help and knowing how to extract exactly the piece of data you need. With that, any operation on any service becomes something you can work out. We will look at what Cloud Shell is and what limits it has, how to install the CLI locally, the anatomy of a command and the help system, the output formats and the filters, authentication and its two modes, named configurations for switching between alpinashop-dev and alpinashop-prod, the other SDK tools, and the basic scripting that chains commands together.
And we will close the module with the course's first real deployment: Dani is going to publish an AlpinaShop "coming soon" page on the internet, end to end, without leaving the browser.
Contents
- What Cloud Shell is
- Installing the Google Cloud CLI locally
- Cloud Shell versus a local CLI
- Anatomy of a
gcloudcommand and the help system - Output formats:
--format - Filters:
--filter - Authentication:
gcloud init,auth loginandapplication-default - Named configurations
- Other SDK tools
- Basic scripting with
gcloud - The first real deployment: AlpinaShop's "coming soon" page
- What Cloud Shell is
Cloud Shell is a free Linux virtual machine that opens inside the browser from the >_ icon in the console. It is designed so that you can administer Google Cloud without installing anything and without configuring credentials.
What it comes with already installed and configured:
| Category | Contents |
|---|---|
| Google Cloud CLI | gcloud, gsutil, bq, kubectl |
| Languages | Python, Java, Go, Node.js, .NET, Ruby, PHP |
| Tools | git, docker, terraform, make, vim, nano, jq, curl |
| Authentication | Already authenticated as your console user |
| Editor | Cloud Shell Editor, based on VS Code technology |
Characteristics and limits you need to know before relying on it:
| Aspect | Detail |
|---|---|
| Cost | Free |
| Machine | A small instance (on the order of 1-2 vCPU and a few GB of RAM) |
| Persistent disk | 5 GB mounted on your $HOME, which does persist between sessions |
Outside $HOME |
Everything is lost: packages installed with apt, changes in /etc, and so on |
| Inactivity | The session closes after roughly an hour without use |
| Maximum session | Around 12 hours at a stretch |
| Deletion through inactivity | If you do not use Cloud Shell for several months, the disk may be deleted (with prior warning) |
| Usage quota | There is a weekly hours limit |
The practical consequence of the persistence point is important: if you install something with apt install, it will be gone in the next session. For it to survive, either you install it in your $HOME, or you automate it in the ~/.customize_environment file, which Cloud Shell runs when the machine starts.
Two additional features we will use:
- Cloud Shell Editor: opened with the "Open editor" button, it gives you an IDE in the browser, with a file explorer, an integrated terminal and syntax highlighting. Very convenient for writing scripts or editing a
Dockerfilewithout leaving the console. - Web preview: the eye-shaped icon lets you open in the browser a service you are running in Cloud Shell (on port 8080 by default) through a temporary, authenticated URL. It is what lets you try out AlpinaShop's Flask application without deploying it.
# Check the machine you are working on
cat /etc/os-release | head -n2
nproc # number of CPUs available
free -h # memory
df -h $HOME # space on the persistent disk
- Installing the Google Cloud CLI locally
Cloud Shell is excellent for learning and for one-off tasks, but for day-to-day work you will want the CLI on your own machine, with your editor, your files and your scripts.
Linux (Debian/Ubuntu), through the official repository:
# 1. Dependencies and Google's repository key
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates gnupg curl
# 2. Add the repository's signing key
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg \
| sudo gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg
# 3. Add the repository to the apt sources
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] \
https://packages.cloud.google.com/apt cloud-sdk main" \
| sudo tee /etc/apt/sources.list.d/google-cloud-sdk.list
# 4. Install
sudo apt-get update && sudo apt-get install -y google-cloud-climacOS, with Homebrew:
Windows: download the GoogleCloudSDKInstaller.exe installer from the official documentation and run it. When it finishes it offers to launch gcloud init. Installing the Linux version inside WSL2 also works perfectly, and is the option many developers prefer.
Managing additional components:
# Install components that do not come by default
gcloud components install kubectl
gcloud components install beta alphaA word of warning: if you installed the CLI through apt or Homebrew, gcloud components update may be disabled, because the package manager handles updates. In that case, update with apt upgrade or brew upgrade. In Cloud Shell, the CLI updates itself.
- Cloud Shell versus a local CLI
| Criterion | Cloud Shell | Local CLI |
|---|---|---|
| Installation | None | Requires installing and updating |
| Authentication | Automatic, as your user | Requires gcloud init / auth login |
| Cost | Free | Free (but it uses your machine) |
| Persistence | Only 5 GB in $HOME |
Your whole disk |
| Power | A small machine | Your computer's |
| Preinstalled tools | Many and up to date | Whatever you install |
| Access to local files | They have to be uploaded | Direct |
| Integration with your editor/IDE | Limited to the web editor | Complete |
| Long sessions or heavy processes | Limited (timeout, quota) | No limit |
| Use from any device | Yes, all you need is a browser | No |
| Recommended for | Learning, one-off tasks, emergencies, demos | Daily work, development, scripts |
The recommendation for this course: use Cloud Shell. It removes all the installation friction and guarantees that you are working with the same version described here. Install the local CLI when you start developing in earnest.
- Anatomy of a
gcloud command and the help system
gcloud command and the help systemEvery gcloud command follows the same structure, and understanding it is what turns the CLI into something you can work out rather than something you have to memorise:
| Part | What it is | Examples |
|---|---|---|
| Group | The service or area | compute, storage, projects, iam, sql, run, billing |
| Subgroup | The type of resource within the service | instances, disks, firewall-rules, buckets |
| Action | The verb | list, describe, create, delete, update, add-iam-policy-binding |
| Arguments | The name of the resource | alpinashop-dev, web-1 |
| Flags | Options | --zone=europe-west1-b, --format=json |
Examples read according to this structure:
# group=compute, subgroup=instances, action=list
gcloud compute instances list
# group=projects, action=describe, argument=alpinashop-dev
gcloud projects describe alpinashop-dev
# group=compute, subgroup=firewall-rules, action=create, argument=permitir-http
gcloud compute firewall-rules create permitir-http --allow=tcp:80The verbs are consistent across services, and that consistency is what lets you work out commands you have never seen:
| Verb | What it does |
|---|---|
list |
Lists resources of the given type |
describe |
Shows the full detail of ONE resource |
create |
Creates a resource |
delete |
Deletes it |
update |
Modifies attributes |
add-iam-policy-binding |
Grants a role |
get-iam-policy |
Shows the permissions policy |
If you know that gcloud compute instances list exists, you can work out that gcloud sql instances list and gcloud run services list will exist too. And you would be right.
Asking for help
# Help for a group: which subgroups and actions it offers
gcloud compute --help
gcloud compute instances --help# Detailed help for a specific command, with ALL its flags and examples
gcloud compute instances create --help# Search for commands by keyword when you do not know where something lives
gcloud search-help "budget"
gcloud search-help "service account key"gcloud search-help is an underrated tool: it searches all the CLI help and returns the relevant commands ordered by relevance. When you do not know which command to use, start there.
Alpha and beta versions
Some commands are only available in preview stages and need a prefix:
A rule of thumb: if a command "does not exist", try beta and alpha before giving up on it. And do not use alpha commands in production: their interface can change without notice.
- Output formats:
--format
--formatBy default, gcloud returns a table designed for humans. The --format flag lets you change that output completely, and it is the key to using gcloud inside scripts.
| Format | What it is for |
|---|---|
--format=table(...) |
A readable table with the columns you choose |
--format=json |
Full JSON, ideal for processing with jq |
--format=yaml |
YAML, convenient to read for complex objects |
--format=value(...) |
Just the values, with no headers: the format for scripts |
--format=csv(...) |
CSV, for spreadsheets |
--format=flattened |
Every field as a key-value pair, one per line |
Applied examples:
# A bespoke table: only the fields you care about
gcloud projects list \
--format="table(projectId, name, projectNumber, lifecycleState)"# Full JSON for a resource: useful for discovering which fields exist
gcloud projects describe alpinashop-dev --format=json# Just one value, with no header or decoration: perfect for storing in a variable
PROJECT_NUMBER=$(gcloud projects describe alpinashop-dev \
--format="value(projectNumber)")
echo "Project number: $PROJECT_NUMBER"# Several values on one line, separated by tabs
gcloud projects list --format="value(projectId, projectNumber)"Useful functions inside --format, which save a lot of post-processing:
# basename() extracts the last segment of a resource URL.
# Without it, the zone appears as a long API URL.
gcloud compute instances list \
--format="table(name, zone.basename(), status, machineType.basename())"# Change the column names and sort the output
gcloud projects list \
--format="table[box](projectId:label=ID, name:label=NAME)" \
--sort-by=projectIdThe rule worth committing to memory: table for you to read, value for a script to read, json to process with jq.
- Filters:
--filter
--filter--filter narrows down the set of results on the server or the client side depending on the command, saving you from filtering with grep, which is fragile.
Available operators:
| Operator | Meaning | Example |
|---|---|---|
= |
Equal | --filter="status=RUNNING" |
!= |
Not equal | --filter="status!=TERMINATED" |
>, <, >=, <= |
Numeric or date comparison | --filter="creationTimestamp>2026-01-01" |
: |
Contains / has the key | --filter="labels.entorno:*" |
~ |
Matches a regular expression | --filter="name~^web-" |
!~ |
Does not match the regex | --filter="name!~^test-" |
AND, OR, NOT |
Logical combination | --filter="status=RUNNING AND zone:europe-west1" |
( ) |
Grouping | --filter="(a=1 OR b=2) AND c=3" |
Examples applied to AlpinaShop:
# Running instances in any zone of europe-west1
gcloud compute instances list \
--filter="status=RUNNING AND zone:europe-west1" \
--format="table(name, zone.basename(), status)"# Projects labelled entorno=desarrollo
gcloud projects list \
--filter="labels.entorno=desarrollo" \
--format="table(projectId, name)"# All enabled APIs related to storage or databases
gcloud services list --enabled \
--filter="config.name~storage OR config.name~sql" \
--format="value(config.name)"How to discover which fields you can filter on: look at the JSON output first. The JSON field names are exactly the ones --filter accepts.
# Step 1: see the object's full structure
gcloud compute instances describe web-1 --zone=europe-west1-b --format=json
# Step 2: filter using the field names you have seen
gcloud compute instances list --filter="machineType~e2-micro"
- Authentication:
gcloud init, auth login and application-default
gcloud init, auth login and application-defaultThis section clears up one of the most common confusions among beginners.
gcloud init
It is the initial setup wizard. It does three things in one: it authenticates you, it lets you choose a default project and it lets you choose a default region and zone.
Use it the first time you configure the CLI on a machine, or when you want to create a new configuration from scratch.
gcloud auth login versus gcloud auth application-default login
They are two different credentials, for two different consumers:
gcloud auth login |
gcloud auth application-default login |
|
|---|---|---|
| Who it is for | For the gcloud command and other SDK tools |
For your code: Python, Java, Go client libraries and so on |
| What it stores | SDK user credentials | An Application Default Credentials (ADC) file |
| Where | gcloud's internal configuration |
~/.config/gcloud/application_default_credentials.json |
| Used by | gcloud, gsutil, bq |
The code using google-cloud-* on your machine |
| When you need it | Always, in order to administer | Only if you develop locally against Google Cloud APIs |
The classic scenario that confuses everyone: Dani runs gcloud storage ls and it works, but his Python script fails with a credentials error. The cause is that he ran gcloud auth login but not gcloud auth application-default login: the client library looks for the ADC, not for the CLI's credentials.
Service accounts
For automated processes (a CI/CD pipeline, a scheduled task) user credentials are not used, service accounts are. And within Google Cloud, the right approach is not to download keys: a VM, a Cloud Run service or a GKE pod obtain credentials automatically from the service account associated with them.
# Authenticate with a service account from a key file.
# Avoid this whenever you can: downloaded keys are a security risk.
gcloud auth activate-service-account \
--key-file=/path/key.jsonService accounts, their roles and the secure alternatives to downloaded keys (Workload Identity Federation) are studied in lesson 03-04.
- Named configurations
A gcloud configuration is a set of properties: active account, project, default region and zone. You can have several named ones and jump between them with a single command, which elegantly solves the problem of switching between alpinashop-dev and alpinashop-prod.
# Create the development configuration
gcloud config configurations create alpinashop-dev
gcloud config set account [email protected]
gcloud config set project alpinashop-dev
gcloud config set compute/region europe-west1
gcloud config set compute/zone europe-west1-b# Create the production configuration
gcloud config configurations create alpinashop-prod
gcloud config set account [email protected]
gcloud config set project alpinashop-prod
gcloud config set compute/region europe-west1
gcloud config set compute/zone europe-west1-bTwo highly recommended complementary techniques:
# Run ONE command with another configuration without changing the active one
gcloud compute instances list --configuration=alpinashop-prod# Override the project for a single command only
gcloud compute instances list --project=alpinashop-prodAnd a tip that prevents serious accidents: add the active project to your bash prompt. Seeing on every line which project you are working on is the best protection against running something meant for development in production.
# Add to ~/.bashrc: shows the active project in the prompt
export PS1='[$(gcloud config get-value project 2>/dev/null)] \w\$ '
- Other SDK tools
The Google Cloud CLI includes several tools besides gcloud:
| Tool | What for | Status |
|---|---|---|
gcloud |
General Google Cloud administration | The main one |
gcloud storage |
Cloud Storage operations | Currently recommended: faster than gsutil |
gsutil |
The classic Cloud Storage tool | Still works; it is being replaced by gcloud storage |
bq |
BigQuery queries and administration | The standard for BigQuery |
kubectl |
Kubernetes / GKE administration | The Kubernetes standard, not Google-specific |
# GKE: get a cluster's credentials so that kubectl can be used
gcloud container clusters get-credentials alpinashop-cluster \
--region=europe-west1
kubectl get nodesThese tools will be used in depth in their corresponding modules: Cloud Storage in 02-02, GKE in 02-05 and BigQuery in 04-01. Here we simply note that they exist and that they are installed together.
- Basic scripting with
gcloud
gcloudCombining --format=value(...) with bash turns gcloud into a powerful automation tool. The fundamental pattern is always the same: list with a filter, extract a clean value, iterate.
# Store a value in a variable
PROJECT_ID=$(gcloud config get-value project)
PROJECT_NUMBER=$(gcloud projects describe "$PROJECT_ID" \
--format="value(projectNumber)")
echo "Project: $PROJECT_ID (number $PROJECT_NUMBER)"# Iterate over the results of a listing.
# This loop goes through all stopped instances and shows their name and zone.
gcloud compute instances list \
--filter="status=TERMINATED" \
--format="value(name, zone.basename())" |
while read -r NAME ZONE; do
echo "Stopped instance: $NAME in $ZONE"
# Here you could run, for example:
# gcloud compute instances delete "$NAME" --zone="$ZONE" --quiet
done# The --quiet flag answers "yes" to every confirmation.
# Essential in unattended scripts, DANGEROUS when typing by hand.
gcloud compute instances delete web-pruebas --zone=europe-west1-b --quiet# Combine gcloud with jq for more complex queries over the JSON
gcloud projects list --format=json |
jq -r '.[] | select(.labels.entorno == "desarrollo") | .projectId'Good practices for gcloud scripts:
- Always start with
set -eso that the script stops as soon as a command fails, instead of carrying on over an inconsistent state. - State the project explicitly with
--projectin important scripts, rather than relying on the active configuration. A script that deletes resources and trusts the active configuration is an accident waiting to happen. - Try it first without
--quiet, so you can see what it is going to ask you and which resources it would act on. - Many commands accept
--dry-runor have read-only equivalents: use them before running destructive operations.
- The first real deployment: AlpinaShop's "coming soon" page
The moment has come to put something on the internet. Dani is going to publish a static "coming soon" page while the team prepares the migration, using Cloud Storage to host it. It is a deliberate preview of the service studied in depth in lesson 02-02: here we use it as an exercise that pulls together everything learned in the module, without going into storage classes, lifecycles or versioning.
Step 1. Prepare the environment. Open Cloud Shell and confirm where you are:
gcloud config set project alpinashop-dev
gcloud config set compute/region europe-west1
gcloud config listStep 2. Create the page. Use the editor or the terminal directly:
mkdir -p ~/alpinashop-proximamente && cd ~/alpinashop-proximamente
cat > index.html <<'HTML'
<h1>AlpinaShop</h1>
<p>Mountaineering gear. We are getting our new online shop ready.</p>
<p>Coming here very soon.</p>
HTML
cat > 404.html <<'HTML'
<h1>Page not found</h1>
<p>Go back to the <a href="/">AlpinaShop home page</a>.</p>
HTMLThe cat > file <<'HTML' ... HTML block is a here-document: it writes into the file everything between the two markers. Putting the marker in single quotes prevents bash from trying to interpret $ or quotes inside the content.
Step 3. Create the bucket. Bucket names are unique across the whole of Google Cloud, just like projectIds, so we add a suffix to avoid collisions:
# Generates a unique name by adding a random suffix
export BUCKET="alpinashop-proximamente-$RANDOM"
echo "Bucket: $BUCKET"
gcloud storage buckets create "gs://$BUCKET" \
--location=europe-west1 \
--uniform-bucket-level-accessA breakdown of the command:
gs://is the Cloud Storage URI scheme.--location=europe-west1sets the region. Remember from lesson 01-05: a bucket's location is immutable.--uniform-bucket-level-accessdisables per-object access control lists and makes all permissions be managed through IAM alone. It is the recommended option because it hugely simplifies reasoning about who can see what.
Step 4. Upload the files:
Step 5. Make the content public. This step grants read access to anyone on the internet. It is exactly what we want for a public page, and exactly what you must never do with a bucket containing internal data:
gcloud storage buckets add-iam-policy-binding "gs://$BUCKET" \
--member=allUsers \
--role=roles/storage.objectViewerallUsers is a special IAM identifier meaning "anyone, authenticated or not". The roles/storage.objectViewer role grants read-only access to objects: it does not allow the bucket configuration to be listed or anything to be written.
Step 6. Configure the bucket as a website and check the result:
gcloud storage buckets update "gs://$BUCKET" \
--web-main-page-index=index.html \
--web-error-page=404.html# Check from the terminal itself that the page is being served
curl -s "https://storage.googleapis.com/$BUCKET/index.html"# Print the URL so you can open it in the browser
echo "https://storage.googleapis.com/$BUCKET/index.html"If curl returns the HTML you wrote, you have just published your first content on Google Cloud: you have created a resource in the right region, configured its permissions and verified it, all from the browser and without installing anything.
Step 7. Clean up. Essential: do not leave resources running that you are not going to use.
What we have not done here, and will come later: serving the page under the alpinashop.example domain with a TLS certificate (it requires a load balancer, lesson 03-07), speeding it up with Cloud CDN (03-03), choosing a storage class and lifecycle rules (02-02) and automating the deployment with Cloud Build (06-01).
Common Mistakes and Tips
- Confusing
gcloud auth loginwithgcloud auth application-default login. The first authenticates the CLI; the second, your code. If your Python script fails with a credentials error andgcloudworks, this is why. - Installing packages in Cloud Shell and losing them. Only
$HOMEpersists. Use~/.customize_environmentfor whatever you need on every start-up. - Running a command in the wrong project. Use named configurations, put the project in your prompt and add an explicit
--projectin dangerous scripts. - Filtering with
grepinstead of--filter.grepdepends on the output format, which can change;--filteroperates on the object's real fields. - Using
--quietwhen typing by hand. It is designed for unattended scripts. Interactively, those confirmations are your last line of defence. - Assuming a command does not exist. Try
gcloud search-help, and try thebetaandalphaprefixes. - Working with an out-of-date CLI. Many strange errors are resolved with
gcloud components update. - Tip: learn
--format=jsonfor exploring. It is how you discover what fields a resource has and therefore which fields you can filter on and what you can extract. - Tip: save your commands in scripts from the start. What you type by hand today, you will repeat tomorrow; and in module 6 you will turn it into a pipeline.
- Tip: use the console's "Equivalent command line" link. It remains the fastest way to learn new commands.
Exercises
Exercise 1: mastering --format and --filter
Write the gcloud commands that solve the following. Run them in your project to check them:
- Show all your projects in a table with just the ID and the project number.
- Store the number of the
alpinashop-devproject in a bash variable calledNUM, with no headers or extra text. - List the enabled APIs whose name contains
storageorsql, showing only the name. - List the zones of the
europe-west1region showing name and status in table format. - Find out, without leaving the terminal, which
gcloudcommand is used to manage billing budgets.
Exercise 2: configurations and authentication
Marta needs to work on two projects and wants to avoid accidents.
- Create two named configurations,
alpinashop-devandalpinashop-prod, each with its project, theeurope-west1region and theeurope-west1-bzone. - Write the command to list the production instances without changing the active configuration (two different ways of achieving it).
- Dani runs
gcloud storage lssuccessfully but his Python script fails withDefaultCredentialsError. Explain the cause and give the command that fixes it. - Propose an additional measure that reduces the risk of accidentally running a destructive command in production.
Exercise 3: full deployment and cleanup
Reproduce the deployment from section 11 with a variation: instead of a fixed page, the home page must show the date it was generated and the region where the bucket is hosted.
- Generate the
index.htmlincluding the current date and the region name. - Create the bucket with a unique name, upload the file, make it public and configure it as a website.
- Verify with
curlthat the content served includes the date. - Write a small script that checks that the bucket exists and shows how many objects it contains.
- Delete all the resources created.
Solutions
Solution 1
# 1
gcloud projects list --format="table(projectId, projectNumber)"
# 2
NUM=$(gcloud projects describe alpinashop-dev --format="value(projectNumber)")
echo "$NUM"
# 3
gcloud services list --enabled \
--filter="config.name~storage OR config.name~sql" \
--format="value(config.name)"
# 4
gcloud compute zones list \
--filter="region:europe-west1" \
--format="table(name, status)"
# 5
gcloud search-help "budget"Point 5 will return, among other results, gcloud billing budgets, with its create, list, describe, update and delete actions. It is the right way to discover commands without leaving the terminal.
Solution 2
# 1. Development configuration
gcloud config configurations create alpinashop-dev
gcloud config set project alpinashop-dev
gcloud config set compute/region europe-west1
gcloud config set compute/zone europe-west1-b
# Production configuration
gcloud config configurations create alpinashop-prod
gcloud config set project alpinashop-prod
gcloud config set compute/region europe-west1
gcloud config set compute/zone europe-west1-b
# Go back to development as the active configuration
gcloud config configurations activate alpinashop-dev# 2. Two ways of querying production without changing the active configuration
gcloud compute instances list --configuration=alpinashop-prod
gcloud compute instances list --project=alpinashop-prodThe first uses the complete production configuration (account, project, region); the second only overrides the project and keeps the rest of the active configuration. For read-only operations either will do; if the configurations used different accounts, the first would be the correct one.
- The cause is that
gcloud auth loginauthenticates the CLI, but Python client libraries look for the Application Default Credentials, which are a different file. The fix:
- Several measures are valid, and ideally you combine them: show the active project in the bash prompt (
export PS1='[$(gcloud config get-value project)] \w\$ '); always use an explicit--projectin scripts that delete or modify resources; do not grant the day-to-day working account deletion permissions in production, applying the least privilege principle (lesson 03-04); and use different browsers or profiles for the development and production consoles.
Solution 3
#!/bin/bash
set -e
REGION="europe-west1"
BUCKET="alpinashop-proximamente-$RANDOM"
# 1. Generate the page with date and region
mkdir -p ~/alpinashop-proximamente && cd ~/alpinashop-proximamente
cat > index.html <<HTML
<h1>AlpinaShop</h1>
<p>Mountaineering gear. New online shop on the way.</p>
<p>Generated on $(date '+%d/%m/%Y %H:%M') | Hosted in the region $REGION</p>
HTMLNote one difference from the example in section 11: here the here-document marker is not in single quotes (<<HTML instead of <<'HTML'), precisely because we want bash to substitute $(date ...) and $REGION before writing the file.
# 2. Create the bucket, upload, publish and configure as a website
gcloud storage buckets create "gs://$BUCKET" \
--location="$REGION" \
--uniform-bucket-level-access
gcloud storage cp index.html "gs://$BUCKET/"
gcloud storage buckets add-iam-policy-binding "gs://$BUCKET" \
--member=allUsers \
--role=roles/storage.objectViewer
gcloud storage buckets update "gs://$BUCKET" \
--web-main-page-index=index.html# 3. Verify the content being served
curl -s "https://storage.googleapis.com/$BUCKET/index.html" | grep "Generated on"# 4. Check existence and count objects
if gcloud storage buckets describe "gs://$BUCKET" \
--format="value(name)" > /dev/null 2>&1; then
OBJECTS=$(gcloud storage ls "gs://$BUCKET/**" | wc -l)
echo "Bucket $BUCKET exists and contains $OBJECTS object(s)."
else
echo "Bucket $BUCKET does not exist."
exit 1
fiThe check uses describe, redirecting the output to /dev/null and evaluating only its exit code: if the bucket does not exist, the command fails and the else branch is taken. The gs://$BUCKET/** pattern lists every object recursively, and wc -l counts them.
Conclusion
With this lesson we close module 1, and we do so with something running on the internet. We have learned what Cloud Shell is, what it comes preinstalled with and what its real limits are —especially that only the 5 GB of your $HOME persist—, as well as its web editor and the web preview. We have seen how to install the CLI on Linux, macOS and Windows, and when each option is worth it. We have taken apart the anatomy of a gcloud command into group, subgroup, action and flags, which turns the CLI into something you can work out, and we have learned to ask it for help with --help and gcloud search-help. We have mastered --format (with table for reading, value for scripts and json for exploring) and --filter with all its operators. We have cleared up the difference between gcloud auth login and gcloud auth application-default login, and we have set up named configurations for switching safely between alpinashop-dev and alpinashop-prod. We have met gcloud storage, bq and kubectl, which will accompany us in later modules, and we have written our first scripts chaining gcloud together with bash. And, above all, Dani has published AlpinaShop's "coming soon" page from the browser, checked that it is being served and cleaned up the resources afterwards.
Looking back over the whole module: we understood what the cloud is and why AlpinaShop needs it, we opened the account with safety-net budgets from day one, we learned to find our way around the console, we designed the project hierarchy and the billing, we chose europe-west1 as our region and grasped which part of security is ours, and now we know how to handle the tools. The ground is prepared and we know how to use the machinery.
In module 2, Core GCP Services, we start building in earnest: we will create virtual machines with Compute Engine, move the 60 GB of product images to the alpinashop-catalogo Cloud Storage bucket, migrate the tienda database to the Cloud SQL instance alpinashop-pedidos, get to know App Engine and the alpinashop-cluster cluster in Google Kubernetes Engine, explore the NoSQL databases and finish with the criteria for choosing the right compute service in each case. AlpinaShop's migration stops being a plan and starts being code.
Google Cloud Platform (GCP) Course
Module 1: Introduction to Google Cloud Platform
- What is Google Cloud Platform?
- Setting Up Your GCP Account
- A Tour of the GCP Console
- Projects, Resource Hierarchy and Billing
- Regions, Zones and the Shared Responsibility Model
- Cloud Shell and the gcloud CLI
Module 2: Core GCP Services
- Compute Engine: Virtual Machines on Google Cloud
- Cloud Storage: Object Storage
- Cloud SQL: Managed Relational Databases
- App Engine: Platform as a Service
- Google Kubernetes Engine (GKE)
- NoSQL Databases: Firestore, Bigtable and Spanner
- How to Choose the Right Compute Service
Module 3: Networking and Security
- VPC Networks
- Cloud Load Balancing
- Cloud CDN
- Identity and Access Management (IAM)
- Cloud Armor
- Secrets and Encryption: Secret Manager and Cloud KMS
- Cloud DNS, TLS Certificates and Publishing Services Securely
Module 4: Data and Analytics
- BigQuery: The Analytical Data Warehouse
- Cloud Dataflow: Batch and Streaming Data Processing
- Cloud Dataproc: Managed Spark and Hadoop
- Cloud Pub/Sub: Asynchronous Messaging
- Cloud Data Fusion: Code-Free Data Integration
- Orchestrating Pipelines with Cloud Composer and Workflows
- Data Governance and Dashboards with Dataplex and Looker Studio
Module 5: Machine Learning and AI
- Vertex AI: The Machine Learning Platform on GCP
- AutoML: Custom Models Without Writing Code
- TensorFlow on GCP: Training and Serving Models
- Natural Language API
- Vision API
- Generative AI on Vertex AI: Gemini Models and Embeddings
- MLOps: From Model to Product with Vertex AI Pipelines
Module 6: DevOps and Monitoring
- Cloud Build: Continuous Integration on GCP
- Cloud Source Repositories and Source Code Management
- Cloud Functions: Serverless Functions
- Cloud Monitoring (formerly Stackdriver): Metrics, Dashboards and Alerts
- Cloud Deployment Manager and Native Infrastructure as Code
- Cloud Logging and Cloud Trace: Logs, Traces and Diagnostics
- Terraform on GCP: Infrastructure as Code in Practice
Module 7: Advanced GCP Topics
- Hybrid and Multicloud with Anthos
- Serverless Computing with Cloud Run
- Advanced Networking: Shared VPC, Peering and Hybrid Connectivity
- Security Best Practices
- Cost Management and Optimization
- Reliability: SLOs, High Availability and Disaster Recovery
- Governance at Scale: Organization, Policies and Auditing
