Docker-Compose kullanarak, birden çok komut nasıl çalıştırılır


500

Sırayla birden fazla komut çalıştırabileceğim bir şey yapmak istiyorum.

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

Yanıtlar:


861

Anladım, kullanın bash -c.

Misal:

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

Birden çok satırda aynı örnek:

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

Veya:

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

6
@Pedram Bash yüklü bir görüntü kullandığınızdan emin olun. Bazı görüntüler ayrıca bash için doğrudan bir yol gerektirebilir./bin/bash
codemaven

5
Yüklü bir bash yoksa sh -c "komutunu" deneyebilirsiniz
Chaoste

Bash'a geçerken komutlarınızı tırnak içine aldığınızdan emin olun ve db'nin çalıştığından emin olmak için bir "uyku 5" i kaydırmak zorunda kaldım, ama benim için çalıştı.
pazartesi

74
Alpine tabanlı görüntülerde hiç bash yüklü değil gibi görünüyor - @Chaoste'un önerdiği gibi kullanın ve shbunun yerine kullanın:[sh, -c, "cd /usr/src/app && npm start"]
Florian Loch

1
Ayrıca sadece ashAlp üzerinde kullanabilirsiniz :)
Jonathan

160

Bunun gibi ayrı bir geçici kapsayıcıda taşıma gibi başlangıç ​​öncesi şeyler çalıştırın (not, oluşturma dosyası sürüm '2' türünde olması gerekir):

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

Bu, şeylerin temiz ve ayrı tutulmasına yardımcı olur. Dikkate alınması gereken iki şey:

  1. Doğru başlatma sırasını sağlamanız gerekir (depends_on kullanarak)

  2. build ve image kullanılarak ilk seferde etiketlenerek elde edilen birden fazla derlemeden kaçınmak istersiniz; diğer kaplardaki görüntüye başvurabilirsiniz.


2
Bu benim için en iyi seçenek gibi görünüyor ve bunu kullanmak istiyorum. Birden fazla derlemeyi önlemek için etiketleme ayarlarınızı ayrıntılı olarak açıklayabilir misiniz? Ekstra adımlardan kaçınmayı tercih ederim, bu yüzden biraz gerekiyorsa, bash -cyukarı çıkabilirim .
Stavros Korokithakis

3
Yukarıdaki yaml dosyasında, oluşturma ve etiketleme işlemi taşıma bölümünde gerçekleşir. İlk bakışta gerçekten açık değildir, ancak docker-compose, build AND image özelliklerini belirttiğinizde etiketler; burada image özelliği, bu yapının etiketini belirtir. Bu daha sonra yeni bir derlemeyi tetiklemeden kullanılabilir (web'e bakarsanız, derlemenin değil, yalnızca bir görüntü özelliğinin olduğunu görürsünüz). İşte daha fazla ayrıntı docs.docker.com/compose/compose-file )
Bjoern Stiel

26
Ben bu fikir gibi olsa da, problem şu ki, bu sırayla hazır olduklarını değil, sadece o sırayla başladıklarını garanti eder. wait-for-it.sh bazı insanların ihtiyaç duyduğu çözüm olabilir.
pazartesi

2
Bu kesinlikle doğru ve docker-compose'un bir konteynerin çıkmasını veya bir portta dinlemeye başlamasını beklemek gibi ince taneli kontrolü desteklememesi biraz utanç verici. Ama evet, özel bir komut dosyası bunu çözüyor, iyi bir nokta!
Bjoern Stiel

1
Bu cevap, depends_on'un nasıl çalıştığı hakkında yanlış ve potansiyel olarak tahrip edici bilgiler verir.
antonagestam

96

Bunun shaksine kullanılmasını öneriyorum bashçünkü çoğu unix tabanlı görüntüde (alpin vb.) Daha kolay bulunur.

İşte bir örnek 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"

Bu, aşağıdaki komutları sırayla çağıracaktır:

  • python manage.py wait_for_db - db'nin hazır olmasını bekleyin
  • python manage.py migrate - taşıma işlemleri gerçekleştirin
  • python manage.py runserver 0.0.0.0:8000 - geliştirme sunucumu başlat

2
Şahsen bu benim en sevdiğim ve en temiz çözümüm.
BugHunterUK

1
Benim de. @LondonAppDev'in işaret ettiği gibi, alanı optimize etmek için bash varsayılan olarak tüm kaplarda kullanılamaz (örneğin, Alpine Linux üzerine inşa edilen çoğu kapsayıcılar)
ewilan

2
Çok satırdan kaçmak zorunda kaldım && ile bir
Andre Van Zuydam

@AndreVanZuydam hmmm bu garip, bunu yapmak zorunda değildim. Alıntılarla çevrelediniz mi? Hangi liman işçisinin lezzetini kullanıyorsun?
LondonAppDev

2
@oligofren >çok satırlı bir girişi başlatmak için kullanılır (bkz. stackoverflow.com/a/3790497/2220370 )
LondonAppDev

40

Bu benim için çalışıyor:

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 komutu çalıştırmadan önce değişkenleri serbest bırakmaya çalışır , bu yüzden bash'ın değişkenleri işlemesini istiyorsanız dolar işaretlerinden iki katına çıkarak kaçmanız gerekir ...

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

... yoksa bir hata mesajı alırsınız:

"Web" hizmetindeki "komut" seçeneği için geçersiz enterpolasyon biçimi:


Merhaba dostum. Bir sorunla karşılaştım: `` tanınmayan argümanlar: / bin / bash -c python3 /usr/local/airflow/__init__.py -C Local -T Windows `` `docker-compose.yml'deki komut: command: - / bin / bash - -c - | python3 /usr/local/airflow/__init__.py -C $ {Client} -T $ {Tipler} Bunu nasıl çözeceğinizi biliyor musunuz? .Env dosyama İstemci ve Türleri ekliyorum.
Newt

İşte sizin için bir doküman: docs.docker.com/compose/compose-file/#variable-substitution Sanırım .env dosyanız bu değişkenleri konteyner ortamına yerleştiriyor, ancak docker-compose kabuk ortamınıza bakıyor . Bunun yerine deneyin $${Types}ve $${Client}. Bu docker compose bu değişkenleri yorumlamak ve docker-compose ne çağırırsanız kabuk değerlerini aramak için önleyeceğini düşünüyorum, bu da ( docker dosyanızı işledikten sonra) bash onları dereference için hala etrafında anlamına gelir .env.
MatrixManAtYrService

Yorumun için teşekkürler. Aslında söylediğini yaptım. Hata bilgisinde $ (Client) aldım. Python'da os.getenv kullanmak için ortam değişkenlerini okuma yolunu değiştirdim, ki bu daha kolay. Yine de teşekkürler.
Newt

23

Burada giriş noktasını kullanabilirsiniz. docker içindeki giriş noktası komuttan önce yürütülürken komut, konteyner başlatıldığında çalıştırılması gereken varsayılan komuttur. Bu nedenle, uygulamaların çoğu genellikle giriş noktası dosyasında kurulum yordamını taşır ve son olarak komutun çalışmasına izin verir.

bir kabuk komut dosyası yapmak docker-entrypoint.shaşağıdaki adda (ad önemli değil) olabilir.

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

docker-compose.yml dosyasında PS ile birlikte kullanın entrypoint: /docker-entrypoint.shve komutu kaydedin: kodunuzla birlikte command: python manage.py runserver 0.0.0.0:8000kopyalamayı unutmayın docker-entrypoint.sh.


Bu docker-compose run service-name ....
işlemin

18

Diğer bir fikir:

Bu durumda olduğu gibi, kabı yalnızca bir başlangıç ​​komut dosyası yerleştirirseniz ve bunu komutla çalıştırırsanız. Veya başlangıç ​​komut dosyasını birim olarak bağlayın.


Evet, sonunda bir run.sh betiği oluşturdum: #!/bin/bash \n python manage.py migrate \n python manage.py runserver 0.0.0.0:8000(çirkin oneline)
fero

9

* GÜNCELLEME *

Bazı komutları çalıştırmanın en iyi yolunun, resmi CMD görüntüden çalıştırılmadan önce istediğim her şeyi yapan özel bir Dockerfile yazmaktır.

liman işçisi-compose.yaml:

version: '3'

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

  mongo:
    container_name: mongo
    image: mongo
    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)

Muhtemelen bunu yapmanın en temiz yolu.

* ESKİ YOL *

Komutlarımla bir kabuk betiği oluşturdum. Bu durumda, başlamak mongodve koşmak istedim mongoimportama çağırmak mongodgeri kalanını çalıştırmanızı engelliyor.

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

Yani bu çatal mongo, monogimport yapar ve daha sonra sökülmüş çatallı mongoyu öldürür ve sökmeden tekrar başlatır. Çatallı bir sürece iliştirmenin bir yolu olup olmadığından emin değilim ama bu işe yarıyor.

NOT: Kesinlikle bazı ilk db verilerini yüklemek istiyorsanız, bunu yapmanın yoludur:

mongo_import.sh

#!/bin/bash
# Import from fixtures

# Used in build and docker-compose mongo (different dirs)
DIRECTORY=../deploy/local/mongo_fixtures
if [[ -d "/fixtures" ]]; then
    DIRECTORY=/fixtures
fi
echo ${DIRECTORY}

mongoimport --db wcm-local --collection clients --file ${DIRECTORY}/clients.json && \
mongoimport --db wcm-local --collection configs --file ${DIRECTORY}/configs.json && \
mongoimport --db wcm-local --collection content --file ${DIRECTORY}/content.json && \
mongoimport --db wcm-local --collection licenses --file ${DIRECTORY}/licenses.json && \
mongoimport --db wcm-local --collection lists --file ${DIRECTORY}/lists.json && \
mongoimport --db wcm-local --collection properties --file ${DIRECTORY}/properties.json && \
mongoimport --db wcm-local --collection videos --file ${DIRECTORY}/videos.json

mongo_fixtures / *. json dosyaları mongoexport komutu ile oluşturulmuştur.

liman işçisi-compose.yaml

version: '3'

services:
  mongo:
    container_name: mongo
    image: mongo:3.2.12
    ports:
      - "27017:27017"
    volumes:
      - mongo-data:/data/db:cached
      - ./deploy/local/mongo_fixtures:/fixtures
      - ./deploy/local/mongo_import.sh:/docker-entrypoint-initdb.d/mongo_import.sh


volumes:
  mongo-data:
    driver: local

5

Birden fazla daemon işlemi çalıştırmanız gerekiyorsa , Docker belgelerinde Supervisord'u ayrılmamış bir modda kullanmak için bir öneri vardır, böylece tüm alt cinler stdout'a çıkar.

Başka bir SO sorusundan, alt süreç çıktısını stdout'a yönlendirebileceğinizi keşfettim. Bu şekilde tüm çıktıları görebilirsiniz!


Buna tekrar baktığımızda, bu cevap seri yerine paralel olarak birden fazla komut çalıştırmak için daha uygun görünüyor.
Tim Tisdall


1

Bekle veya dockerize gibi bir araç kullanın . Bunlar, uygulamanızın görüntüsüne ekleyebileceğiniz küçük sarıcı komut dosyalarıdır. Ya da daha uygulamaya özgü komutları gerçekleştirmek için kendi sarmalayıcı komut dosyanızı yazın. şuna göre: https://docs.docker.com/compose/startup-order/


0

Jenkins konteynırımı jenkins kullanıcısı olarak docker konteynırları kurmak için kurmaya çalışırken buna rastladım.

Daha sonra docker-compose dosyasında bağladığım Dockerfile'daki docker.sock dosyasına dokunmam gerekiyordu. Önce ona dokunmazsam, henüz yoktu. Bu benim için çalıştı.

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

liman işçisi-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

Bu, farklı sorunun cevabı gibi görünüyor.
kenorb

-7

";" iki sürümde iseniz komutları ayırmak için örn.

command: "sleep 20; echo 'a'"

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.