web-dev-qa-db-fra.com

Utilisation de Docker-Compose, comment exécuter plusieurs commandes

Je veux faire quelque chose comme ceci où je peux exécuter plusieurs commandes dans l'ordre.

db:
  image: postgres
web:
  build: .
  command: python manage.py migrate
  command: python manage.py runserver 0.0.0.0:8000
  volumes:
    - .:/code
  ports:
    - "8000:8000"
  links:
    - db
294

Pour le comprendre, utilisezbash -c.

Exemple:

command: bash -c "python manage.py migrate && python manage.py runserver 0.0.0.0:8000"

Même exemple en multilignes:

command: >
    bash -c "python manage.py migrate
    && python manage.py runserver 0.0.0.0:8000"
563

J'exécute des tâches de pré-démarrage telles que les migrations dans un conteneur éphémère distinct, par exemple (remarque, le fichier de composition doit être de type "2"):

db:
  image: postgres
web:
  image: app
  command: python manage.py runserver 0.0.0.0:8000
  volumes:
    - .:/code
  ports:
    - "8000:8000"
  links:
    - db
  depends_on:
    - migration
migration:
  build: .
  image: app
  command: python manage.py migrate
  volumes:
    - .:/code
  links:
    - db
  depends_on:
    - db

Cela aide les choses à rester propres et séparées. Deux choses à considérer:

  1. Vous devez vous assurer que la séquence de démarrage est correcte (en utilisant depend_on).

  2. vous voulez éviter les versions multiples, ce qui est obtenu en la marquant du premier coup en utilisant build et image; vous pouvez vous référer à l'image dans d'autres conteneurs alors

122
Bjoern Stiel

Je recommande d'utiliser sh plutôt que bash car il est plus facilement disponible sur la plupart des images à base d'unix (Alpine, etc.).

Voici un exemple docker-compose.yml:

version: '3'

services:
  app:
    build:
      context: .
    command: >
      sh -c "python manage.py wait_for_db &&
             python manage.py migrate &&
             python manage.py runserver 0.0.0.0:8000"

Cela appellera les commandes suivantes dans l’ordre:

  • python manage.py wait_for_db - attend que la base de données soit prête
  • python manage.py migrate - exécuter toutes les migrations 
  • python manage.py runserver 0.0.0.0:8000 - démarrer mon serveur de développement
28
LondonAppDev

Une autre idée:

Si, comme dans ce cas, vous construisez le conteneur, placez-y simplement un script de démarrage et exécutez-le avec la commande. Ou montez le script de démarrage en tant que volume.

17
rweng

Vous pouvez utiliser entrypoint ici. entrypoint in docker est exécuté avant la commande while commande est la commande par défaut à exécuter au démarrage du conteneur . Ainsi, la plupart des applications portent généralement la procédure d'installation dans un fichier entrypoint et autorisent l'exécution de la dernière commande.

créer un fichier de script shell peut être en tant que docker-entrypoint.sh (le nom importe peu) avec le contenu suivant.

#!/bin/bash
python manage.py migrate
exec "$@"

dans le fichier docker-compose.yml, utilisez-le avec entrypoint: /docker-entrypoint.sh et enregistrez la commande en tant que command: python manage.py runserver 0.0.0.0:8000 P.S: n'oubliez pas de copier docker-entrypoint.sh avec votre code.

15
Harshad Yeola

Cela fonctionne pour moi:

version: '3.1'
services:
  db:
    image: postgres
  web:
    build: .
    command:
      - /bin/bash
      - -c
      - |
        python manage.py migrate
        python manage.py runserver 0.0.0.0:8000

    volumes:
      - .:/code
    ports:
      - "8000:8000"
    links:
      - db

docker-compose essaie de déréférencer les variables avant en exécutant la commande. Si vous voulez que bash gère les variables, vous devrez échapper aux signes dollar en les doublant ...

    command:
      - /bin/bash
      - -c
      - |
        var=$$(echo 'foo')
        echo $$var # prints foo

... sinon vous aurez une erreur:

Format d'interpolation non valide pour l'option "commande" du service "web":

8

Si vous devez exécuter plusieurs processus démons, une suggestion de dans la documentation de Docker consiste à utiliser Supervisord en mode détaché afin que tous les sous-démons soient exportés vers la sortie standard.

À partir d'une autre question SO, j'ai découvert que vous pouvez rediriger la sortie des processus enfants vers la sortie standard. De cette façon, vous pouvez voir tout le résultat!

2
Tim Tisdall

Utilisez un outil tel que wait-for-it ou dockerize . Il s’agit de petits scripts de wrapper que vous pouvez inclure dans l’image de votre application. Ou écrivez votre propre script d'encapsulation pour exécuter des commandes plus spécifiques à l'application. selon: https://docs.docker.com/compose/startup-order/

1
Eran

* METTRE À JOUR *

J'ai pensé que la meilleure façon d'exécuter des commandes est d'écrire un fichier Docker personnalisé qui fait tout ce que je veux avant que le CMD officiel ne soit exécuté à partir de l'image.

docker-compose.yaml:

version: '3'

# Can be used as an alternative to VBox/Vagrant
services:

  mongo:
    container_name: mongo
    # image: mongo:3.2.12
    build:
      context: .
      dockerfile: deploy/local/Dockerfile.mongo
    ports:
      - "27017:27017"
    volumes:
      - ../.data/mongodb:/data/db

Dockerfile.mongo:

FROM mongo:3.2.12

RUN mkdir -p /fixtures

COPY ./fixtures /fixtures

RUN (mongod --fork --syslog && \
     mongoimport --db wcm-local --collection clients --file /fixtures/clients.json && \
     mongoimport --db wcm-local --collection configs --file /fixtures/configs.json && \
     mongoimport --db wcm-local --collection content --file /fixtures/content.json && \
     mongoimport --db wcm-local --collection licenses --file /fixtures/licenses.json && \
     mongoimport --db wcm-local --collection lists --file /fixtures/lists.json && \
     mongoimport --db wcm-local --collection properties --file /fixtures/properties.json && \
     mongoimport --db wcm-local --collection videos --file /fixtures/videos.json)

C'est probablement la manière la plus propre de le faire.

* VIEILLE VOIE *

J'ai créé un script shell avec mes commandes. Dans ce cas, je voulais démarrer mongod et exécuter mongoimport mais appeler mongod vous empêche de lancer le reste. 

docker-compose.yaml :

version: '3'

services:
  mongo:
    container_name: mongo
    image: mongo:3.2.12
    ports:
      - "27017:27017"
    volumes:
      - ./fixtures:/fixtures
      - ./deploy:/deploy
      - ../.data/mongodb:/data/db
    command: sh /deploy/local/start_mongod.sh

start_mongod.sh :

mongod --fork --syslog && \
mongoimport --db wcm-local --collection clients --file /fixtures/clients.json && \
mongoimport --db wcm-local --collection configs --file /fixtures/configs.json && \
mongoimport --db wcm-local --collection content --file /fixtures/content.json && \
mongoimport --db wcm-local --collection licenses --file /fixtures/licenses.json && \
mongoimport --db wcm-local --collection lists --file /fixtures/lists.json && \
mongoimport --db wcm-local --collection properties --file /fixtures/properties.json && \
mongoimport --db wcm-local --collection videos --file /fixtures/videos.json && \
pkill -f mongod && \
sleep 2 && \
mongod

Donc, cette fourche mongo fait monogimport puis tue le mongo fourchu qui est détaché et le redémarre sans se détacher. Vous ne savez pas s'il existe un moyen de vous connecter à un processus forké, mais cela fonctionne.

0
radtek

Je me suis heurté à cela en essayant de configurer mon conteneur Jenkins pour construire des conteneurs Docker en tant qu'utilisateur jenkins.

Je devais toucher le fichier docker.sock dans le fichier Docker car je le lierai plus tard dans le fichier docker-compose. À moins que je ne l'aie touché en premier, cela n'existait pas encore. Cela a fonctionné pour moi.

Dockerfile:

USER root
RUN apt-get update && \
apt-get -y install apt-transport-https \
ca-certificates \
curl \
software-properties-common && \
curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; 
echo "$ID")/gpg > /tmp/dkey; apt-key add /tmp/dkey && \
add-apt-repository \
"deb [Arch=AMD64] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
$(lsb_release -cs) \
stable" && \
apt-get update && \
apt-get -y install docker-ce
RUN groupmod -g 492 docker && \
usermod -aG docker jenkins  && \
touch /var/run/docker.sock && \
chmod 777 /var/run/docker.sock

USER Jenkins

docker-compose.yml:

version: '3.3'
services:
jenkins_pipeline:
    build: .
    ports:
      - "8083:8083"
      - "50083:50080"
    volumes:
        - /root/pipeline/jenkins/mount_point_home:/var/jenkins_home
        - /var/run/docker.sock:/var/run/docker.sock
0
Jason Anderson