web-dev-qa-db-fra.com

Comment éditer du code dans un conteneur Docker en développement?

J'ai le code de tous mes sites Web sous /srv dans mes conteneurs.

Mon Dockerfile télécharge le code à l'aide de git et le fait partie de l'image pour un déploiement plus facile en production.

Mais alors comment éditer le code en cours de développement? Je pensais que l'utilisation de volumes était la solution, par exemple: -v /docker/mycontainer/srv:/srv. Mais il écrase le répertoire du conteneur. Si c'est la première fois que je l'exécute, il le vide car il n'y a rien dans l'hôte. Donc, tout ce que j'ai fait dans le Dockerfile s'est perdu.

Il existe également des répertoires et des fichiers à l'intérieur de /srv/myapp que je souhaite partager entre les différentes versions de mon application, par exemple: /srv/myapp/user-uploads. Il s'agit d'une pratique courante dans le développement Web professionnel.

Alors, que puis-je faire pour pouvoir faire toutes ces choses?:

  • éditer le code dans/srv en développement
  • partager/srv/myapp/user-uploads sur différentes versions
  • laissez Dockerfile télécharger le code. À mon avis, faire "git clone" ou "git pull" en dehors de Docker irait à l'encontre du but de Docker. De plus, il y a des choses que je ne peux pas exécuter dans l'hôte, comme les migrations de base de données ou d'autres scripts spécifiques à l'application.

Existe-t-il un moyen de faire un montage à volume inversé? Je veux dire que le conteneur écrase l'hôte, au lieu du contraire.

Je pense qu'une solution pourrait être de copier/srv dans /srv.deployment-copy avant d'exécuter le démon du conteneur. Et puis, lorsque j'exécute le démon, vérifiez si /srv.deployment-copy existe et copiez tout dans/srv. De cette façon, je peux utiliser/srv en tant que volume et toujours pouvoir y déployer du code avec le Dockerfile. J'utilise déjà des alias pour toutes les commandes de docker, donc l'automatisation ne sera pas un problème. Qu'est-ce que tu penses?

60
ChocoDeveloper

J'ai trouvé que la meilleure façon de modifier le code en développement est d'installer tout comme d'habitude (y compris le clonage du référentiel de votre application), mais déplacez tout le code dans le conteneur pour dire /srv/myapp.deploy.dev. Ensuite, démarrez le conteneur avec un volume rw pour /srv/myapp, et un script init.d qui nettoie ce volume et copie le nouveau contenu à l'intérieur comme ceci:

rm -r /srv/myapp/*
rm -r /srv/myapp/.[!.]*
cp -r /srv/myapp.deploy.dev/. /srv/myapp
rm -r /srv/myapp.deploy.dev
13
ChocoDeveloper

Il existe une autre façon de démarrer le conteneur avec le volume d'un autre conteneur:

Regardez https://docs.docker.com/userguide/dockervolumes/
Création et montage d'un conteneur de volume de données

Si vous avez des données persistantes que vous souhaitez partager entre conteneurs, ou que vous souhaitez utiliser à partir de conteneurs non persistants, il est préférable de créer un conteneur de volume de données nommé, puis d'en monter les données.

Créons un nouveau conteneur nommé avec un volume à partager.

$ Sudo docker run -d -v /dbdata --name dbdata training/postgres echo Data-only container for postgres

Vous pouvez ensuite utiliser l'indicateur --volumes-from pour monter le volume/dbdata dans un autre conteneur.

$ Sudo docker run -d --volumes-from dbdata --name db1 training/postgres

Et un autre:

$ Sudo docker run -d --volumes-from dbdata --name db2 training/postgres

Une autre fonction utile que nous pouvons effectuer avec les volumes est de les utiliser pour les sauvegardes, les restaurations ou les migrations. Nous faisons cela en utilisant l'indicateur --volumes-from pour créer un nouveau conteneur qui monte ce volume, comme ceci:

$ Sudo docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata

=============

Je pense que vous ne devriez pas utiliser le montage de votre répertoire Host sur un conteneur. Mais vous pouvez utiliser des volumes avec tous ses pouvoirs. Vous pouvez éditer des fichiers dans des volumes en utilisant d'autres conteneurs avec un ensemble parfait de vos éditeurs et outils. Et contenez ce que votre application sera propre sans frais généraux.

La structure est:
-) Conteneur pour les données d'application
docker run -d -v /data --name data
-) Conteneur pour les binaires d'application
docker run -d --volumes-from data --name app1
-) Conteneur pour éditeurs et utilitaires de développement
docker run -d --volumes-from data --name editor

13
Mikl

Remarque: vous ne pouvez pas monter répertoire conteneur vers le répertoire hôte avec -v.

Je ne pense pas que vous ayez besoin de mangle/srv et /srv.deployment-copy. Si vous

Je pense que:

  • Vous devez utiliser le volume pour les données persistantes/partagées: -v /hostdir/user-uploads:/srv/myapp/user-uploads, ou vous pouvez utiliser conteneur de volume de données concept. Vous pouvez considérer cela comme une base de données soutenue par un système de fichiers qui est stockée sur l'hôte (conteneur de données uniquement) et le conteneur est autorisé à l'utiliser par -v.

  • Vous avez raison: pour le déploiement de production - vous pouvez créer l'image avec le code source (git clone), vous créez une image pour chaque version. Il ne devrait pas être nécessaire de modifier le code source en production.

  • pour environnement de développement - vous devez créer l'image sans code source ou vous pouvez masquer le répertoire du code source avec le volume en cas d'utilisation de la même image pour le déploiement/développement. Ensuite, git clonez le code source localement et utilisez le volume -v /hostdir/project/src:/srv/project pour partager le code source avec le conteneur. De préférence, vous devez partager le code source en lecture seule (:ro à la fin) et tous les fichiers temporaires ou intermédiaires doivent être stockés ailleurs dans le conteneur. J'ai des scripts de configuration (migration des données, reconstruction de certains fichiers de données d'index/cache, etc.) exécutés au démarrage du conteneur, avant le démarrage du service. Donc, chaque fois que je sens que j'ai besoin de fraîcheur re-init, Je viens de tuer le conteneur de développement et de l'exécuter à nouveau. Ou, je n'arrête pas l'ancien conteneur - j'en lance juste un autre.

6
Jiri

J'ai trouvé une belle façon de le faire en utilisant juste git:

CONTAINER=my_container
SYNC_REPO=/tmp/my.git
CODE=/var/www

#create bare repo in container
docker exec $CONTAINER git init --bare $SYNC_REPO

#add executable syncing hook that checks out into code dir in container
printf "#!/bin/sh\nGIT_WORK_TREE=$CODE git checkout -f\n" | \
docker exec -i $CONTAINER bash -c "tee $SYNC_REPO/hooks/post-receive;chmod +x \$_"

#use git-remote-helper to use docker exec instead of ssh for git
git remote add docker "ext::docker exec -i $CONTAINER sh -c %S% $SYNC_REPO"

#Push updated local code into docker
git Push docker master

Suppose que vous avez un git local avec le code. Git doit être installé dans un conteneur. Alternativement, vous pourriez probablement utiliser docker run et un conteneur de données avec un volume partagé avec git installé.

5
till

En supposant que git n'est pas le point d'entrée du conteneur, si git est installé dans votre conteneur docker, vous pouvez ssh dans le conteneur et exécuter le git clone/git pull. En raison de la façon dont le volume est partagé avec l'hôte, les modifications apportées du conteneur aux fichiers seront également apportées à l'hôte (en réalité, ce sont les mêmes fichiers).

Ici est une explication de la façon de rapidement ssh dans un conteneur.

2