Docker 等待 postgresql 运行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35069027/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Docker wait for postgresql to be running
提问by Quba
I am using postgresql with django in my project. i've got them in different containers and the problem is that i need to wait for postgres before running django. At this time i am doing it with sleep 5
in command.sh file for django container. I also found that netcat can do the trick but i would prefer way without additional packages. curl and wget can't do this because they do not support postgres protocol.
Is there a way to do it?
我在我的项目中使用 postgresql 和 django。我将它们放在不同的容器中,问题是我需要在运行 django 之前等待 postgres。此时,我sleep 5
在 django 容器的 command.sh 文件中执行此操作。我还发现 netcat 可以做到这一点,但我更喜欢没有额外包的方式。curl 和 wget 不能这样做,因为它们不支持 postgres 协议。有没有办法做到这一点?
采纳答案by Quba
Problem with your solution tiziano is that curl is not installed by default and i wanted to avoid installing additional stuff. Anyway i did what bereal said. Here is the script if anyone would need it.
您的解决方案 tiziano 的问题是默认情况下未安装 curl,我想避免安装其他内容。无论如何,我做了bereal所说的。如果有人需要,这里是脚本。
import socket
import time
import os
port = int(os.environ["DB_PORT"]) # 5432
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while True:
try:
s.connect(('myproject-db', port))
s.close()
break
except socket.error as ex:
time.sleep(0.1)
回答by Mário Pinhal
If you have psql
you could simply add the following code to your .sh file:
如果你有,psql
你可以简单地将以下代码添加到 .sh 文件中:
RETRIES=5
until psql -h $PG_HOST -U $PG_USER -d $PG_DATABASE -c "select 1" > /dev/null 2>&1 || [ $RETRIES -eq 0 ]; do
echo "Waiting for postgres server, $((RETRIES--)) remaining attempts..."
sleep 1
done
回答by Alister
This will successfully wait for Postgres to start. (Specifically line 6). Just replace npm start
with whatever command you'd like to happen after Postgres has started.
这将成功等待 Postgres 启动。(特别是第 6 行)。只需用npm start
您希望在 Postgres 启动后发生的任何命令替换即可。
services:
practice_docker:
image: dockerhubusername/practice_docker
ports:
- 80:3000
command: bash -c 'while !</dev/tcp/db/5432; do sleep 1; done; npm start'
depends_on:
- db
environment:
- DATABASE_URL=postgres://postgres:password@db:5432/practicedocker
- PORT=3000
db:
image: postgres
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
- POSTGRES_DB=practicedocker
回答by Vinicius Chan
I've spent some hours investigating this problem and I got a solution.
Docker depends_on
just consider service startup to run another service. Than it happens because as soon as db
is started, service-app tries to connect to ur db
, but it's not ready to receive connections. So you can check db
health status in app service to wait for connection. Here is my solution, it solved my problem. :)
Important: I'm using docker-compose version 2.1.
我花了几个小时调查这个问题,我得到了一个解决方案。Dockerdepends_on
只是考虑服务启动来运行另一个服务。之所以会发生这种情况,是因为一旦db
启动, service-app 就会尝试连接到 ur db
,但还没有准备好接收连接。因此您可以db
在应用服务中检查健康状态以等待连接。这是我的解决方案,它解决了我的问题。:) 重要提示:我使用的是 docker-compose 2.1 版。
version: '2.1'
services:
my-app:
build: .
command: su -c "python manage.py runserver 0.0.0.0:8000"
ports:
- "8000:8000"
depends_on:
db:
condition: service_healthy
links:
- db
volumes:
- .:/app_directory
db:
image: postgres:10.5
ports:
- "5432:5432"
volumes:
- database:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
volumes:
database:
In this case it's not necessary to create a .sh file. I hope it helps you guys ;) cya
在这种情况下,不需要创建 .sh 文件。我希望它可以帮助你们;) cya
回答by Pifagorych
The simplest solution is a short bash script:
最简单的解决方案是一个简短的 bash 脚本:
while ! nc -z HOST PORT; do sleep 1; done;
./run-smth-else;
回答by veeresh yh
wait-for-itsmall wrapper scripts which you can include in your application's image to poll a given host and port until it's accepting TCP connections.
等待它的小型包装脚本,您可以将其包含在应用程序的映像中以轮询给定的主机和端口,直到它接受 TCP 连接。
can be cloned in Dockerfile by below command
可以通过以下命令在 Dockerfile 中克隆
RUN git clone https://github.com/vishnubob/wait-for-it.git
docker-compose.yml
docker-compose.yml
version: "2"
services:
web:
build: .
ports:
- "80:8000"
depends_on:
- "db"
command: ["./wait-for-it/wait-for-it.sh", "db:5432", "--", "npm", "start"]
db:
image: postgres
回答by Kurt Peek
If the backend application itself has a PostgreSQL client, you can use the pg_isready
command in an until
loop. For example, suppose we have the following project directory structure,
如果后端应用程序本身具有 PostgreSQL 客户端,则可以pg_isready
在until
循环中使用该命令。例如,假设我们有以下项目目录结构,
.
├── backend
│?? └── Dockerfile
└── docker-compose.yml
with a docker-compose.yml
与 docker-compose.yml
version: "3"
services:
postgres:
image: postgres
backend:
build: ./backend
and a backend/Dockerfile
和一个 backend/Dockerfile
FROM alpine
RUN apk update && apk add postgresql-client
CMD until pg_isready --username=postgres --host=postgres; do sleep 1; done \
&& psql --username=postgres --host=postgres --list
where the 'actual' command is just a psql --list
for illustration. Then running docker-compose build
and docker-compose up
will give you the following output:
其中“实际”命令仅psql --list
用于说明。然后运行docker-compose build
,docker-compose up
将为您提供以下输出:
Note how the result of the psql --list
command only appears after pg_isready
logs postgres:5432 - accepting connections
as desired.
请注意psql --list
命令的结果如何仅出现在所需的pg_isready
日志之后postgres:5432 - accepting connections
。
By contrast, I have found that the nc -z
approach does not work consistently. For example, if I replace the backend/Dockerfile
with
相比之下,我发现这种nc -z
方法并不一致。例如,如果我backend/Dockerfile
用
FROM alpine
RUN apk update && apk add postgresql-client
CMD until nc -z postgres 5432; do echo "Waiting for Postgres..." && sleep 1; done \
&& psql --username=postgres --host=postgres --list
then docker-compose build
followed by docker-compose up
gives me the following result:
然后docker-compose build
跟着docker-compose up
给我以下结果:
That is, the psql
command throws a FATAL
error that the database system is starting up
.
也就是说,该psql
命令会抛出一个FATAL
错误,即the database system is starting up
.
In short, using an until pg_isready
loop (as also recommended here) is the preferable approach IMO.
简而言之,使用until pg_isready
循环(这里也推荐)是 IMO 的首选方法。
回答by tiziano
Why not curl?
为什么不卷曲?
Something like this:
像这样的东西:
while ! curl http://$POSTGRES_PORT_5432_TCP_ADDR:$POSTGRES_PORT_5432_TCP_PORT/ 2>&1 | grep '52'
do
sleep 1
done
It works for me.
这个对我有用。
回答by Nicu Surdu
In your Dockerfile
add waitand change your start command to use it:
在Dockerfile
添加等待并更改启动命令以使用它:
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.7.3/wait /wait
RUN chmod +x /wait
CMD /wait && npm start
Then, in your docker-compose.yml
add a WAIT_HOSTS
environment variable for your api service:
然后,在您的 api 服务中docker-compose.yml
添加一个WAIT_HOSTS
环境变量:
services:
api:
depends_on:
- db
environment:
- WAIT_HOSTS: postgres:5432
postgres:
image: postgres
ports:
- "5432:5432"
This has the advantage that it supports waiting for multiple services:
这样做的好处是它支持等待多个服务:
environment:
- WAIT_HOSTS: postgres:5432, mysql:3306, mongo:27017
For more details, please read their documentation.
有关更多详细信息,请阅读他们的文档。
回答by wilsonpage
#!/bin/sh
POSTGRES_VERSION=9.6.11
CONTAINER_NAME=my-postgres-container
# start the postgres container
docker run --rm \
--name $CONTAINER_NAME \
-e POSTGRES_PASSWORD=docker \
-d \
-p 5432:5432 \
postgres:$POSTGRES_VERSION
# wait until postgres is ready to accept connections
until docker run \
--rm \
--link $CONTAINER_NAME:pg \
postgres:$POSTGRES_VERSION pg_isready \
-U postgres \
-h pg; do sleep 1; done