web-dev-qa-db-de.com

Mit Docker-Compose können Sie mehrere Befehle ausführen

Ich möchte so etwas tun, wo ich mehrere Befehle nacheinander ausführen kann.

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

Um herauszufinden, verwenden Siebash -c.

Beispiel:

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

Gleiches Beispiel in Multilinien:

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

Ich führe Vor-Start-Sachen wie Migrationen in einem separaten ephemeren Container aus (wie folgt (beachten Sie, dass die Erstellungsdatei die Version '2' hat)

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

Dies hilft, Dinge sauber und getrennt zu halten. Zwei Dinge zu beachten:

  1. Sie müssen die korrekte Startreihenfolge sicherstellen (mithilfe von „changes_on“).

  2. sie möchten mehrere Builds vermeiden, die durch die erste Markierung mit Build und Image erreicht werden. Sie können dann auf das Bild in anderen Containern verweisen

122
Bjoern Stiel

Ich empfehle die Verwendung von sh im Gegensatz zu bash, da sie auf den meisten Unix-basierten Bildern (Alpine usw.) leichter verfügbar ist.

Hier ist ein Beispiel 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"

Dadurch werden die folgenden Befehle der Reihe nach aufgerufen:

  • python manage.py wait_for_db - warte, bis die Datenbank bereit ist
  • python manage.py migrate - Alle Migrationen ausführen 
  • python manage.py runserver 0.0.0.0:8000 - starte meinen Entwicklungsserver
28
LondonAppDev

Eine andere Idee:

Wenn Sie wie in diesem Fall den Container erstellen, platzieren Sie einfach ein Startskript und führen Sie dieses mit dem Befehl aus. Oder mounten Sie das Startskript als Volume.

17
rweng

Sie können hier einen Eingangspunkt verwenden. entrypoint in docker wird ausgeführt, bevor der Befehl ausgeführt wird, während der Befehl der Standardbefehl ist, der ausgeführt werden soll, wenn der Container gestartet wird .. Die meisten Anwendungen führen im Allgemeinen eine Einstellungsprozedur in der Entypoint-Datei aus, und zuletzt erlauben sie die Ausführung des Befehls.

eine Shell-Skriptdatei kann als docker-entrypoint.sh (Name ist egal) mit folgendem Inhalt erstellt werden.

#!/bin/bash
python manage.py migrate
exec "[email protected]"

in der Datei docker-compose.yml verwenden Sie sie mit entrypoint: /docker-entrypoint.sh und den Befehl register als command: python manage.py runserver 0.0.0.0:8000 P.S: Vergessen Sie nicht, docker-entrypoint.sh zusammen mit Ihrem Code zu kopieren.

15
Harshad Yeola

Das funktioniert bei mir:

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 versucht, Variablen vor dem Ausführen des Befehls zu dereferenzieren. Wenn Sie also möchten, dass bash mit Variablen umgeht, müssen Sie die Dollarzeichen umgehen, indem Sie sie verdoppeln ...

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

... sonst erhalten Sie eine Fehlermeldung:

Ungültiges Interpolationsformat für die Option "Befehl" im Dienst "Web":

Wenn Sie mehr als einen Daemon-Prozess ausführen müssen, gibt es in der Docker-Dokumentation einen Vorschlag, Supervisord in einem nicht getrennten Modus zu verwenden, damit alle Sub-Daemons im stdout ausgegeben werden.

Aus einer anderen SO - Frage habe ich herausgefunden, dass Sie die Ausgabe der untergeordneten Prozesse an die Standardausgabe umleiten können. Auf diese Weise können Sie alle Ausgaben sehen!

2
Tim Tisdall

Verwenden Sie ein Tool wie beispielsweise Wait-For-It oder Dockerize . Dies sind kleine Wrapper-Skripts, die Sie in das Image Ihrer Anwendung einfügen können. Oder schreiben Sie Ihr eigenes Wrapper-Skript, um anwendungsspezifische Befehle auszuführen. gemäß: https://docs.docker.com/compose/startup-order/

1
Eran

* UPDATE *

Ich habe mir gedacht, dass der beste Weg, einige Befehle auszuführen, darin besteht, eine benutzerdefinierte Docker-Datei zu schreiben, die alles ausführt, was ich will, bevor die offizielle CMD aus dem Bild ausgeführt wird.

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)

Dies ist wahrscheinlich der sauberste Weg, dies zu tun.

* ALTER WEG *

Ich habe ein Shell-Skript mit meinen Befehlen erstellt. In diesem Fall wollte ich mongod starten und mongoimport ausführen, aber der Aufruf von mongod hindert Sie daran, den Rest auszuführen. 

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

Also gabelt das Mongo, macht Monogimport und tötet dann den abgespannten gespaltenen Mongo und startet ihn wieder, ohne ihn zu lösen. Sie sind sich nicht sicher, ob es einen Weg gibt, an einen gegabelten Prozess anzuhängen, aber das funktioniert.

0
radtek

Ich bin darauf gestoßen, als ich versuchte, meinen Jenkins-Container so einzurichten, dass er als Jenkins-Benutzer Docker-Container erstellt.

Ich musste die docker.sock-Datei in der Docker-Datei anfassen, da ich sie später in der Docker-Compose-Datei verlinke. Wenn ich es nicht zuerst berührte, existierte es noch nicht. Das hat bei mir funktioniert.

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