3
votes

service docker avec noeud unique de fichier de composition et image locale

J'ai donc besoin de mises à jour progressives avec docker sur mon serveur à nœud unique . Jusqu'à présent, j'utilisais docker-compose mais malheureusement, je ne peux pas réaliser ce dont j'ai besoin avec. En lisant le Web, docker-swarm semble être la voie à suivre.

J'ai trouvé comment exécuter une application avec plusieurs répliques sur un seul nœud en utilisant swarm:

docker stack deploy -c docker-compose.yml <name>

myapp: latest en cours de construction à partir de mon docker-compose.yml:

version: "3.6"

services:
  postgres:
    env_file:
      - ".env"
    image: "postgres:11.0-alpine"
    volumes:
      - "/var/run/postgresql:/var/run/postgresql"
  app:
    build: "."
    working_dir: /app
    depends_on:
      - "postgres"
    env_file:
      - ".env"
    command: iex -S mix phx.server
    volumes:
      - ".:/app"

volumes:
  postgres: {}
  static:
    driver_opts:
      device: "tmpfs"
      type: "tmpfs"

Malheureusement, cela ne fonctionne pas car il ne récupère pas la configuration du fichier docker-compose.yml : fichier .env , commande entrée etc.

En cherchant plus profondément, je trouve que l'utilisation de

docker service create --replicas 3 --name myapp-staging myapp_app:latest

créera un service en utilisant mon docker-compose.yml config.

Mais j'obtiens le message d'erreur suivant:

échec de la mise à jour du service myapp-staging_postgres: réponse d'erreur du démon: rpc error: code = InvalidArgument desc = ContainerSpec: une référence d'image doit être fournie

Il semble donc que je doive utiliser le registre et y pousser mon image pour qu'elle fonctionne. Je comprends ce besoin dans le cas d'une architecture à nœuds multiples, mais dans mon cas, je ne veux pas faire cela . (Les images porteuses sont lourdes, je ne veux pas que mon image soit publique, et après tout, l'image est ici , alors pourquoi devrais-je la déplacer sur Internet?)

Comment puis-je configurer mon service docker en utilisant l'image locale et la configuration écrites dans docker-compose.yml ?

Je pourrais probablement gérer mon chemin en utilisant les options de docker service create , mais cela n'utiliserait pas mon fichier docker-compose.yml donc ce ne serait pas être DRY ni maintenable, ce qui est important pour moi.

docker-compose est un excellent outil pour les développeurs, il est triste que nous devions plonger dans les outils DevOps pour atteindre ces fonctionnalités sous forme de mises à jour progressives. Toute cette architecture d'essaim semble trop compliquée pour mes besoins à ce stade.


2 commentaires

avez-vous essayé d'exécuter docker-compose -f docker-compose.yml up ?


De plus, dans vos services / application, vous n'avez pas spécifié d'image .. ce qui est probablement la raison de cette erreur ...


3 Réponses :


0
votes

Au lieu d'images docker, vous pouvez y utiliser directement le fichier docker. veuillez consulter l'exemple ci-dessous.

version: "3.7"
services:
  webapp:
    build: ./dir

L'erreur est due au fait que la composition n'a pas pu trouver d'image dans le registre public Docker. La méthode ci-dessus devrait résoudre votre problème.


3 commentaires

votre fichier docker doit être dans le répertoire dir.


Je ne vois pas comment déplacer le Dockerfile vers le répertoire dir changera quoi que ce soit. Ou ai-je raté quelque chose?


Par exemple, votre fichier docker-compose dans /user/docker-compose.yaml, alors gardez votre fichier docker dans / user / dir / dockerfile.



3
votes

Vous n'avez pas à utiliser des registres dans votre configuration de nœud unique. vous pouvez créer votre image "app" sur votre nœud à partir d'un fichier docker local en utilisant cette commande -cd dans le répertoire de votre fichier docker-

version: "3.6"

services:
  postgres:
    env_file:
      - ".env"
    image: "postgres:11.0-alpine"
    volumes:
      - "/var/run/postgresql:/var/run/postgresql"
  app:
    image: "my-app:latest"
    depends_on:
      - "postgres"
    env_file:
      - ".env"
    volumes:
      - ".:/app"

volumes:
  postgres: {}
  static:
    driver_opts:
      device: "tmpfs"
      type: "tmpfs"

Cela créera une image docker locale sur votre nœud , cette image n'est visible que pour votre nœud unique, ce qui est avantageux dans votre cas d'utilisation, mais je ne le recommanderais pas dans une configuration de production.

Vous pouvez maintenant modifier le fichier de composition pour qu'il soit:

docker build . -t my-app:latest

Et maintenant vous pouvez exécuter votre pile à partir de ce nœud et elle utilisera l'image de votre application locale et bénéficiera de l'utilisation de l'image [mises à jour - rollbacks ... etc]

J'ai une note latérale sur votre fichier de pile. Vous utilisez le même fichier env pour les deux services, veuillez noter que swarm recherchera le fichier ".env" relatif / à côté du fichier ".yml", donc si ce n'est pas intentionnel, veuillez réviser l'emplacement de vos fichiers env.

De plus, cette solution n'est réalisable que sur un cluster à un seul nœud et si vous mettez votre cluster à l'échelle, vous devrez utiliser un registre et des registres ne doivent pas nécessairement être public , vous pouvez déployer un registre privé sur votre cluster et seuls vos nœuds peuvent y accéder -ou vous pouvez le rendre public- l'accessibilité de votre registre est votre choix.

J'espère que cela vous aidera à résoudre votre problème.


2 commentaires

Merci pour votre réponse, je vais y aller! Donc feedback: cette solution n'est faisable que sur un seul cluster de nœuds => Oui, c'est exactement ma question :). Je ne recommanderais pas cela dans une configuration de production => Pourquoi? Pour le manque d'automatisation? si ce n'est pas intentionnel => J'ai fusionné postgres et les variables d'environnement de l'application à ce stade. Bref, pour l'instant je joue juste avec la configuration donc la sécurité n'est pas une chose ici (encore!).


Dans un environnement de production, vous aurez probablement un cluster à plusieurs nœuds et comme l'image est construite sur un nœud, les autres nœuds ne pourront donc pas extraire l'image et exécuter le service - à moins que vous ne le copiez manuellement, ce qui est marécageux et inefficace :) -. Et pour les fichiers de variables, la fusion des variables fonctionnera je pense :)) bonne chance.



0
votes

En gros, vous devez utiliser des images docker pour que la mise à jour progressive fonctionne dans docker swarm. Je voudrais également préciser que vous pouvez héberger un registre privé et l'utiliser au lieu d'un registre public.

Explication détaillée: Lorsque vous essayez de mettre à jour en continu le fonctionnement de docker swarm, il voit s'il y a un changement dans l'image qui est utilisée pour le service si tel est le cas, alors docker swarm planifie la mise à jour du service en fonction de la configuration des critères de mise à jour et fonctionnera dessus. Disons qu'il n'y a pas de changement dans l'image alors que se passe-t-il? Docker n'appliquera simplement pas la mise à jour progressive. Techniquement, vous pouvez spécifier l'indicateur --force pour forcer la mise à jour du service, mais il ne fera que redéployer le service.

Par conséquent, créez un dépôt local et stockez les images dans celui-ci et utilisez ce nom d'image dans le fichier docker-compose à utiliser pour un essaim. Vous pouvez sécuriser le dépôt en utilisant SSL, les informations d'identification de l'utilisateur, les restrictions de pare-feu qui dépendent de vous. Consultez ceci pour plus de détails sur le déploiement du serveur de registre docker.

Corrections dans votre fichier de rédaction:

  1. Puisque la pile de docker utilise l'image pour créer le service, vous devez spécifier image: "" dans le service app comme cela est fait dans postgres code> service. Comme vous l'avez mentionné, l'instruction nom-image de l'instruction build est obligatoire car docker-compose ne sait pas comment nommer l'image. Référence.
  2. Un serveur de registre est nécessaire si vous prévoyez de déployer l'application sur plusieurs serveurs. Depuis que vous l'avez mentionné, c'est un déploiement à un seul nœud, il suffit d'avoir l'image extraite / construite sur le serveur. Mais l'approche de registre privé est la méthode recommandée.
  3. Ma recommandation est de ne pas regrouper tous les services dans un seul fichier docker-compose. La raison en est que lorsque vous déployez / détruisez à l'aide du fichier docker-compose, tous les services seront supprimés. C'est une sorte de couplage serré. Bien sûr, je comprends que tous les autres services dépendent de DB. dans de tels cas, assurez-vous que le service DB est activé avant les autres services.
  4. Au lieu de spécifier le fichier env, faites-le comme une partie de l'instruction du fichier Docker. copiez le fichier env et sourcez-le dans le point d'entrée ou utilisez la variable ENV pour le définir.

Aussi juste une mise à jour: Stack est juste pour regrouper les services dans swarm.

Donc, votre fichier de composition doit être:

docker-compose build

docker-compose push (optional needed to push the image into registry in case registry is used)]

docker stack deploy -c docker-compose.yml <stackname>

Dockerfile: p>

from baseimage:tag
ENV a $a
ENV b $b
ENV c $c # here a,b,c has to be exported in the shell befire building the image.
ENTRYPOINT ./file-to-run

Autre Dockerfile:

from baseimage:tag
COPY .env /somelocation
# your further instructions go here
RUN ... & \
    ... & \
    ... && chmod a+x /somelocation/.env
ENTRYPOINT source /somelocation/.env && ./file-to-run

Et vous devrez peut-être exécuter

version: "3.6"

services:
  postgres:
    env_file:
      - ".env"
    image: "postgres:11.0-alpine"
    volumes:
      - "/var/run/postgresql:/var/run/postgresql"
  app:
    build: "."
    image: "image-name:tag" #the image built will be tagged as image-name:tag
    working_dir: /app # note here I've removed .env file
    depends_on:
      - "postgres"
    command: iex -S mix phx.server
    volumes:
      - ".:/app"

volumes:
  postgres: {}
  static:
    driver_opts:
      device: "tmpfs"
      type: "tmpfs"

REMARQUE: Même si vous pouvez créer les services comme indiqué ici par @ M.Hassan J'ai expliqué la méthode recommandée idéale.


0 commentaires