Docker正在等待postgresql运行
在我的项目中,我正在使用postgresql和django。我把它们放在不同的容器中,问题是在运行django之前我需要等待postgres。此时,我正在使用django容器的Docker正在等待postgresql运行,postgresql,docker,Postgresql,Docker,在我的项目中,我正在使用postgresql和django。我把它们放在不同的容器中,问题是在运行django之前我需要等待postgres。此时,我正在使用django容器的command.sh文件中的sleep5执行此操作。我还发现netcat可以做到这一点,但我更喜欢没有额外软件包的方式curl和wget无法执行此操作,因为它们不支持postgres协议。 有办法吗?为什么不卷曲 大概是这样的: while ! curl http://$POSTGRES_PORT_5432_TCP_ADD
command.sh
文件中的sleep5
执行此操作。我还发现netcat可以做到这一点,但我更喜欢没有额外软件包的方式curl
和wget
无法执行此操作,因为它们不支持postgres协议。
有办法吗?为什么不卷曲
大概是这样的:
while ! curl http://$POSTGRES_PORT_5432_TCP_ADDR:$POSTGRES_PORT_5432_TCP_PORT/ 2>&1 | grep '52'
do
sleep 1
done
你的解决方案tiziano的问题是默认情况下没有安装curl,我想避免安装额外的东西。不管怎样,我还是照贝雷尔说的做了。这是脚本,如果有人需要的话
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)
也许你可以使用docker compose来管理你的容器 是文档
在其yaml文件中,您可以设置
链接
属性来表示服务之间的依赖关系。然后,服务将按您的意愿启动。如果您有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
这将成功等待Postgres启动。(特别是第6行)。只需在Postgres启动后使用任何您希望执行的命令替换
npm start
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
服务:
实习码头工人:
图片:dockerhubusername/practice\u docker
端口:
- 80:3000
命令:bash-c'while 最简单的解决方案是一个简短的bash脚本:
while ! nc -z HOST PORT; do sleep 1; done;
./run-smth-else;
可以在应用程序映像中包含的小包装脚本,用于轮询给定的主机和端口,直到它接受TCP连接
可以通过以下命令在Dockerfile中克隆
RUN git clone https://github.com/vishnubob/wait-for-it.git
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
我花了几个小时研究这个问题,找到了解决办法。
DOCKER <代码> RealsSon < /COD> >考虑服务启动来运行另一个服务。这是因为只要启动db
,服务应用程序就会尝试连接到urdb
,但它还没有准备好接收连接。因此,您可以在应用程序服务中检查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:
在这种情况下,不需要创建.sh文件。
我希望这对你们有帮助;)
cya如果后端应用程序本身有一个PostgreSQL客户端,则可以在直到循环中使用该命令。例如,假设我们有以下项目目录结构
.
├── backend
│ └── Dockerfile
└── docker-compose.yml
使用docker compose.yml
version: "3"
services:
postgres:
image: postgres
backend:
build: ./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
其中“实际”命令只是一个psql--list
,用于说明。然后运行docker compose build
和docker compose up
将为您提供以下输出:
请注意,psql--list
命令的结果如何仅在pg_isready
logspostgres:5432-根据需要接受连接之后显示
相比之下,我发现nc-z
方法并不一致。例如,如果我将后端/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
然后,docker compose build
接着是docker compose up
给出以下结果:
也就是说,psql
命令抛出一个FATAL
错误,数据库系统正在启动
简而言之,使用直到pg_isready
循环(也是推荐的)是更好的方法。在Dockerfile
中添加并更改start命令以使用它:
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.7.3/wait /wait
RUN chmod +x /wait
CMD /wait && npm start
然后,在docker compose.yml
中为api服务添加一个WAIT\u HOSTS
环境变量:
服务:
应用程序编程接口:
取决于:
-博士后
环境:
-等等主持人:postgres:5432
博士后:
图片:博士后
端口:
- "5432:5432"
这样做的优点是它支持等待多个服务:
环境:
-等等,主机:postgres:5432,mysql:3306,mongo:27017
有关详细信息,请阅读。#/垃圾箱/垃圾箱
POSTGRES_版本=9.6.11
CONTAINER\u NAME=我的postgres容器
#启动postgres容器
docker run--rm\
--名称$CONTAINER\u名称\
-e POSTGRES_密码=docker\
-d\
-p 5432:5432\
博士后:$postgres\u版本
#等待postgres准备好接受连接
直到docker逃跑\
--rm\
--链接$CONTAINER\u NAME:pg\
博士后:$postgres\u版本pg\u已准备就绪\
-美国博士后\
-h pg;做睡眠1;完成
灵感来自@tiziano和nc
或pg\u的缺失,似乎在最近的docker python映像(此处为python:3.9)中,curl默认安装,我的entrypoint.sh中运行了以下检查:
postgres_ready() {
$(which curl) http://$DBHOST:$DBPORT/ 2>&1 | grep '52'
}
until postgres_ready; do
>&2 echo 'Waiting for PostgreSQL to become available...'
sleep 1
done
>&2 echo 'PostgreSQL is available.'
通过向docker compose定义中添加运行状况检查,我成功地解决了我的问题
db:
image: postgres:latest
ports:
- 5432:5432
healthcheck:
test: "pg_isready --username=postgres && psql --username=postgres --list"
timeout: 10s
retries: 20
然后,在从属服务中,您可以检查运行状况:
my-service:
image: myApp:latest
depends_on:
kafka:
condition: service_started
db:
condition: service_healthy
来源:睡眠直到pg\u isready
返回true。不幸的是,这并不总是可靠的。如果您的postgres容器至少指定了一个initdb脚本,那么即使pg_isready
已返回true,它也可能尚未就绪
相反,您可以做的是等待该实例的docker日志返回一个PostgreSQL初始化进程完成;准备启动。
string,然后继续执行pg\u isready
检查
例如:
start\u postgres(){
docker compose up-d——无需重新创建postgres
}
等待博士后(){
直到docker撰写日志| grep-q“PostgreSQL初始化过程完成;准备启动。”\
&&docker compose exec-T postgres sh-c“PGPASSWORD=\$postgres\u PASSWORD PGUSER=\$postgres\u USER pg\u isready--dbname=\$postgres\u DB”>/dev/null 2>&1;do
printf“\r正在等待postgres容器可用…”
睡眠1
完成
printf
# Dockerfile
FROM node:12.16.2-alpine
ENV NODE_ENV="development"
RUN mkdir -p /app
WORKDIR /app
COPY ./package.json ./yarn.lock ./
RUN yarn install
COPY . .
CMD ["/bin/sh", "./entrypoint.dev.sh"]