Je travaille donc sur un fichier de composition de docker pour déployer mon serveur Web Go. Mon serveur utilise mongo. J'ai donc ajouté un conteneur de volumes de données et le service Mongo dans docker compose . Ensuite, j'ai écrit un fichier Docker afin de construire mon projet Go et de l'exécuter.
Cependant, il y a une autre étape à faire. Une fois mon projet compilé, je dois exécuter la commande suivante: ./my-project -setup
Cela ajoutera quelques informations nécessaires à la base de données, et les informations ne devront être ajoutées qu'une seule fois . Je ne peux cependant pas ajouter cette étape au fichier Docker (dans le processus de construction) car mongo doit déjà être démarré .
Alors, comment puis-je y parvenir? Même si je redémarre le serveur et que je lance à nouveau docker-compose up
, je ne veux pas que cette commande soit exécutée à nouveau.
Docker me manque un peu de compréhension, car je ne comprends pas tout ce qui concerne les conteneurs de volumes de données (s'agit-il simplement de conteneurs arrêtés qui montent un volume?) . puis exécutez docker-compose up
, quelles commandes seront exécutées? Va-t-il simplement démarrer le même conteneur qui était maintenant arrêté avec le CMD donné?
En tout cas, voici mon docker-compose.yml:
version: '2'
services:
mongodata:
image: mongo:latest
volumes:
- /data/db
command: --break-mongo
mongo:
image: mongo:latest
volumes_from:
- mongodata
ports:
- "28001:27017"
command: --smallfiles --rest --auth
my_project:
build: .
ports:
- "6060:8080"
depends_on:
- mongo
- mongodata
links:
- mongo
Et voici mon Dockerfile pour construire mon image de projet:
FROM golang
ADD . /go/src/my_project
RUN cd /go/src/my_project && go get
RUN go install my_project
RUN my_project -setup
ENTRYPOINT /go/bin/my_project
EXPOSE 8080
Je suggère d'ajouter un script entrypoint à votre conteneur; dans ce script de point d'entrée, vous pouvez vérifier si la base de données a été initialisée et, dans le cas contraire, effectuer les étapes requises.
Comme vous l'avez remarqué dans votre question, l'ordre dans lequel les services/conteneurs sont démarrés ne doit pas être pris pour acquis, il est donc possible que votre conteneur d'applications soit démarré avant le conteneur de base de données, le script doit donc en tenir compte. .
A titre d'exemple, jetez un coup d'œil à l'image officielle de WordPress, qui effectue une initialisation unique de la base de données dans son script entrypoint. Le script tente de se connecter à la base de données (et tente à nouveau si la base de données ne peut pas encore être contactée) et vérifie si une initialisation est nécessaire. https://github.com/docker-library/wordpress/blob/df190dc9c5752fd09317d836bd2dcd09ee379a5/Apache/docker-entrypoint.sh#L146-L171
REMARQUE
Je remarque que vous avez créé un "conteneur de données uniquement" auquel attacher votre volume. Depuis Docker 1.9, docker dispose d’une gestion des volumes, y compris des noms de volumes. De ce fait, vous n’avez plus besoin d’utiliser des conteneurs "données uniquement".
Vous pouvez supprimer le conteneur contenant uniquement des données de votre fichier de composition et modifier votre service Mongo pour qu’il ressemble à ceci;
mongo:
image: mongo:latest
volumes:
- mongodata:/data/db
ports:
- "28001:27017"
command: --smallfiles --rest --auth
Cela devrait créer un nouveau volume, nommé mongodata
s'il n'existe pas, ou réutiliser le volume existant avec ce nom. Vous pouvez répertorier tous les volumes à l'aide de docker volume ls
et supprimer un volume avec docker volume rm <some-volume>
si vous n'en avez plus besoin.
Vous pouvez essayer d'utiliser ONBUILD
instruction :
L'instruction ONBUILD
ajoute à l'image une instruction de déclenchement à exécuter ultérieurement, lorsque l'image est utilisée comme base pour une autre construction. Le déclencheur sera exécuté dans le contexte de la construction en aval, comme s'il avait été inséré immédiatement après l'instruction FROM
dans la Dockerfile
en aval.
Toute instruction de construction peut être enregistrée en tant que déclencheur.
Ceci est utile si vous construisez une image qui servira de base pour créer d'autres images, par exemple un environnement de construction d'application ou un démon pouvant être personnalisé avec une configuration spécifique à l'utilisateur.
Par exemple, si votre image est un générateur d’application Python réutilisable, il faudra ajouter le code source de l’application dans un répertoire particulier et éventuellement appeler un script de construction after that. Vous ne pouvez pas simplement appeler ADD
et RUN
maintenant, car vous n’avez pas encore accès au code source de l’application, qui sera différent pour chaque construction d’application. Vous pouvez simplement fournir aux développeurs d’applications une variable Dockerfile
à copier-coller dans leur application, mais c’est inefficace, source d’erreurs et difficile à mettre à jour car elle se mélange au code spécifique à l’application.
La solution consiste à utiliser ONBUILD
pour enregistrer les instructions préalables à exécuter ultérieurement, au cours de la phase de construction suivante.
Voici comment ça fonctionne:
ONBUILD
, le générateur ajoute un déclencheur aux métadonnées de l'image en cours de construction. L'instruction n'affecte pas par ailleurs la construction actuelle.OnBuild
. Ils peuvent être inspectés avec la commande docker inspect
.FROM
. Dans le cadre du traitement de l'instruction FROM
, le générateur en aval recherche les déclencheurs ONBUILD
et les exécute dans le même ordre dans lequel ils ont été enregistrés. Si l'un des déclencheurs échoue, l'instruction FROM
est abandonnée, ce qui entraîne l'échec de la construction. Si tous les déclencheurs réussissent, l'instruction FROM
se termine et la construction se poursuit normalement.Votre application a besoin d'un état initial pour fonctionner. Cela signifie que vous devriez:
Vous pouvez écrire un programme pour vérifier l’état actuel de la base de données (ici, je vais utiliser le script bash mais ce peut être tout autre programme linguistique):
RUN if $(./check.sh); then my_project -setup; fi
Dans mon cas, si le script renvoie 0 (statut de sortie réussi), la commande setup
sera appelée.