Qub*_*uba 17 postgresql docker
我在我的项目中使用带有django的postgresql.我把它们放在不同的容器中,问题是我需要在运行django之前等待postgres.这时我正在使用sleep 5django容器的command.sh文件.我还发现netcat可以做到这一点,但我更喜欢没有额外包的方式.curl和wget不能这样做,因为他们不支持postgres协议.有办法吗?
小智 24
如果你有,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
Run Code Online (Sandbox Code Playgroud)
Ali*_*ter 20
这将成功等待Postgres开始.(特别是第6行).只需替换npm startPostgres启动后你想要发生的任何命令.
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
Run Code Online (Sandbox Code Playgroud)
Nic*_*rdu 14
在Dockerfile添加等待并更改启动命令以使用它:
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.7.3/wait /wait
RUN chmod +x /wait
CMD /wait && npm start
Run Code Online (Sandbox Code Playgroud)
然后,在您的 api 服务中docker-compose.yml添加一个WAIT_HOSTS环境变量:
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.7.3/wait /wait
RUN chmod +x /wait
CMD /wait && npm start
Run Code Online (Sandbox Code Playgroud)
这样做的好处是它支持等待多个服务:
services:
api:
depends_on:
- postgres
environment:
- WAIT_HOSTS: postgres:5432
postgres:
image: postgres
ports:
- "5432:5432"
Run Code Online (Sandbox Code Playgroud)
有关更多详细信息,请阅读他们的文档。
gad*_*k.a 14
我已经通过向 docker-compose 定义添加运行状况检查来解决我的问题。
db:
image: postgres:latest
ports:
- 5432:5432
healthcheck:
test: "pg_isready --username=postgres && psql --username=postgres --list"
timeout: 10s
retries: 20
Run Code Online (Sandbox Code Playgroud)
然后在依赖的服务中可以检查健康状态:
my-service:
image: myApp:latest
depends_on:
kafka:
condition: service_started
db:
condition: service_healthy
Run Code Online (Sandbox Code Playgroud)
来源:https ://docs.docker.com/compose/compose-file/compose-file-v2/#healthcheck
tiz*_*ano 10
为什么不卷曲?
像这样的东西:
while ! curl http://$POSTGRES_PORT_5432_TCP_ADDR:$POSTGRES_PORT_5432_TCP_PORT/ 2>&1 | grep '52'
do
sleep 1
done
Run Code Online (Sandbox Code Playgroud)
这个对我有用。
您的解决方案问题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)
Run Code Online (Sandbox Code Playgroud)
如果后端应用程序本身具有 PostgreSQL 客户端,则可以pg_isready在until循环中使用该命令。例如,假设我们有以下项目目录结构,
.
??? backend
? ??? Dockerfile
??? docker-compose.yml
Run Code Online (Sandbox Code Playgroud)
与 docker-compose.yml
version: "3"
services:
postgres:
image: postgres
backend:
build: ./backend
Run Code Online (Sandbox Code Playgroud)
和一个 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
Run Code Online (Sandbox Code Playgroud)
其中“实际”命令仅psql --list用于说明。然后运行docker-compose build,docker-compose up将为您提供以下输出:
请注意psql --list命令的结果如何仅出现在所需的pg_isready日志之后postgres:5432 - accepting connections。
相比之下,我发现这种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
Run Code Online (Sandbox Code Playgroud)
然后docker-compose build跟着docker-compose up给我以下结果:
也就是说,该psql命令会抛出一个FATAL错误,即the database system is starting up.
简而言之,使用until pg_isready循环(这里也推荐)是 IMO 的首选方法。
正如其他答案提到的,有几个解决方案。
但不要让它变得复杂,只需让它与restart: on-failure. 您的服务将打开与数据库的连接,并且可能第一次会失败。就让它失败吧。Docker 将重新启动您的服务,直至其变绿。让您的服务简单并以业务为中心。
version: '3.7'
services:
postgresdb:
hostname: postgresdb
image: postgres:12.2
ports:
- "5432:5432"
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=Ceo
migrate:
image: hanh/migration
links:
- postgresdb
environment:
- DATA_SOURCE=postgres://user:secret@postgresdb:5432/Ceo
command: migrate sql --yes
restart: on-failure # will restart until it's success
Run Code Online (Sandbox Code Playgroud)
查看重启政策。
除了以下内容之外,其他解决方案均无效:
version : '3.8'
services :
postgres :
image : postgres:latest
environment :
- POSTGRES_DB=mydbname
- POSTGRES_USER=myusername
- POSTGRES_PASSWORD=mypassword
healthcheck :
test: [ "CMD", "pg_isready", "-q", "-d", "mydbname", "-U", "myusername" ]
interval : 5s
timeout : 5s
retries : 5
otherservice:
image: otherserviceimage
depends_on :
postgres:
condition: service_healthy
Run Code Online (Sandbox Code Playgroud)
感谢这个帖子:https ://github.com/peter-evans/docker-compose-healthcheck/issues/16
小智 8
我花了几个小时研究这个问题,然后找到了解决方案。DockerDepends_on只是考虑启动服务来运行另一个服务。发生这种情况的原因是,一旦数据库启动,service-app就会尝试连接到ur 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:
Run Code Online (Sandbox Code Playgroud)
在这种情况下,无需创建.sh文件。我希望它对你们有帮助;)
等待它的小型包装器脚本,您可以将其包含在应用程序的映像中,以轮询给定的主机和端口,直到它接受TCP连接为止。
可以通过以下命令在Dockerfile中克隆
RUN git clone https://github.com/vishnubob/wait-for-it.git
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
最简单的解决方案是简短的bash脚本:
while ! nc -z HOST PORT; do sleep 1; done;
./run-smth-else;
Run Code Online (Sandbox Code Playgroud)
不幸的是,睡眠直到pg_isready返回 true 并不总是可靠的。如果您的 postgres 容器至少指定了一个 initdb 脚本,则postgres 在其引导过程期间启动后会重新启动,因此即使pg_isready已返回 true,它也可能尚未准备好。
相反,您可以做的是等待该实例的 docker 日志返回一个PostgreSQL init process complete; ready for start up.字符串,然后才继续进行pg_isready检查。
例子:
start_postgres() {
docker-compose up -d --no-recreate postgres
}
wait_for_postgres() {
until docker-compose logs | grep -q "PostgreSQL init process complete; ready for start up." \
&& docker-compose exec -T postgres sh -c "PGPASSWORD=\$POSTGRES_PASSWORD PGUSER=\$POSTGRES_USER pg_isready --dbname=\$POSTGRES_DB" > /dev/null 2>&1; do
printf "\rWaiting for postgres container to be available ... "
sleep 1
done
printf "\rWaiting for postgres container to be available ... done\n"
}
start_postgres
wait_for_postgres
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
21200 次 |
| 最近记录: |