도커가 postgresql이 실행될 때까지 기다립니다.
저는 프로젝트에서 django와 함께 postgresql을 사용하고 있습니다.저는 그것들을 다른 컨테이너에 넣었고 문제는 제가 django를 실행하기 전에 postgres를 기다려야 한다는 것입니다.이 시간에 저는 그것을 하고 있습니다.sleep 5
command.sh
container.django 파일입니다.을 할 수 있다는 패키지가 방법을 선호합니다. netcat과 netcat의 차이점은 무엇입니까? curl
그리고.wget
Postgres 프로토콜을 지원하지 않기 때문에 이 작업을 수행할 수 없습니다.할 수 있는 방법이 있습니까?
저는 이 문제를 조사하는 데 몇 시간이 걸렸고 해결책을 찾았습니다. 도depends_on
다른 서비스를 실행하려면 서비스 시작을 고려하십시오.그렇게 되는 것보다 더 빨리db
시작되면 의 시됨앱, 에 연결하려고 .db
연결을 수신할 준비가 되지 않았습니다.확인하실 수 있습니다.db
연결을 기다리는 앱 서비스의 상태입니다.여기 제 해결책이 있습니다. Docker-compose version2.1을 하고 있습니다. :) ::) 2을 사용하고 도커 컴포지션 버전 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 파일을 생성할 필요가 없습니다.
이렇게 하면 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
가지고 계신다면,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
가장 간단한 솔루션은 짧은 bash 스크립트입니다.
while ! nc -z HOST PORT; do sleep 1; done;
./run-smth-else;
당신의 솔루션 티지아노의 문제는 컬이 기본적으로 설치되어 있지 않다는 것이고 나는 추가적인 것들을 설치하는 것입니다.어쨌든 나는 비리얼이 말한 대로 했습니다.필요한 사람이 있다면 여기 대본이 있습니다.
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)
의 신의에서.Dockerfile
wait를 추가하고 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
a를 추가합니다.WAIT_HOSTS
서비스에대한 :api 파일:
services:
api:
depends_on:
- postgres
environment:
- WAIT_HOSTS: postgres:5432
postgres:
image: postgres
ports:
- "5432:5432"
이는 여러 서비스의 대기를 지원한다는 장점이 있습니다.
environment:
- WAIT_HOSTS: postgres:5432, mysql:3306, mongo:27017
자세한 내용은 해당 설명서를 참조하십시오.
응용 프로그램 이미지에 포함하여 TCP 연결을 허용할 때까지 지정된 호스트 및 포트를 폴링할 수 있는 wait-for-it 작은 래퍼 스크립트입니다.
아래 명령을 사용하여 도커 파일에서 복제할 수 있습니다.
RUN git clone https://github.com/vishnubob/wait-for-it.git
도커-docker.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
왜 컬 안 해요?
이와 같은 것:
while ! curl http://$POSTGRES_PORT_5432_TCP_ADDR:$POSTGRES_PORT_5432_TCP_PORT/ 2>&1 | grep '52'
do
sleep 1
done
저한테는 효과가 있어요.
도커 합성 정의에 헬스 체크를 추가하여 문제를 해결할 수 있었습니다.
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
출처: https://docs.docker.com/compose/compose-file/compose-file-v2/ #healthcheck
백엔드 응용 프로그램 자체에 Postgre가 있는 경우SQL 클라이언트에서 명령을 사용할 수 있습니다.until
를 들어,과 같은 구조를 가정합니다. 예를 들어, 다음과 같은 프로젝트 디렉토리 구조를 가지고 있다고 가정합니다.
.
├── backend
│ └── Dockerfile
└── docker-compose.yml
docker-compose.yml
version: "3"
services:
postgres:
image: postgres
backend:
build: ./backend
a 리고a.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
'http서 '명은'입니다.psql --list
예를 들어그 때 달리기docker-compose build
그리고.docker-compose up
출력을 합니다.
의결를기다니의 나오는지 .psql --list
는 은령다만표니다시됩에음명다▁appears 뒤에만 .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
그리고나서docker-compose build
에 뒤에docker-compose up
다음과 같은 결과를 제공합니다.
즉은,psql
명령어가 명령어를 던집니다.FATAL
잘못을 저지르다the database system is starting up
.
간단히 말해서, an을 사용합니다.until pg_isready
루프(여기서도 권장됨)가 선호되는 접근 방식 IMO입니다.
다른 답변과 같이 몇 가지 해결책이 있습니다.
, 와 Fail-Fast를 하도록 하세요.restart: on-failure
서비스가 DB에 대한 연결을 열어서 처음에 실패할 수 있습니다.그냥 실패하게 둬.도커가 녹색이 될 때까지 서비스를 다시 시작합니다.서비스를 단순하고 비즈니스 중심으로 유지합니다.
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
다음을 제외하고는 다른 솔루션이 작동하지 않았습니다.
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
이 스레드 덕분에: https://github.com/peter-evans/docker-compose-healthcheck/issues/16
잠잘때까지pg_isready
true를 반환하지만 항상 신뢰할 수 있는 것은 아닙니다.postgres 컨테이너에 하나 이상의 initdb 스크립트가 지정된 경우 부트스트랩 절차 중에 시작된 후 postgres가 다시 시작되므로 아직 준비되지 않았을 수 있습니다.pg_isready
이미 true로 반환되었습니다.
될 때까지 .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
.py "를 사용하여 를 사용할 수 수 없는 경우 py 명령 "check"를 사용하여 데이터베이스를 사용할 수 있는지 확인합니다(사용할 수 없는 경우 2초간 기다렸다가 다시 확인).예를 들어, 당신이 이것을 당신의 안에서 한다면,command.sh
마이그레이션을 실행하기 전에 파일, 마이그레이션 명령을 실행하는 동안 Django에 유효한 DB 연결이 있습니다.
...
echo "Waiting for db.."
python manage.py check --database default > /dev/null 2> /dev/null
until [ $? -eq 0 ];
do
sleep 2
python manage.py check --database default > /dev/null 2> /dev/null
done
echo "Connected."
# Migrate the last database changes
python manage.py migrate
...
PS: 저는 껍데기 전문가가 아닙니다. 개선점을 제시해 주십시오.
#!/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
Nodejs 및 Postgres api의 예입니다.
#!/bin/bash
#entrypoint.dev.sh
echo "Waiting for postgres to get up and running..."
while ! nc -z postgres_container 5432; do
# where the postgres_container is the hos, in my case, it is a Docker container.
# You can use localhost for example in case your database is running locally.
echo "waiting for postgress listening..."
sleep 0.1
done
echo "PostgreSQL started"
yarn db:migrate
yarn dev
# 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"]
한 줄 명령으로 실행하려는 경우.컨테이너에 연결하여 postgres가 실행 중인지 확인하면 됩니다.
docker exec -it $DB_NAME bash -c "\
until psql -h $HOST -U $USER -d $DB_NAME-c 'select 1'>/dev/null 2>&1;\
do\
echo 'Waiting for postgres server....';\
sleep 1;\
done;\
exit;\
"
echo "DB Connected !!"
@tiziano 답변과 부족함에 영감을 받았습니다.nc
또는pg_isready
되는 최근 이미지(python: 여기 과 같은 되는 것 .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.'
많은 방법으로 시도해보니 도커파일, 도커구성 yaml, bash스크립트가 있습니다.: 마막방도됩움니다이만법지▁with다▁only됩▁help.makefile
.
docker-compose up --build -d postgres
sleep 2
docker-compose up --build -d app
컨테이너 내의 Postgres 데이터베이스가 준비될 때까지 기다리려고 했습니다. Java만 사용합니다.제가 한 일은 다음과 같습니다.
다음 레코드를 사용하여 Postgres 데이터베이스가 있는 컨테이너를 나타냅니다.
public record DBContainer(String containerId, String driverClassName, String url, String username, String password) {}
그런 다음 이 메서드는 컨테이너가 준비될 때까지 기다립니다.
private static void waitForPostgresContainerToBeReady(DBContainer dbContainer) throws InterruptedException {
while (!containerIsReady(dbContainer)) {
System.err.println(String.format("Container %s is not ready", dbContainer.containerId()));
Thread.sleep(Duration.ofMillis(300));
}
System.out.println(String.format("Container %s is ready", dbContainer.containerId()));
}
추가 도우미 방법:
// Check if the postgres database whithin the container is ready by trying to open a connection to it.
private static boolean containerIsReady(DBContainer dbContainer) {
try {
DataSource dataSource = getDataSource(dbContainer);
Connection connection = dataSource.getConnection();
boolean isOpen = !connection.isClosed();
if (isOpen) {
connection.close();
}
return isOpen;
} catch (SQLException e) {
return false;
}
}
// Get a datasource from a DBContainer
public static DataSource getDataSource(DBContainer container) {
DataSource dataSource = DataSourceBuilder.create()
.driverClassName(container.driverClassName())
.url(container.url())
.username(container.username())
.password(container.password())
.build();
return dataSource;
}
언급URL : https://stackoverflow.com/questions/35069027/docker-wait-for-postgresql-to-be-running
'programing' 카테고리의 다른 글
Git 상태는 내용이 동일하더라도 파일이 변경된 것으로 표시됩니다. (0) | 2023.05.21 |
---|---|
리눅스 셸에서 변수로 나눗셈을 어떻게 할 수 있습니까? (0) | 2023.05.21 |
iOS 8 iPad에서 UIAactivityView 컨트롤러 충돌 (0) | 2023.05.21 |
분기 기준 변경 (0) | 2023.05.21 |
각도 2 - 모델 변경 후 뷰가 업데이트되지 않음 (0) | 2023.05.21 |