15 - Containers 101 and Artifact Registry
Welcome to Day 15 of Learn GCP in 30 Days! Today, we kick off Week 3: Serverless & Containerized Applications.
Today's Goal Don't worry if technical buzzwords like "Containers", "Docker", or "Artifact Registry" sound complex or intimidating! In this lesson, we break everything down using simple, everyday analogies. You will learn what containers actually are (just lightweight, portable boxes for your apps), why they save developers hours of frustration, and how to safely build and store your very first container image inside Google Cloud Artifact Registry!
π¦ The Core Problem: "It Works on My Machine!"
Every software developer has experienced this painful scenario:
What Existed Previously:
Developers wrote code on their personal laptops (running macOS, Windows, or Ubuntu) with specific versions of programming languages, tools, and background helper libraries installed. When it was time to deploy to a production Virtual Machine, they had to manually recreate that entire environment.
Problems Faced:
- π€¦ Version Mismatch: The developer had Python 3.11 with library version 2.4, but the production server had Python 3.8 with library version 1.9. The app immediately crashed.
- π Heavy Virtual Machines: To fix compatibility, teams used full Virtual Machine snapshots. But VMs take gigabytes of disk space, minutes to boot up, and consume heavy memory just to run an entire duplicate guest operating system.
- π Slow Scaling: If website traffic surged, launching 5 new VMs took 3 to 5 minutes each.
How Present Technology Solves It:
The cloud industry standardized on Docker Containers:
- Self-Contained Portability: Your code, runtime, system tools, and exact library versions are packaged together into one sealed, standardized box (a Container).
- Identical Everywhere: If a container runs on your laptop, it is mathematically guaranteed to run identically on GCP, AWS, or any Linux server.
- Blazing Fast & Lightweight: Containers share the host operating system's kernel. They start up in milliseconds instead of minutes and take megabytes of space instead of gigabytes!
π’ Real-World Analogy: Cargo Shipping Containers
Before 1956, shipping goods internationally was chaotic:
- Before Standard Shipping Containers: Workers manually loaded loose barrels of wine, wooden crates of fruit, and sacks of grain onto ships. Trucks and trains could not easily fit each other's goods.
- After Standard Shipping Containers: The global shipping industry invented the Standard 20-Foot Steel Box. The crane doesn't care what is inside the box (shoes, electronics, or coffee). It only cares that the box has standard corner locks and fits every ship, truck, and train in the world!
- Docker Containers = Software Shipping Containers: Docker is the standardized steel box for software. Cloud platforms (Google Cloud Run, GKE, Kubernetes) do not care whether your code is Python, Node.js, Java, or Go. They simply run your standardized container!
π Everyday Cloud Terms Explained in Plain English
Let's demystify the 4 core concepts of container technology:
1. Dockerfile vs. Container Image vs. Container
Think of these 3 terms like baking a cake:
- π Dockerfile (The Recipe): A simple text file with step-by-step instructions on how to build your application (e.g., "1. Install Python, 2. Copy my code, 3. Run app.py").
- π¦ Container Image (The Frozen Cake Mix Box): The static, immutable (read-only) package created after building your Dockerfile. It contains your code and all libraries frozen in time. You store and share this image.
- π Container (The Live Cake): The active, running instance of an image. You can launch 1, 10, or 1,000 running containers simultaneously from a single Container Image!
2. Virtual Machine (VM) vs. Container: Key Differences
| Feature | π₯οΈ Virtual Machine (Compute Engine) | π³ Container (Docker / Cloud Run) |
|---|---|---|
| Boot Time | 1 to 3 minutes | 100 milliseconds to 2 seconds |
| Size on Disk | 10 GB to 50 GB | 20 MB to 300 MB |
| Operating System | Has its own full Guest OS | Shares host machine's OS kernel |
| Resource Usage | Heavy (reserves fixed RAM/CPU) | Extremely lightweight (uses only what it needs) |
| Best For | Legacy apps, custom kernel drivers | Modern microservices, APIs, scalable web apps |
3. What is Google Cloud Artifact Registry?
Once you build a Container Image on your computer, where do you store it so your cloud servers can access and run it?
Real-World Analogy Mapping:
Think of Google Cloud Artifact Registry as a Private App Store / Secure Warehouse for your container images:
- When you finish building your container image, you
docker pushit into Artifact Registry. - Artifact Registry securely stores, versions, and automatically scans your images for security vulnerabilities.
- When Google Cloud Run or GKE needs to scale up, it instantly pulls the container image directly from Artifact Registry!
Artifact Registry vs. Container Registry (GCR)
In older GCP tutorials, you might see gcr.io (Google Container Registry). Google has replaced it with Artifact Registry (pkg.dev), which is faster, cheaper, supports fine-grained IAM permissions, and stores not just Docker containers, but also Maven, npm, Python, and Go packages!
π§ͺ Hands-on Lab Activity: Build & Push a Container to GCP Artifact Registry
In this hands-on lab, we will:
- Enable the Artifact Registry API.
- Create a private Docker repository in Artifact Registry.
- Write a simple Python web application and a
Dockerfile. - Build the container image locally in Cloud Shell.
- Authenticate Docker with GCP and push the image to Artifact Registry!
Step 1: Enable the Artifact Registry API
Option A: Web Console UI
- Log into console.cloud.google.com.
- Press
/, type Artifact Registry API, and click on it. - Click Enable.
Option B: Cloud Shell CLI
- Open Cloud Shell (
>_). - Run:
bash
gcloud services enable artifactregistry.googleapis.com
Step 2: Create a Docker Repository in Artifact Registry
We need a dedicated repository to store our Docker container images.
Option A: Web Console UI
- In the left navigation menu
β°, go to CI/CD (or Tools) Artifact Registry Repositories. - Click Create Repository at the top.
- Configure the repository:
- Name:
my-docker-repo - Format:
Docker - Mode:
Standard - Location type:
Regionasia-south1(or your preferred region, e.g.us-central1) - Encryption:
Google-managed key
- Name:
- Click Create.
Option B: Cloud Shell CLI
gcloud artifacts repositories create my-docker-repo \
--repository-format=docker \
--location=asia-south1 \
--description="My First Docker Repository on GCP"
Step 3: Write a Simple Web App & Dockerfile in Cloud Shell
Let's create a minimal web application using Python. Copy and paste each command block one by one into Cloud Shell:
3.1: Create Project Directory
mkdir -p ~/gcp-container-lab && cd ~/gcp-container-lab
3.2: Create the Python Web Server (app.py)
How Code Files are Created in this Lab (2 Ways)
- β‘ Fast 1-Click Way (Recommended): Simply copy & paste the
cat << 'EOF' ... EOFcommand block below directly into your Cloud Shell terminal. It creates and savesapp.pyautomatically in 1 second! - π Manual Way (If you want to edit code):
- Open editor:
nano app.py - Paste code:
Ctrl+V(or right-click Paste) - Save:
Ctrl+Othen pressEnter - Exit:
Ctrl+X - (Or click the graphical Open Editor π button in Cloud Shell).
- Open editor:
cat << 'EOF' > app.py
from http.server import HTTPServer, BaseHTTPRequestHandler
class SimpleHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
html = """
<!DOCTYPE html>
<html>
<head>
<title>GCP Container Lab</title>
<style>
body { font-family: sans-serif; background: #0f172a; color: #f8fafc; text-align: center; padding: 50px; }
.box { background: #1e293b; padding: 30px; border-radius: 12px; display: inline-block; box-shadow: 0 10px 25px rgba(0,0,0,0.5); }
h1 { color: #38bdf8; }
</style>
</head>
<body>
<div class="box">
<h1>π³ Hello from Docker Container on Google Cloud!</h1>
<p>Packaged and delivered safely via <strong>Artifact Registry</strong>.</p>
</div>
</body>
</html>
"""
self.wfile.write(html.encode('utf-8'))
if __name__ == '__main__':
server = HTTPServer(('0.0.0.0', 8080), SimpleHandler)
print("Server running on port 8080...")
server.serve_forever()
EOF
Anatomy Breakdown: What is happening in app.py line-by-line?
| Code Line | What It Does In Plain English |
|---|---|
from http.server import HTTPServer, BaseHTTPRequestHandler | Imports Python's built-in web server library (no external pip install required!). |
class SimpleHandler(BaseHTTPRequestHandler): | Defines a custom handler that teaches Python how to respond to web browser requests. |
def do_GET(self): | Automatically runs whenever a user opens our URL in their browser (an HTTP GET request). |
self.send_response(200) | Sends standard HTTP 200 OK status code to tell the browser "Success! The page is ready." |
self.send_header('Content-type', 'text/html') | Tells the browser to interpret the incoming content as an HTML webpage. |
self.end_headers() | Marks the end of HTTP header instructions. |
html = """...""" | The actual HTML/CSS code defining the webpage layout, dark theme colors, and headline. |
self.wfile.write(html.encode('utf-8')) | Converts the HTML text into bytes and sends it across the network to the browser. |
server = HTTPServer(('0.0.0.0', 8080), SimpleHandler) | Starts the server listening on Port 8080 across all available network interfaces (0.0.0.0). |
server.serve_forever() | Keeps the server running indefinitely so it never shuts down while waiting for visitors. |
3.3: Create the Dockerfile (The Recipe)
(Shortcut: nano Dockerfile paste Ctrl+O Enter Ctrl+X or use 1-click command below)
cat << 'EOF' > Dockerfile
# Step 1: Use lightweight Python base image
FROM python:3.11-slim
# Step 2: Set working directory inside the container
WORKDIR /app
# Step 3: Copy our application code into the container
COPY app.py .
# Step 4: Expose port 8080
EXPOSE 8080
# Step 5: Command to run when the container starts
CMD ["python", "app.py"]
EOF
Anatomy Breakdown: What is happening in Dockerfile line-by-line?
| Dockerfile Instruction | What It Does In Plain English |
|---|---|
FROM python:3.11-slim | The Foundation: Downloads a clean, lightweight, official Linux image with Python 3.11 pre-installed. |
WORKDIR /app | The Workspace: Creates an internal folder named /app inside the container and navigates into it (cd /app). |
COPY app.py . | The Code Transfer: Copies app.py from our Cloud Shell into the container's /app directory (.). |
EXPOSE 8080 | The Door Opening: Informs Docker that our application communicates on network Port 8080. |
CMD ["python", "app.py"] | The Startup Trigger: The default command executed automatically when the container powers on. |
Step 4: Build & Test the Docker Image Locally
Now, let's compile our Dockerfile recipe into a real Container Image using Docker in Cloud Shell:
docker build -t hello-app:v1 .
Anatomy Breakdown: What does docker build do?
docker build: Tells Docker to read ourDockerfileand package everything into an image.-t hello-app:v1: Tags (names) the imagehello-appwith version numberv1..(the period at the end): Specifies the build contextβtells Docker to look forDockerfileandapp.pyin the current directory.
Let's test running our container locally inside Cloud Shell:
# 1. Run container in background on port 8080
docker run -d -p 8080:8080 --name test-app hello-app:v1
# 2. Test with curl
curl http://localhost:8080
# 3. Stop and remove the test container
docker stop test-app && docker rm test-app
Anatomy Breakdown: What does docker run do?
-d(Detached Mode): Runs the container in the background so your terminal remains free to type commands.-p 8080:8080(Port Mapping): Maps[Cloud Shell Port 8080]:[Container Internal Port 8080]. When traffic hits Cloud Shell on port 8080, Docker redirects it directly into the container!--name test-app: Assigns a human-friendly name to the running container instance.hello-app:v1: The specific image blueprint to launch.
Step 5: Tag & Push Your Container to Artifact Registry
To push our container image to Google Cloud, we must tag it with the exact Artifact Registry path format:
1. Authenticate Docker with Google Cloud
Run this command so Docker has permission to upload directly to your GCP repository:
gcloud auth print-access-token | docker login -u oauth2accesstoken --password-stdin https://asia-south1-docker.pkg.dev
Anatomy Breakdown: What does this command do?
gcloud auth print-access-token: Generates a temporary, secure OAuth2 security token for your Google account.|(Pipe): Hands that token directly to Docker's login system.docker login -u oauth2accesstoken --password-stdin ...: Authenticates Docker with Google's Artifact Registry servers safely without asking you to type your password!
2. Get Your Current Project ID & Tag the Image
PROJECT_ID=$(gcloud config get-value project)
docker tag hello-app:v1 asia-south1-docker.pkg.dev/$PROJECT_ID/my-docker-repo/hello-app:v1
Anatomy Breakdown: What does docker tag do?
- It attaches an official shipping label (full URL address) to our local image
hello-app:v1so Docker knows exactly which cloud region (asia-south1), project ID (gcp-lab-day07), and repository (my-docker-repo) to upload it to.
3. Push the Image to Artifact Registry
docker push asia-south1-docker.pkg.dev/$PROJECT_ID/my-docker-repo/hello-app:v1
Anatomy Breakdown: What does docker push do?
- Uploads the image layer by layer over encrypted HTTPS into your private Google Cloud Artifact Registry warehouse!
Alternative 1-Step Method: Cloud Build If you ever encounter local network hiccups in Cloud Shell, you can also build and push directly in one step using Google Cloud Build:
gcloud builds submit --tag asia-south1-docker.pkg.dev/$PROJECT_ID/my-docker-repo/hello-app:v1
Step 6: Verify Your Image in Artifact Registry
- Open your GCP Console Search for Artifact Registry Click Repositories.
- Click on
my-docker-repo. - You will see
hello-applisted! - Click on
hello-appto see your tagged versionv1, upload timestamp, and image size (around 50 MB).
π§Ή Step 7: Clean Up All Resources (Credit Safety Guarantee)
To ensure your GCP Free Trial costs remain at $0.00, clean up the lab repository and local files:
Option A: Web Console UI
- Go to Artifact Registry Repositories.
- Check the box next to
my-docker-repoClick Delete Typemy-docker-repoto confirm.
Option B: Cloud Shell CLI
# 1. Delete the Artifact Registry repository and all images inside
gcloud artifacts repositories delete my-docker-repo \
--location=asia-south1 \
--quiet
# 2. Clean up local test files and local docker images
rm -rf ~/gcp-container-lab
docker rmi hello-app:v1 2>/dev/null || true
Signal vs. Noise: Key Concepts & Noise Filter
Good to Know (Key Concepts)
- Dockerfile: Text recipe containing instructions to build an image.
- Container Image: Immutable frozen package containing your code, runtime, and libraries.
- Container: Running live instance of an image.
- Artifact Registry: Google's modern, secure storage repository for container images and language packages (
pkg.dev). - Image Tagging Format:
LOCATION-docker.pkg.dev/PROJECT_ID/REPO_NAME/IMAGE:TAG.
Noise Filter (Don't Memorize)
- Do NOT memorize complex Docker build optimization flags (like multi-stage build caching arguments or BuildKit syntax) right now.
- Do NOT worry about deprecated
gcr.iocommands; always usepkg.devwith Artifact Registry for modern projects.
Common Doubts & Interview Traps
Q1: What is the main difference between a Virtual Machine and a Container?
- Answer: A Virtual Machine virtualizes the physical hardware and runs a complete, heavy Guest Operating System. A Container virtualizes the Operating System, sharing the host OS kernel to run lightweight, isolated application packages in milliseconds.
Q2: What does it mean when we say a Container Image is "immutable"?
- Answer: "Immutable" means unchangeable. Once an image is built (e.g.,
hello-app:v1), its contents cannot be modified. If you change even one line of code, you build a new image with a new tag (e.g.,hello-app:v2). This guarantees 100% consistency across testing and production.
Q3: Can I run a Docker container without pushing it to Artifact Registry?
- Answer: On your local computer, yes. But to run containers serverlessly on Google Cloud (such as Google Cloud Run or GKE), Google Cloud needs a centralized cloud storage warehouse to pull the image fromβwhich is Artifact Registry.
Daily Practice Drill & Self-Check
Test your understanding of today's lesson:
// Try answering these:
1. Which file contains the step-by-step recipe to build a container image: a Dockerfile or a Container Image?
2. Why are containers able to boot up in milliseconds compared to Virtual Machines which take minutes?
3. What is the modern GCP service used to store Docker images: Container Registry or Artifact Registry?
π‘ Click for Solutions
- Dockerfile! It is the text file recipe.
- Because containers share the host OS kernel and do not need to boot up a full separate Guest Operating System!
- Artifact Registry (
pkg.dev)!
π Congratulations! You have completed Day 15 and your first step into Week 3: Serverless & Containers!
You now understand the magic of Docker containers, how images work, and how to store them securely in Google Cloud Artifact Registry.
Tomorrow on Day 16, we will use the container image you learned to build today to launch a serverless web app on Cloud Run - Serverless Container Apps!
β 14 - Hands-on Lab - High-Availability Web Cluster | Next Topic β 16 - Cloud Run - Serverless Container Apps