我想做这样的事情,我可以按顺序运行多个命令。
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
答案 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
这有助于保持清洁和分离。需要考虑两件事:
您必须确保正确的启动顺序(使用depends_on)
你想避免多次构建,这是通过使用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"
答案 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'"