mirror of https://github.com/docker/compose.git
Document ways to make services wait for dependencies
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
This commit is contained in:
parent
62fb6b99eb
commit
6b947ee478
94
docs/faq.md
94
docs/faq.md
|
@ -15,6 +15,76 @@ weight=90
|
||||||
If you don’t see your question here, feel free to drop by `#docker-compose` on
|
If you don’t see your question here, feel free to drop by `#docker-compose` on
|
||||||
freenode IRC and ask the community.
|
freenode IRC and ask the community.
|
||||||
|
|
||||||
|
|
||||||
|
## How do I control the order of service startup? I need my database to be ready before my application starts.
|
||||||
|
|
||||||
|
You can control the order of service startup with the
|
||||||
|
[depends_on](compose-file.md#depends-on) option. Compose always starts
|
||||||
|
containers in dependency order, where dependencies are determined by
|
||||||
|
`depends_on`, `links`, `volumes_from` and `network_mode: "service:..."`.
|
||||||
|
|
||||||
|
However, Compose will not wait until a container is "ready" (whatever that means
|
||||||
|
for your particular application) - only until it's running. There's a good
|
||||||
|
reason for this.
|
||||||
|
|
||||||
|
The problem of waiting for a database to be ready is really just a subset of a
|
||||||
|
much larger problem of distributed systems. In production, your database could
|
||||||
|
become unavailable or move hosts at any time. Your application needs to be
|
||||||
|
resilient to these types of failures.
|
||||||
|
|
||||||
|
To handle this, your application should attempt to re-establish a connection to
|
||||||
|
the database after a failure. If the application retries the connection,
|
||||||
|
it should eventually be able to connect to the database.
|
||||||
|
|
||||||
|
The best solution is to perform this check in your application code, both at
|
||||||
|
startup and whenever a connection is lost for any reason. However, if you don't
|
||||||
|
need this level of resilience, you can work around the problem with a wrapper
|
||||||
|
script:
|
||||||
|
|
||||||
|
- Use a tool such as [wait-for-it](https://github.com/vishnubob/wait-for-it)
|
||||||
|
or [dockerize](https://github.com/jwilder/dockerize). These are small
|
||||||
|
wrapper scripts which you can include in your application's image and will
|
||||||
|
poll a given host and port until it's accepting TCP connections.
|
||||||
|
|
||||||
|
Supposing your application's image has a `CMD` set in its Dockerfile, you
|
||||||
|
can wrap it by setting the entrypoint in `docker-compose.yml`:
|
||||||
|
|
||||||
|
version: "2"
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
build: .
|
||||||
|
ports:
|
||||||
|
- "80:8000"
|
||||||
|
depends_on:
|
||||||
|
- "db"
|
||||||
|
entrypoint: ./wait-for-it.sh db:5432
|
||||||
|
db:
|
||||||
|
image: postgres
|
||||||
|
|
||||||
|
- Write your own wrapper script to perform a more application-specific health
|
||||||
|
check. For example, you might want to wait until Postgres is definitely
|
||||||
|
ready to accept commands:
|
||||||
|
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
host="$1"
|
||||||
|
shift
|
||||||
|
cmd="$@"
|
||||||
|
|
||||||
|
until psql -h "$host" -U "postgres" -c '\l'; do
|
||||||
|
>&2 echo "Postgres is unavailable - sleeping"
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
>&2 echo "Postgres is up - executing command"
|
||||||
|
exec $cmd
|
||||||
|
|
||||||
|
You can use this as a wrapper script as in the previous example, by setting
|
||||||
|
`entrypoint: ./wait-for-postgres.sh db`.
|
||||||
|
|
||||||
|
|
||||||
## Why do my services take 10 seconds to recreate or stop?
|
## Why do my services take 10 seconds to recreate or stop?
|
||||||
|
|
||||||
Compose stop attempts to stop a container by sending a `SIGTERM`. It then waits
|
Compose stop attempts to stop a container by sending a `SIGTERM`. It then waits
|
||||||
|
@ -90,30 +160,6 @@ specify the filename to use, for example:
|
||||||
docker-compose -f docker-compose.json up
|
docker-compose -f docker-compose.json up
|
||||||
```
|
```
|
||||||
|
|
||||||
## How do I get Compose to wait for my database to be ready before starting my application?
|
|
||||||
|
|
||||||
Unfortunately, Compose won't do that for you but for a good reason.
|
|
||||||
|
|
||||||
The problem of waiting for a database to be ready is really just a subset of a
|
|
||||||
much larger problem of distributed systems. In production, your database could
|
|
||||||
become unavailable or move hosts at any time. The application needs to be
|
|
||||||
resilient to these types of failures.
|
|
||||||
|
|
||||||
To handle this, the application would attempt to re-establish a connection to
|
|
||||||
the database after a failure. If the application retries the connection,
|
|
||||||
it should eventually be able to connect to the database.
|
|
||||||
|
|
||||||
To wait for the application to be in a good state, you can implement a
|
|
||||||
healthcheck. A healthcheck makes a request to the application and checks
|
|
||||||
the response for a success status code. If it is not successful it waits
|
|
||||||
for a short period of time, and tries again. After some timeout value, the check
|
|
||||||
stops trying and report a failure.
|
|
||||||
|
|
||||||
If you need to run tests against your application, you can start by running a
|
|
||||||
healthcheck. Once the healthcheck gets a successful response, you can start
|
|
||||||
running your tests.
|
|
||||||
|
|
||||||
|
|
||||||
## Should I include my code with `COPY`/`ADD` or a volume?
|
## Should I include my code with `COPY`/`ADD` or a volume?
|
||||||
|
|
||||||
You can add your code to the image using `COPY` or `ADD` directive in a
|
You can add your code to the image using `COPY` or `ADD` directive in a
|
||||||
|
|
Loading…
Reference in New Issue