使用Docker-Compose,如何执行多个命令

Using Docker-Compose, how to execute multiple commands

我想做这样的事情,我可以按顺序 运行 多个命令。

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

想通了,用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”类型):

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

这有助于保持事物的清洁和分离。需要考虑两件事:

  1. 您必须确保正确的启动顺序(使用depends_on)。

  2. 您想避免多次构建,这是通过在第一轮使用构建和图像对其进行标记来实现的;之后可以参考其他容器中的镜像。

如果您需要 运行 多个守护进程,有一个 suggestion in the Docker documentation to use Supervisord 处于非分离模式,因此所有子守护进程都将输出到标准输出。

From another SO question, I discovered you can redirect the child processes output to the stdout.这样你就可以看到所有的输出了!

使用 wait-for-it 或 dockerize. These are small wrapper scripts which you can include in your application’s image. Or write your own wrapper script to perform a more application-specific commands. according to: https://docs.docker.com/compose/startup-order/

等工具

您可以在此处使用入口点。 docker 中的入口点在命令之前执行,而命令是容器启动时应为 运行 的默认命令。 所以大多数应用程序通常在入口点文件中进行设置过程,最后它们允许命令 运行.

制作一个shell脚本文件可以是docker-entrypoint.sh(名称无关紧要),其中包含以下内容。

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

在 docker-compose.yml 文件中将其与 entrypoint: /docker-entrypoint.sh 一起使用并将命令注册为 command: python manage.py runserver 0.0.0.0:8000 P.S :不要忘记将 docker-entrypoint.sh 与您的代码一起复制。

尝试使用“;”如果您使用的是两个版本,则将命令分开 例如

command: "sleep 20; echo 'a'"

我建议使用 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 - 启动我的开发服务器

我 运行 尝试设置我的 jenkins 容器以作为 jenkins 用户构建 docker 容器。

我需要触摸 Dockerfile 中的 docker.sock 文件,因为我 link 稍后会在 docker-compose 文件中触摸它。除非我先触摸它,否则它还不存在。这对我有用。

Docker 文件:

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

* 更新 *

我想 运行 一些命令的最佳方法是编写一个自定义 Dockerfile,它可以在官方 CMD 从图像 运行 之前完成我想要的一切。

docker-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)

这可能是最简洁的方法。

* 老办法 *

我用我的命令创建了一个 shell 脚本。在这种情况下,我想开始 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

所以这会分叉 mongo,执行 monogimport,然后杀死分离的分叉 mongo,然后在不分离的情况下再次启动它。不确定是否有附加到分叉进程的方法,但这确实有效。

注意:如果你确实想加载一些初始数据库数据,这是这样做的方法:

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 文件是通过 mongoexport 命令创建的。

docker-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

这对我有用:

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

...否则会出现错误:

Invalid interpolation format for "command" option in service "web":

使用bash -c.

docker-compose 文件中的运行多个命令
command: >
    bash -c "python manage.py makemigrations
    && python manage.py migrate
    && python manage.py runserver 0.0.0.0:8000"

来源:https://intellipaat.com/community/19590/docker-run-multiple-commands-using-docker-compose-at-once?show=19597#a19597

这个帖子中已经有很多很好的答案,但是,我发现将其中一些答案组合起来效果最好,尤其是对于基于 Debian 的用户。

services:
  db:
    . . . 
  web:
    . . .
    depends_on:
       - "db"
    command: >      
      bash -c "./wait-for-it.sh db:5432 -- python manage.py makemigrations
      && python manage.py migrate
      && python manage.py runserver 0.0.0.0:8000"

先决条件:将 wait-for-it.sh 添加到您的项目目录。

来自 the docs 的警告:“(在生产中使用 wait-for-it.sh 时),您的数据库可能随时变得不可用或移动主机......(此解决方案适用于人们那) 不需要这种级别的弹性。"

编辑:

这是一个很酷的短期修复,但对于长期解决方案,您应该尝试在 Dockerfile 中为每个图像使用入口点。

Alpine-based 图像实际上似乎没有安装 bash,但您可以使用 shash,其中 link 到 /bin/busybox .

示例docker-compose.yml

version: "3"
services:

  api:
    restart: unless-stopped
    command: ash -c "flask models init && flask run"

最干净?

---
version: "2"
services:
  test:
    image: alpine
    entrypoint: ["/bin/sh","-c"]
    command:
    - |
       echo a
       echo b
       echo c

我遇到了同样的问题,我想 运行 我在端口 3000 上的反应应用程序和端口 6006 上的故事书都在同一个容器中。

我尝试从 Dockerfile 启动入口点命令以及使用 docker-compose command 选项。

在这方面花了一些时间后,决定将这些服务分离到单独的容器中,并且效果很好

基于@Bjorn 的回答,docker 具有 recently introduced 特殊的依赖规则,允许您等到“init 容器”成功退出,这给出了

db:
  image: postgres
web:
  image: app
  command: python manage.py runserver 0.0.0.0:8000
  depends_on:
    db:
    migration:
      condition: service_completed_successfully
migration:
  build: .
  image: app
  command: python manage.py migrate
  depends_on:
    - db

我不确定你是否还需要 buildkit,但在我这边它可以与

DOCKER_BUILDKIT=1 COMPOSE_DOCKER_CLI_BUILD=1 docker-compose up

如果其他人试图使用基于 Windows 的容器找出多个命令,则以下格式有效:
command: "cmd.exe /c call C:/Temp/script1.bat && dir && C:/Temp/script2.bat && ..."

包括 'call' 指令是为我解决的问题。

或者,如果每个命令都可以在没有前一个命令成功执行的情况下执行,则只需用分号分隔每个命令:
command: "cmd.exe /c call C:/Temp/script1.bat; dir; C:/Temp/script2.bat; ... "

这是我解决这个问题的方法:

services:
  mongo1:
    container_name: mongo1
    image: mongo:4.4.4
    restart: always
#    OPTION 01:
#    command: >
#      bash -c "chmod +x /scripts/rs-init.sh
#      && sh /scripts/rs-init.sh"
#    OPTION 02:
    entrypoint: [ "bash", "-c", "chmod +x /scripts/rs-init.sh && sh /scripts/rs-init.sh"]
    ports:
      - "9042:9042"
    networks:
      - mongo-cluster
    volumes:
      - ~/mongors/data1:/data/db
      - ./rs-init.sh:/scripts/rs-init.sh
      - api_vol:/data/db
    environment:
      *env-vars
    depends_on:
      - mongo2
      - mongo3