Using Docker-Compose, how to execute multiple commands
I want to do something like this where I can run multiple commands in order.
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
Solution 1:
Figured it out, use bash -c
.
Example:
command: bash -c "python manage.py migrate && python manage.py runserver 0.0.0.0:8000"
Same example in multilines:
command: >
bash -c "python manage.py migrate
&& python manage.py runserver 0.0.0.0:8000"
Or:
command: bash -c "
python manage.py migrate
&& python manage.py runserver 0.0.0.0:8000
"
Solution 2:
I run pre-startup stuff like migrations in a separate ephemeral container, like so (note, compose file has to be of version '2' type):
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
This helps things keeping clean and separate. Two things to consider:
-
You have to ensure the correct startup sequence (using depends_on).
-
You want to avoid multiple builds which is achieved by tagging it the first time round using build and image; you can refer to image in other containers then.
Solution 3:
I recommend using sh
as opposed to bash
because it is more readily available on most Unix based images (alpine, etc).
Here is an example 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"
This will call the following commands in order:
-
python manage.py wait_for_db
- wait for the DB to be ready -
python manage.py migrate
- run any migrations -
python manage.py runserver 0.0.0.0:8000
- start my development server
Solution 4:
This works for me:
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 tries to dereference variables before running the command, so if you want bash to handle variables you'll need to escape the dollar-signs by doubling them...
command:
- /bin/bash
- -c
- |
var=$$(echo 'foo')
echo $$var # prints foo
...otherwise you'll get an error:
Invalid interpolation format for "command" option in service "web":
Solution 5:
Cleanest ?
---
version: "2"
services:
test:
image: alpine
entrypoint: ["/bin/sh","-c"]
command:
- |
echo a
echo b
echo c