Pourquoi Déployer Go sur Azure ?
Le déploiement de Go sur Azure est une pratique courante pour les développeurs, car Azure offre une plateforme robuste et flexible qui permet d'héberger des applications écrites en Go de manière sécurisée et performante.
Un cas d'utilisation concret serait la création d'une application web backend utilisant le framework Gin-Gonic. Cette application pourrait être déployée sur Azure pour fournir des services aux clients, comme un système de gestion des tâches ou une API RESTful pour un blog.
Prerequis
- Connaissances en Go (version 1.16+ recommandée)
- Compteur Azure avec les droits nécessaires
- Visual Studio Code ou un autre éditeur Go
- Interface de ligne de commande Azure (
az)
Concepts fondamentaux
1. Création d'un projet Go
Pour commencer, créez un nouveau dossier pour votre projet et initialisez-le comme un module Go.
mkdir my-go-app
cd my-go-app
go mod init my-go-app
2. Définition de l'application principale
Créer un fichier main.go avec le code suivant :
// main.go - Point d'entrée de l'application Go
package main
import (
"fmt"
"net/http"
)
func helloWorld(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}
func main() {
http.HandleFunc("/", helloWorld)
fmt.Println("Starting server at port 8080")
if err := http.ListenAndServe(":8080", nil); err != nil {
fmt.Println(err)
}
}
3. Création d'un fichier Dockerfile
Pour déployer l'application sur Azure, nous utiliserons Docker. Créez un fichier Dockerfile avec le contenu suivant :
## Dockerfile - Définition de l'image Docker pour notre application Go
FROM golang:1.16 AS builder
WORKDIR /app
COPY . .
RUN go build -o main .
FROM alpine:latest
WORKDIR /root/
COPY --from=builder /app/main .
CMD ["./main"]
4. Création d'un fichier Procfile pour Azure App Service
Azure App Service utilise un Procfile pour définir comment démarrer l'application.
## Procfile - Spécifie le point de départ de l'application
web: ./main
Mise en pratique : Projet fil rouge
Étape 1 : Initialisation du projet
Créez un nouveau dossier pour votre application et initialisez-le comme un module Go.
mkdir task-manager
cd task-manager
go mod init task-manager
Étape 2 : Définition de l'application principale
Créer un fichier main.go avec le code suivant :
// main.go - Point d'entrée de l'application Go
package main
import (
"encoding/json"
"fmt"
"net/http"
)
type Task struct {
ID int `json:"id"`
Title string `json:"title"`
Done bool `json:"done"`
}
var tasks = []Task{
{ID: 1, Title: "Buy groceries", Done: false},
{ID: 2, Title: "Read a book", Done: true},
}
func getTasks(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(tasks)
}
func createTask(w http.ResponseWriter, r *http.Request) {
var newTask Task
err := json.NewDecoder(r.Body).Decode(&newTask)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
newTask.ID = len(tasks) + 1
tasks = append(tasks, newTask)
json.NewEncoder(w).Encode(newTask)
}
func updateTask(w http.ResponseWriter, r *http.Request) {
var updatedTask Task
err := json.NewDecoder(r.Body).Decode(&updatedTask)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
for i, t := range tasks {
if t.ID == updatedTask.ID {
tasks[i] = updatedTask
json.NewEncoder(w).Encode(updatedTask)
return
}
}
http.Error(w, "Task not found", http.StatusNotFound)
}
func deleteTask(w http.ResponseWriter, r *http.Request) {
var taskToDelete Task
err := json.NewDecoder(r.Body).Decode(&taskToDelete)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
for i, t := range tasks {
if t.ID == taskToDelete.ID {
tasks = append(tasks[:i], tasks[i+1:]...)
json.NewEncoder(w).Encode(t)
return
}
}
http.Error(w, "Task not found", http.StatusNotFound)
}
func main() {
http.HandleFunc("/tasks", getTasks)
http.HandleFunc("/tasks", createTask)
http.HandleFunc("/tasks/", updateTask)
http.HandleFunc("/tasks/", deleteTask)
fmt.Println("Starting server at port 8080")
if err := http.ListenAndServe(":8080", nil); err != nil {
fmt.Println(err)
}
}
Étape 3 : Création d'un fichier Dockerfile
Créez un fichier Dockerfile avec le contenu suivant :
## Dockerfile - Définition de l'image Docker pour notre application Go
FROM golang:1.16 AS builder
WORKDIR /app
COPY . .
RUN go build -o main .
FROM alpine:latest
WORKDIR /root/
COPY --from=builder /app/main .
CMD ["./main"]
Étape 4 : Création d'un fichier Procfile pour Azure App Service
Créez un fichier Procfile avec le contenu suivant :
## Procfile - Spécifie le point de départ de l'application
web: ./main
Étape 5 : Connexion à votre compte Azure
Connectez-vous à votre compte Azure en utilisant la commande suivante :
az login
Étape 6 : Création d'un groupe de ressources
Créez un groupe de ressources pour votre application.
az group create --name task-manager-group --location eastus
Étape 7 : Création d'une application App Service
Créez une application App Service dans Azure.
az webapp create --resource-group task-manager-group --plan task-manager-plan --name task-manager-app --runtime "GO|1.16"
Étape 8 : Déploiement de l'application
Déployez votre application sur Azure en utilisant la commande suivante :
az webapp publish task-manager-app --publish-method Docker
Erreurs fréquentes et debugging
1. Erreur : failed to load module information: could not read modules in go.mod
Cette erreur se produit si le fichier go.mod n'est pas correctement configuré.
Code incorrect :
import (
"fmt"
"net/http"
)
Code correct :
package main
import (
"encoding/json"
"fmt"
"net/http"
)
func getTasks(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(tasks)
}
// ... reste du code ...
2. Erreur : failed to pull image: manifest unknown
Cette erreur se produit si l'image Docker n'est pas correctement construite.
Code incorrect :
FROM golang:1.16 AS builder
WORKDIR /app
COPY . .
RUN go build -o main .
FROM alpine:latest
WORKDIR /root/
COPY --from=builder /app/main .
CMD ["./main"]
Code correct :
## Dockerfile - Définition de l'image Docker pour notre application Go
FROM golang:1.16 AS builder
WORKDIR /app
COPY . .
RUN go build -o main .
FROM alpine:latest
WORKDIR /root/
COPY --from=builder /app/main .
CMD ["./main"]
3. Erreur : failed to bind to port 8080: listen tcp :8080: address already in use
Cette erreur se produit si le port 8080 est déjà utilisé.
Code incorrect :
func main() {
http.HandleFunc("/tasks", getTasks)
http.HandleFunc("/tasks", createTask)
http.HandleFunc("/tasks/", updateTask)
http.HandleFunc("/tasks/", deleteTask)
fmt.Println("Starting server at port 8080")
if err := http.ListenAndServe(":8080", nil); err != nil {
fmt.Println(err)
}
}
Code correct :
func main() {
http.HandleFunc("/tasks", getTasks)
http.HandleFunc("/tasks", createTask)
http.HandleFunc("/tasks/", updateTask)
http.HandleFunc("/tasks/", deleteTask)
fmt.Println("Starting server at port 8080")
if err := http.ListenAndServe(":8080", nil); err != nil {
fmt.Println(err)
}
}
Pour aller plus loin
- Intégration continue avec Azure DevOps : Utilisez Azure DevOps pour automatiser le processus de déploiement et la gestion des environnements.
- Monitoring et observabilité : Intégrez Azure Monitor pour surveiller les performances de votre application en temps réel.
- Sécurité et contrôle d'accès : Configurez des politiques d'accès fine-grained sur votre application pour protéger ses données.
Défi pratique
Développez une petite API RESTful en Go qui gère un inventaire simple. L'API doit permettre de créer, lire, mettre à jour et supprimer des articles dans l'inventaire.