Ожидаем Postgres При Запуске Приложений с Docker-Compose
Работая с Docker-Compose, многие сталкивались со следующей проблемой: контейнер с базой запустился, но сам Postgres еще не успел стартовать. При этом, контейнер с нашим приложением уже запустился и пытается подключиться к БД.
В результате, приложение падает с ошибкой подключения к Postgres.
Рассмотрим следующий пример. У нас есть простое веб-приложение, написаное на Go, которое использует Postgres в качестве БД. Чтобы лучше понимать контекст, перед дальнейшим прочтением рекомендую ознакомится с исходниками.
Так выглядит Dockerfile для приложения:
FROM golang:1.14-buster
RUN go version
ENV GOPATH=/
COPY ./ ./
# build go app
RUN go mod download
RUN go build -o todo-app ./cmd/main.go
CMD ["./todo-app"] Ничего сложного, здесь мы копируем все файлы нашего приложения и компилируем его в изображении.
Описываем 2 контейнера: само приложение и БД. Приложение зависит от базы, поэтому контейнер db будет запущен перед приложением. Однако при первом запуске приложение не может подключиться к базе и выдает ошибку:
При повторном запуске приложение запуститься без проблем, потому что контейнер с базой уже стартанул и Postgres запустился. Однако при свежем запуске приложения, эта ошибка будет постоянно воспроизводится.
На официальном сайте Docker есть пример скрипта wait-for-postgres.sh , который помогает решить эту проблему.
Давайте перепишем наши файлы Dockerfile и docker-compose.yml , добавив в корень проекта также данный скрипт.
В Dockerfile теперь будем устанавливать утилиту psql для выполнения скрипта. А в docker-compose.yml в командах контейнера укажем следующий код.
command: ./wait-for-postgres.sh db ./todo-app Теперь все запускается без проблем, и перед запуском приложения, скрипт пытается достучаться к БД.
todo-app_1 | psql: could not connect to server: Connection refused
todo-app_1 | Is the server running on host "db" (172.23.0.2) and accepting
todo-app_1 | TCP/IP connections on port 5432?
todo-app_1 | Postgres is unavailable - sleeping
todo-app_1 | psql: FATAL: the database system is starting up
todo-app_1 | Postgres is unavailable - sleeping
todo-app_1 | psql: FATAL: the database system is starting up
todo-app_1 | Postgres is unavailable - sleeping
todo-app_1 | psql: FATAL: the database system is starting up