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

时间:2015-05-05 21:53:37

标签: docker yaml 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

16 个答案:

答案 0 :(得分:608)

想出来,使用 const int

示例:

bash -c

多线中的相同示例:

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

答案 1 :(得分:130)

我在一个单独的短暂容器中运行预启动之类的东西,比如这样(注意,撰写文件必须是版本' 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. 你想避免多次构建,这是通过使用build和image第一次标记它来实现的;您可以参考其他容器中的图像,然后

答案 2 :(得分:46)

我建议使用sh而不是bash,因为它在大多数基于unix的图像(高山等)上更容易使用。

下面是一个示例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-启动我的开发服务器

答案 3 :(得分:19)

最干净?

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

答案 4 :(得分:17)

另一个想法:

如果在这种情况下构建容器,只需在其中放置一个启动脚本并使用命令运行它。或者将启动脚本挂载为卷。

答案 5 :(得分:17)

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

使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与您的代码一起复制。

答案 6 :(得分:10)

这对我有用:

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 :(得分:7)

要使用 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

答案 8 :(得分:3)

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

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

答案 9 :(得分:3)

*更新*

我认为运行某些命令的最佳方法是编写一个自定义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,然后在不分离的情况下再次启动它。不确定是否有方法可以附加到分叉的进程上,但这确实可行。

答案 10 :(得分:2)

此线程中已经有很多不错的答案,但是,我发现其中的一些组合似乎效果最好,特别是对于基于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时,您的数据库可能不可用或随时移动主机...(此解决方案适用于那些需要这样做的人)”不需要这种弹性。”

答案 11 :(得分:1)

使用等待它或dockerize等工具。这些是小包装脚本,您可以将其包含在应用程序的图像中。或编写自己的包装器脚本以执行更多特定于应用程序的命令。根据:https://docs.docker.com/compose/startup-order/

答案 12 :(得分:0)

在尝试设置我的jenkins容器以作为jenkins用户构建docker容器时遇到了这个问题。

我需要触摸Dockerfile中的docker.sock文件,因为我稍后在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

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

答案 13 :(得分:0)

基于高山的图像实际上似乎没有安装bash,但是您可以使用链接到sh的{​​{1}}或ash

示例/bin/busybox

docker-compose.yml

答案 14 :(得分:0)

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

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

在花了一些时间之后,决定将这些服务分离到单独的容器中,它的效果非常好

答案 15 :(得分:-7)

尝试使用&#34 ;;"如果你在两个版本中分开命令 e.g。

command: "sleep 20; echo 'a'"