civil-and-structural-engineering
Deploying Docker Containers on Google Cloud Platform with Gke
Table of Contents
Deploying Docker Containers on GKE: A Comprehensive Guide
Google Kubernetes Engine (GKE) provides a fully managed environment for deploying, managing, and scaling containerized applications using Kubernetes. When combined with Docker, it offers a robust platform for running cloud-native applications at scale. This guide walks through the entire process—from cluster creation to production deployment and beyond—while highlighting best practices and advanced configuration options.
Why GKE for Docker Workloads?
Running Docker containers directly on virtual machines can become unwieldy as your application grows. Kubernetes automates deployment, scaling, and management of containers across a cluster of machines. GKE removes the operational overhead of managing Kubernetes control planes, upgrades, and node health. You gain automatic load balancing, self-healing, rolling updates, and integration with other GCP services. For teams already using Docker, GKE provides a seamless migration path to orchestrated, production-grade deployments.
Prerequisites and Initial Setup
Before starting, ensure you have the following in place:
- Google Cloud account with billing enabled. New accounts qualify for a free tier trial with $300 in credits.
- Google Cloud SDK (gcloud) installed and configured. Authenticate with
gcloud auth loginand set your project usinggcloud config set project PROJECT_ID. - Docker installed on your local machine. Verify with
docker --version. - kubectl command-line tool for interacting with Kubernetes clusters. Install via
gcloud components install kubectl. - Basic familiarity with Docker commands and Kubernetes resource types (Pods, Deployments, Services).
Enable Required APIs
GKE and the Container Registry (or Artifact Registry) require explicit API enablement:
gcloud services enable container.googleapis.com
gcloud services enable containerregistry.googleapis.com
Replace containerregistry.googleapis.com with artifactregistry.googleapis.com if you prefer to use Artifact Registry (recommended for newer projects due to enhanced security and performance).
Step 1: Create a GKE Cluster
Clusters are the foundation of your Kubernetes environment. You can create one via the Cloud Console or the command line. The command below creates a standard cluster with two nodes in a specific zone:
gcloud container clusters create my-cluster \
--zone us-central1-a \
--num-nodes 2 \
--machine-type e2-medium
Cluster Configuration Options
- Zone vs. Region: For higher availability, use a regional cluster (
--region us-central1). Regional clusters replicate control plane and nodes across multiple zones. - Node Pools: Create specialized pools for different workload types. For example, a pool with GPU nodes for machine learning inference and a pool with general-purpose nodes for web servers.
- Autoscaling: Enable cluster autoscaling (
--enable-autoscaling --min-nodes 1 --max-nodes 5) to automatically adjust node count based on resource demands. - Network: Use a VPC-native cluster with alias IP ranges for better isolation and performance (
--enable-ip-aliasis default in newer versions).
Once the cluster is created, configure kubectl to use it:
gcloud container clusters get-credentials my-cluster --zone us-central1-a
Verify connectivity with kubectl get nodes. You should see the two nodes listed as ready.
Step 2: Build Your Docker Image
Prepare your application. For demonstration, use a simple web server (e.g., an Express.js app or Nginx). Create a Dockerfile:
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Build the image with a tag that matches your container registry's URL structure. GCR (Google Container Registry) uses the format gcr.io/<project-id>/<image-name>:<tag>:
docker build -t gcr.io/your-project-id/my-app:v1 .
If you are using Artifact Registry, the format differs based on your repository location. Example for a repository in us-central1:
docker build -t us-central1-docker.pkg.dev/your-project-id/my-repo/my-app:v1 .
Step 3: Push the Image to a Container Registry
Authentication with the registry is required before pushing. For GCR:
gcloud auth configure-docker
docker push gcr.io/your-project-id/my-app:v1
For Artifact Registry, first create a repository:
gcloud artifacts repositories create my-repo \
--repository-format docker \
--location us-central1
Then configure Docker:
gcloud auth configure-docker us-central1-docker.pkg.dev
docker push us-central1-docker.pkg.dev/your-project-id/my-repo/my-app:v1
Pushing may take a few minutes depending on image size. After successful push, you can verify the image in the Cloud Console under Container Registry or Artifact Registry.
Step 4: Deploy the Application to GKE
Kubernetes resources are defined in YAML files. Create a deployment.yaml that declares how many replicas of the container to run and which image to use. A basic example:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: gcr.io/your-project-id/my-app:v1
ports:
- containerPort: 80
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 5
Apply the deployment:
kubectl apply -f deployment.yaml
Check deployment status: kubectl get deployments. Wait until all replicas are ready.
Expose the Application with a Service
To make your application accessible outside the cluster, create a Service resource. For a web app, use type: LoadBalancer which provisions a Google Cloud TCP/UDP Load Balancer with a public IP:
apiVersion: v1
kind: Service
metadata:
name: my-app-service
spec:
type: LoadBalancer
selector:
app: my-app
ports:
- port: 80
targetPort: 80
Apply the service: kubectl apply -f service.yaml. Run kubectl get services my-app-service to see the external IP. Initially it may show <pending> while the load balancer is provisioned. Once ready, you can access the app via http://EXTERNAL_IP.
Scaling and Updating Deployments
One of GKE’s strengths is effortless scaling. To increase replicas:
kubectl scale deployment my-app --replicas=5
Or enable Horizontal Pod Autoscaler (HPA) based on CPU or memory:
kubectl autoscale deployment my-app --cpu-percent=80 --min=3 --max=10
For updates, change the image tag in your deployment YAML and apply again. GKE performs a rolling update, incrementally replacing pods to eliminate downtime. If something goes wrong, roll back with:
kubectl rollout undo deployment my-app
Advanced GKE Features
Persistent Storage
Stateful applications need persistent disks. Use PersistentVolumeClaims (PVCs) with GKE’s pd-ssd or pd-standard storage classes. GKE can automatically provision disks when a PVC is created. For databases, consider using regional persistent disks for higher availability.
Secrets and ConfigMaps
Store sensitive data like API keys in Kubernetes Secrets. Configuration data (e.g., environment variables) go in ConfigMaps. Mount them as volumes or inject them into environment variables. GKE integrates with Cloud Secret Manager for more advanced secret management.
Node Auto-Repair and Auto-Upgrade
By default, GKE enables node auto-repair (replaces unhealthy nodes) and node auto-upgrade (applies security patches). These features ensure your cluster remains healthy and up to date with minimal intervention.
Workload Identity
Use Workload Identity to allow your Kubernetes pods to authenticate to Google Cloud APIs using service accounts without storing long-lived credentials. This is the recommended method for accessing cloud resources from within the cluster.
Observability and Monitoring
GKE integrates with Cloud Monitoring and Logging to provide metrics, logs, and dashboards out of the box. You can view pod metrics, request latencies, and error rates from the Cloud Console. For distributed tracing, deploy Cloud Trace. To set up custom alerts, create alerting policies based on metrics like CPU utilization, memory pressure, or application-specific health checks.
Configuring Logging and Metrics
GKE ships container logs to Cloud Logging automatically. You can also install the metrics-server for HPA. For more granular monitoring, deploy Prometheus and Grafana using the marketplace or Helm charts. GKE also supports native sidecar logging if you need to forward logs to external systems.
CI/CD Integration
Automate the workflow of building, testing, and deploying to GKE. Cloud Build can build your Docker images, push them to Artifact Registry, and trigger a deployment to GKE in one pipeline. A sample cloudbuild.yaml:
steps:
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'us-central1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app:$COMMIT_SHA', '.']
- name: 'gcr.io/cloud-builders/docker'
args: ['push', 'us-central1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app:$COMMIT_SHA']
- name: 'gcr.io/cloud-builders/kubectl'
args:
- 'set'
- 'image'
- 'deployment/my-app'
- 'my-app=us-central1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app:$COMMIT_SHA'
env:
- 'CLOUDSDK_COMPUTE_ZONE=us-central1-a'
- 'CLOUDSDK_CONTAINER_CLUSTER=my-cluster'
Trigger this build on pushes to a Git repository. A more advanced pipeline can include integration tests and canary deployments.
Security Best Practices
- Use private clusters to avoid exposing your master endpoint to the public internet.
- Enable Binary Authorization to ensure only trusted images are deployed.
- Apply least privilege RBAC for service accounts and users.
- Scan images for vulnerabilities using Artifact Analysis or third-party tools before pushing to production.
- Keep container images small by using multi-stage builds and minimal base images (e.g.,
alpineordistroless) to reduce attack surface.
Troubleshooting Common Issues
Pod stuck in ImagePullBackOff: Verify the image tag exists in the registry and that the node has pull permissions. If using a private registry, create an imagePullSecrets.
Load Balancer external IP not assigned: Ensure your service type is LoadBalancer and that quotas for load balancers are not exhausted. Wait a few minutes—GKE provisions the LB asynchronously.
Insufficient node capacity: Increase node count or machine type. Check cluster autoscaler logs for scaling events.
Connection refused: Verify that your deployment pods have the correct containerPort and that the Service’s targetPort matches.
Conclusion
Deploying Docker containers on GKE provides a production-ready, scalable platform with minimal operational overhead. By following the steps outlined above—cluster creation, image building and pushing, deployment, exposure, and scaling—you can quickly get a containerized application running on Google Cloud. GKE’s deep integration with other GCP services, combined with its advanced features like workload identity, autoscaling, and automated upgrades, makes it an ideal choice for teams adopting cloud-native architectures. Start with a simple deployment, then gradually incorporate persistent storage, CI/CD pipelines, and security controls to build a robust, automated infrastructure.