Le but de ce chapitre est de créer une application conteneurisée avec Cloud Run.

CloudRun est un service managé qui permet de faire fonctionner une instance de conteneur sans avoir à gérer l’infrastructure d’exécution et d’orchestration des conteneurs.

Notez que cet exemple est à but pédagogique et se veut simple. Sinon ce n’est pas une bonne pratique d’exposer un conteneur directement sur Internet. La bonne démarche est d’utiliser un Load Balancer (et si possible un WAF pour filtrer les attaques Web).

Côté infrastructure / Terraform

Créer un dépôt Artifact Registry

# gar.tf
resource "google_artifact_registry_repository" "registry" {
  location = var.region
  repository_id = "docker-registry"
  format = "docker"
}

Le service Cloud Run

Dans un premier temps, on crée le service Cloud Run avec une image d’exemple (hello-app) :

# cloudrun.tf

# Enable CR API
resource "google_project_service" "gcrapi" {
  service = "run.googleapis.com"
  disable_on_destroy = true
}

# Create a Hello instance
resource "google_cloud_run_service" "myservice" {
  depends_on = [google_project_service.gcrapi]
  name = "myservice"
  location = var.location

  template {
    spec {
      containers {
        image = "gcr.io/google-samples/hello-app:1.0"
      }
    }
  }

  traffic {
    percent         = 100
    latest_revision = true
  }

}

Créer un rôle IAM pour rendre le service visible publiquement :

resource "google_cloud_run_service_iam_member" "myservice_allusers" {
  service  = google_cloud_run_service.myservice.name
  location = var.region
  role     = "roles/run.invoker"
  member   = "allUsers"
}

Montrer l’adresse publique et tester

output "public-url" {
  value = google_cloud_run_service.myservice.status[0].url
}

Il ne reste plus qu’à regarder :

http://x.y.z.run.app

Côté application : CI/CD avec une image Docker perso

Oui, on va rapidement parler de CI/CD parce que l’on est dans le coeur des technos Devops/Cloud.

Ici on veut que les développeurs puissent créer et versionner des images Docker de leur application (CI) et qu’ils puissent les publier dans le registry Google pour que cette image puisse être déployée automatiquement dans Cloud Run (CD).

Partons d’une image simple : nextcloud, une application Web libre de Cloud privé, facile à déployer.

Création d’une image Docker

Concernant l’application Nextcloud, il y a déjà plein d’images et de Dockerfiles existants.

On peut se contenter de prendre l’image officielle ou d’en construire une personnalisée.

La construction d’images Docker est largement documentée dans ce blog, ici on va seulement prendre l’image du Docker Hub.

docker pull nextcloud:latest
docker run -d -p 8080:80 nextcloud

On vérifie : http://localhost:8080

Si tout va bien, on a donc un Nextcloud qui fonctionne tout seul.

Pousser l’image dans notre Artifact Registry Google

Avant de pouvoir pousser l’image, il faut y être autorisé.

Il y a plusieurs façons de s’authentifier, l’une d’elles utilise gcloud :

gcloud auth configure-docker europe-west9-docker.pkg.dev

Ensuite, il faut tagger l’image pour lui dire où elle doit aller :

# Le tag est sous cette forme :
docker tag my-nextcloud <region>-docker.pkg.dev/<project-id>/<registry-name>/<image-name>:<image-version>
# Exemple :
docker tag my-nextcloud europe-west9-docker.pkg.dev/monprojet/docker-registry/my-nextcloud:v1

Enfin, on pousse l’image :

docker push europe-west9-docker.pkg.dev/monprojet/docker-registry/my-nextcloud:v1

Utilisation de l’image perso dans le code Terraform

On peut créer des nouvelles variables pour se simplifier la vie :

# variables.tf
...
variable "registry" {
  default = "dockerregistry"
  type    = string
}

variable "image" {
  default = "my-nextcloud"
  type    = string
}

variable "img_version" {
  default = "v1"
  type    = string
}

Puis on appelle la bonne image :

# cloudrun.tf

# Create a Nextcloud instance
resource "google_cloud_run_service" "nxcl" {
  ...
  template {
    spec {
      containers {
        image = "${var.region}-docker.pkg.dev/${var.project_name}/${var.registry}/${var.image}:${var.img_version}"
      }
    }
  }
  ...

Quand on réapplique le Terraform, on peut à nouveau tester :

http://x.y.z.run.app