Développer et tester des API connectées localement à une base de données n'est pas une blague. La base de données devient souvent un problème. Cependant, en utilisant Docker, le processus devient plus facile et beaucoup plus simple, ce qui facilite la réplication. Dans ce blog, nous verrons comment Dockeriser une API Golang avec une base de données MySQL, la rendant également prête pour Docker Compose
Pour la démo, j'ai créé cette API RESTful Golang. Nous pouvons effectuer des opérations CRUD telles que créer, supprimer et modifier des planifications dans la base de données MySQL. Nous pouvons en apprendre davantage sur les points de terminaison, les méthodes, etc. dans le projet README. Nous n'entrerons pas trop dans le fonctionnement de l'API, car notre objectif principal est de nous concentrer sur la partie Dockerisation.
Pour Dockerzing une application, nous devons créer un Dockerfile. Laissez-moi vous dire qu'il existe des centaines de façons d'écrire un Dockerfile, et qu'il n'y a rien de mal ou de bien, chaque individu/entreprise a son propre ensemble de pratiques et sa propre façon d'écrire. Dans notre cas, nous suivrons quatre des meilleures pratiques de notre Dockerfile pour obtenir une image meilleure et optimisée, plus petite et plus sécurisée. Comprenons les 4 pratiques et pourquoi nous les implémentons avant de nous lancer dans l'écriture d'un Dockerfile.
Utiliser des images de base plus claires : Pour presque toutes les langues, il existe une version plus légère de l'image. Par plus léger, je ne veux pas dire quelques mégaoctets de moins, il peut être 10 fois plus petit, la raison pour laquelle il est plus léger est qu'il ne contient pas de dépendances inutiles, ce qui le rend plus petit et plus sécurisé. Oui, plus de dépendances entraînent plus de risques de sécurité. nous aurons une version bullseye et alpine pour le node, Golang, etc.
Builds en plusieurs étapes : Ils sont l'un des super pouvoirs de Docker, ils nous permettent d'exécuter les étapes de construction en parallèle et nous permettent également de créer une image finale en copiant les fichiers et les éléments nécessaires des autres étapes et ne disposant que des éléments nécessaires à l'exécution de notre programme.
Créer un binaire : De nombreux langages prennent en charge la création de binaires à partir du code source, ce qui le rend plus petit et beaucoup plus facile à exécuter car nous n'avons pas besoin de gérer le code source complet. De plus, nous pouvons courir dans n'importe quel environnement, quelle que soit la barrière linguistique.
Décomposer les calques : Comme nous le savons, chaque instruction d'un Dockerfile est une couche, et décomposer les calques est un bon moyen d'accélérer notre construction. Par exemple, si nous copions tous les fichiers (ainsi que le fichier de dépendances à installer) à partir de la source, puis installons les dépendances, même si nous n'avons apporté aucune modification aux dépendances, chaque fois que nous reconstruisons une image, elle sera copiez tous les fichiers et installez les dépendances. Pour surmonter cela, nous les divisons en plusieurs couches et pouvons copier le fichier de dépendances en une seule étape et l'installer. Et à l’étape suivante, nous pouvons copier tous les fichiers. Désormais, lorsque nous modifions le code et reconstruisons cette fois, seule la couche où nous copions tous les fichiers sera reconstruite, laissant l'étape de dépendance (qui est mise en cache car il n'y a aucune modification). Nous pouvons également voir un exemple dans le Dockerfile ci-dessous. Nous écrivons Dockerfile de telle manière que les éléments qui changent le moins, comme l'image de base, les dépendances, etc., seront selon une approche de haut en bas.
Voici donc le Dockerfile que nous avons créé pour notre API Go.
# Build Stage FROM golang:alpine3.20 AS builder WORKDIR /build COPY go.mod go.sum ./ RUN go mod download COPY . . RUN go build -o /app . # Final Stage FROM alpine:3.20 COPY --from=builder /app /app CMD ["/app"]
Dans le FROM, nous pouvons voir que nous avons utilisé une version golang:alpine comme image de base au lieu d'utiliser une version golang à part entière et de nommer le générateur d'étapes, le nom/l'étiquette nous aidera à copier les fichiers d'une étape vers un autre. Après cela, nous avons créé un répertoire de travail. Ensuite, au lieu de copier tous les fichiers ensemble, nous avons simplement copié go.mod et go.sum et installé les dépendances (j'en ai expliqué la raison ci-dessus dans le point Décomposer les couches).
Maintenant, une fois les dépendances installées, nous copions les fichiers restants. Ensuite, nous créons un binaire à partir de notre code source en exécutant go build et en nommant le binaire avec l'indicateur de sortie -o à l'emplacement actuel.
Maintenant, ici les choses deviennent intéressantes, dans la phase finale, nous n'avons pas besoin d'une image Golang ou autre, nous pouvons utiliser une image de base Alpine car nous avons maintenant un binaire, et nous pouvons fonctionner sur n'importe quel système Linux, quelle que soit la programmation. spécificités linguistiques. À l'étape suivante, nous pouvons copier le binaire de l'étape de création vers l'étape finale et exécuter le binaire.
C'est tout. C'est ainsi que Dockerzie notre application et nous pouvons encore améliorer le Dockerfile en introduisant les meilleures pratiques telles que la création d'un utilisateur et l'exécution en tant que non-root, etc. Nous pouvons maintenant créer une image avec le Dockerfile et l'exécuter, puis nous connecter à la télécommande ou serveur MySQL local en fournissant les informations d'identification dont il a besoin, puis en accédant à ces points de terminaison d'API.
But, we will not stop here we will take a step further, and we will also run a MySQL server in a container and connect with our app. But, one point to note here is we can run a spin of a MySQL container and connect our API container to that, but there is so much manual work and long commands to type in the terminal, and things can go wrong. To overcome this we will use Docker Compose instead to make our life easier.
Let's create a file called compose.yml and use the blow config.
services: app: container_name: go-api build: context: . dockerfile: Dockerfile image: go-api ports: - 8080:8080 environment: - DB_HOST=mysql - DB_PORT=3306 - DB_USER=user - DB_PASSWORD=password - DB_NAME=my-database depends_on: mysql: condition: service_healthy networks: - go-network mysql: container_name: go-mysql image: mysql:9.0 environment: - MYSQL_ROOT_PASSWORD=password - MYSQL_USER=user - MYSQL_PASSWORD=password volumes: - dbdata:/var/lib/mysql networks: - go-network healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 10s timeout: 5s retries: 3 volumes: dbdata: networks: go-network: driver: bridge
It's a pretty basic configuration, but a couple of key things I want to mention is that if we see DB_HOST is mysql, there is no localhost or ip because in compose services communicate with other services by the service name. This is out-of-the-box networking provided by Docker Compose.
Another point, it often happens when working with Docker Compose where we have two services: an app and a database, and the app service starts first and crashes because the database isn't ready when the app tries to connect. To overcome this, we set up a healthcheck for the database to confirm its readiness. Then, in our app service, we can use depends_on with a condition to ensure the app only starts when the database service is healthy.
Now when we do Docker compose for 1st time, we might encounter an error saying permission denied because it doesn't have permission as well as a database with the name my_database, so we need to both by execing into the container.
Even though our app has crashed the DB is still up and running. We can check by doing docker ps.
Now exec into the container by doing docker exec -it
mysql -u root -p
It will ask for the password, enter the password you mentioned in the compose.yml file. Once we log in, we can create a database. Create a database with the same name specified in the compose file. In my case, it's my_database. Execute the below command:
CREATE DATABASE my_database;
Now to give the right privileges and flush it execute the below command.
GRANT ALL PRIVILEGES ON my_database.* TO 'user'@'%'; FLUSH PRIVILEGES;
Once we are done, we need to stop the running compose service and restart again by doing docker compose up
That's it for this blog. I'm glad you're still reading and made it to the end—thank you so much for your support and reading. I sometimes share tips on Golang on Twitter. You can connect with me there.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!