[GO] Solution pour le serveur Gin inaccessible fonctionnant sur le conteneur Docker

Aperçu

J'ai essayé de déployer et d'exécuter un serveur API en utilisant le framework Web de Golang Gin sur un conteneur Docker, mais je n'ai pas pu accéder à l'API. J'ai été troublé pendant assez longtemps.

En conséquence, j'ai trouvé que c'était un problème d'écriture du code du serveur Gin, mais j'écrirai la solution ici au cas où.

À propos, cette erreur s'est produite sur le serveur Ubuntu (t2.small) sous Windows 10 et AWS (bien que l'environnement d'exécution ne semble pas avoir grand-chose à voir avec l'apparition de cette erreur).

Statut

J'essayais de configurer un serveur API en utilisant Gin. Puisqu'il est encore au stade de la construction de l'environnement, le code est un simulacre comme celui ci-dessous.

package main

import (
	"log"
	"os"
	"github.com/gin-gonic/gin"
)

func main() {
	logConfig()

	r := gin.Default()
	r.GET("/accounting-api", func(c *gin.Context) {
		log.Println("GET")
		c.JSON(200, gin.H{
			"state": "success",
		})
	})
	r.DELETE("/accounting-api", func(c *gin.Context) {
		log.Println("DELETE")
		c.JSON(200, gin.H{
			"state": "success",
		})
	})
	log.Println("Start Server")
	r.Run()
}

func logConfig() {
	logFile, _ := os.OpenFile("log/log.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	log.SetOutput(logFile)
	log.SetFlags(log.LstdFlags | log.Lmicroseconds | log.Lshortfile)
	log.SetPrefix("[LOG] ")
}

C'est un serveur qui renvoie simplement le json {" state ":" success "} lorsqu'une requête pour un chemin particulier arrive avec la méthode GET ou DELETE.

Et le Dockerfile pour exécuter ce serveur est ci-dessous.

FROM golang:alpine
RUN apk update && apk add --no-cache git
RUN go get -u github.com/gin-gonic/gin && mkdir /usr/src && mkdir /usr/src/api
COPY ./api /usr/src/api
WORKDIR /usr/src/api
CMD ["go","run","main.go"]

Puisque le fichier Go ci-dessus, etc. se trouve dans le répertoire appelé ʻapi sur l'hôte, copiez-le sur le conteneur et démarrez le serveur. J'ai construit ce Dockerfile avec le nom ʻapi et l'ai lancé avec la commande suivante.

docker run -p 8083:8080 api

Mappage du port «8083» sur l'hôte vers le port «8080» sur le conteneur. Lorsque vous exécutez la commande ci-dessus, la sortie suivante sera sortie et vous pourrez confirmer que le serveur Gin est opérationnel.

[GIN-debug] GET    /accounting-api           --> main.main.func1 (3 handlers)
[GIN-debug] DELETE /accounting-api           --> main.main.func4 (3 handlers)
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on localhost:8080

Je n'ai pas spécifié de port, donc il fonctionne sur le port 8080 par défaut. À première vue, cela semble fonctionner correctement, mais lorsque j'essaie d'accéder à http: localhost: 8083 avec curl du côté hôte, j'obtiens l'erreur suivante.

curl: (52) Empty reply from server

Ce que j'ai essayé pour résoudre l'erreur

1. Entrez dans le conteneur et vérifiez si vous pouvez accéder à l'API

Tout d'abord, assurez-vous que le programme Go s'exécute réellement sur le conteneur. Allons à l'intérieur du conteneur docker lancé à cet effet.

#Allez dans le conteneur en cours d'exécution du serveur api
docker exec -it api /bin/ash

L'Alpine sur laquelle ce conteneur est basé n'avait pas / bin / bash, donc utilisez / bin / ash. Tapez ensuite la commande suivante pour voir si le programme fonctionne correctement.

#Puisque curl n'est pas inclus en premier lieu, installez-le
apk add --no-cache curl
#Juste au cas où, désactivez le proxy et accédez au serveur api avec curl
curl -x "" http://localhost:8080/accounting-api

Voici le résultat de l'exécution de curl.

{"state": "success"}

Les résultats s'améliorent. Donc, il semble que le programme du serveur Gin fonctionne correctement sur le conteneur.

2. EXPOSEZ le port dans le Dockerfile

Le programme semble fonctionner sur le conteneur, donc je soupçonne ensuite que la partie de mappage de port ne fonctionne pas. Quand je l'ai recherché, il semble que la commande ʻEXPOSE` puisse être écrite dans le Dockerfile, je vais donc l'ajouter.

EXPOSE 8080

Faire cela n'a pas aidé.

En premier lieu, selon les Documents officiels, la commande ʻEXPOSE ne fait rien et informe le développeur qu'elle ouvrira un port spécifique. Il semble qu'il n'a qu'un rôle similaire à celui d'un document pour. Donc, le simple fait d'ajouter la commande ʻEXPOSE ne pouvait pas résoudre le problème.

3. Vérifiez les paramètres du pare-feu Windows

Étant donné que le développement était essentiellement effectué avec Docker sur Windows, j'ai examiné les paramètres du pare-feu Windows, mais cela n'avait pas non plus de sens.

En premier lieu, lorsque j'ai construit ce Dockerfile sur Ubuntu et l'ai lancé, je ne pouvais pas non plus accéder au serveur API, donc j'ai su dès le début que ce n'était pas dû au pare-feu Windows.

4. (C'est la solution) Spécifiez le port côté serveur Gin

Dans le programme Go, j'ai essayé de spécifier le port dans la partie qui démarre le serveur GIn, et maintenant je peux bien y accéder. Plus précisément, c'est la partie suivante.

r := gin.Default()
r.Run(":8080")

Je m'en fichais car il démarre avec 8080 par défaut même si je ne spécifie rien, mais cela semble inutile si je ne le spécifie pas correctement.

Je ne sais pas pourquoi le port est mauvais par défaut et doit être explicitement indiqué. Je l'ajouterai quand je le comprendrai.

Recommended Posts

Solution pour le serveur Gin inaccessible fonctionnant sur le conteneur Docker
Créer un serveur CGI fonctionnant sur Python 3 sur Docker
Essayez d'exécuter tensorflow sur Docker + anaconda
Conseils pour exécuter Go avec Docker
Démarrez le conteneur Docker lors de l'exécution de Pytest
Exécutez Matplotlib sur un conteneur Docker
Dockerfile: installer Docker sur un serveur Linux
Exécutez matplotlib sur un conteneur Windows Docker
Entrez dans stdin du conteneur Docker en cours d'exécution