Использование Docker-Compose, как выполнять несколько команд

Я хочу сделать что-то вроде этого, где я могу запускать несколько команд в порядке.

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

Ответ 1

bash -c, используйте bash -c.

Пример:

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

Тот же пример в мультилинии:

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

Или же:

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

Ответ 2

Я запускаю материал перед запуском, например, миграции в отдельном эфемерном контейнере, например (примечание, файл компоновки должен иметь тип версии "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

Это помогает держать вещи в чистоте и разделить. Две вещи, которые следует учитывать:

  • Вы должны обеспечить правильную последовательность запуска (используя параметр depend_on)

  • вы хотите избежать нескольких сборок, которые достигаются путем пометки его в первый раз с использованием сборки и изображения; вы можете ссылаться на изображение в других контейнерах, затем

Ответ 3

Я рекомендую использовать sh а не bash потому что он более доступен для большинства образов на основе Unix (alpine и т.д.).

Вот пример 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"

Это вызовет следующие команды по порядку:

  • python manage.py wait_for_db - дождаться готовности БД
  • python manage.py migrate - запускать любые миграции
  • python manage.py runserver 0.0.0.0:8000 - запустить мой сервер разработки

Ответ 4

Здесь вы можете использовать точку входа. точка входа в докер выполняется перед командой, а команда - это команда по умолчанию, которая должна запускаться при запуске контейнера. Таким образом, большинство приложений обычно выполняют процедуру настройки в файле точки входа, а в последнем случае они позволяют запускать команду.

сделать файл оболочки script может быть как docker-entrypoint.sh (имя не имеет значения) со следующим содержимым в нем.

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

в файле docker-compose.yml используйте его с entrypoint: /docker-entrypoint.sh и зарегистрируйте команду как command: python manage.py runserver 0.0.0.0:8000 P.S: не забудьте скопировать docker-entrypoint.sh вместе с вашим кодом.

Ответ 5

Другая идея:

Если, как в этом случае, вы создаете контейнер, просто разместите в нем запуск script и запустите его с помощью команды. Или установите запуск script в качестве тома.

Ответ 6

Это работает для меня:

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 пытается разыменовать переменные перед запуском команды, поэтому, если вы хотите, чтобы bash обрабатывал переменные, вам нужно экранировать знаки доллара, удваивая их...

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

... в противном случае вы получите ошибку:

Неверный формат интерполяции для опции "команда" в сервисе "сеть":

Ответ 7

* ОБНОВИТЬ *

Я подумал, что лучший способ запустить некоторые команды - написать собственный Dockerfile, который делает все, что я хочу, до запуска официального CMD из образа.

докер-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)

Это, наверное, самый чистый способ сделать это.

* СТАРЫЙ ПУТЬ *

Я создал сценарий оболочки с моими командами. В этом случае я хотел запустить mongod и запустить mongoimport но вызов mongod блокирует запуск остальных.

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

Так что это разветвляет монго, делает моногимпорт, а затем убивает раздвоенное монго, и снова запускает его, не отрываясь. Не уверен, есть ли способ присоединиться к разветвленному процессу, но это работает.

Ответ 8

Если вам нужно запустить более одного процесса демона, предложите предложение в документации Docker использовать Supervisord в режиме без отсоединения поэтому все суб-демоны будут выводиться на стандартный вывод.

Из другого вопроса SO я обнаружил, что вы можете перенаправить вывод дочерних процессов на stdout. Таким образом вы можете увидеть весь вывод!

Ответ 9

Используйте такой инструмент, как wait-for-it или dockerize. Это небольшие скрипты-оболочки, которые вы можете включить в образ приложений. Или напишите свою собственную оболочку script, чтобы выполнить больше команд приложения. в соответствии с: https://docs.docker.com/compose/startup-order/

Ответ 10

Я столкнулся с этим, пытаясь настроить мой контейнер jenkins для сборки докеров как пользователь jenkins.

Мне нужно было прикоснуться к файлу docker.sock в Dockerfile, так как я позже сошлюсь на него в файле docker-compose. Пока я не прикоснулся к нему первым, его еще не было. Это сработало для меня.

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

докер-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

Ответ 11

Хотя это не совсем относится к вопросу, размещая его здесь, он помогает кому-то. Если вы хотите запустить команду перед запуском контейнера, вы можете запустить контейнер в обычном режиме. Затем войдите в контейнер и внесите изменения. Затем вы можете зафиксировать контейнер как новое изображение. Это новое изображение может использоваться для обеспечения того, чтобы все необходимые изменения существовали до запуска контейнера.

Ответ 12

В версии Docker Compose версии 2 (и в том числе 3) вы можете указать список аргументов, как в Dockerfile:

version: '3'
# version: '2'

services:
  app:
    image: foo:1-bar
    command: ["foo", "bar", "baz"]

Ответ 13

попробуйте использовать ";" отделить команды, если вы находитесь в двух вариантах например.

command: "sleep 20; echo 'a'"