Почему в Docker Compose не запускается PostgreSQL?
Почему PostgreSQL в Docker Compose не запускается: проверьте POSTGRES_* переменные, путь тома /var/lib/postgresql/data, права доступа и логи (docker logs db).
Почему не запускается контейнер db (PostgreSQL) в Docker Compose?
При запуске docker-compose.yml в Docker Desktop контейнер db отображается как не запущенный. Ниже приведены мои файлы docker-compose.yml и Dockerfile.
docker-compose.yml:
services:
#PHP Service
app:
build:
context: .
dockerfile: Dockerfile
image: digitalocean.com/php
container_name: app
restart: unless-stopped
tty: true
environment:
SERVICE_NAME: app
SERVICE_TAGS: dev
working_dir: /src
volumes:
- ./:/src
- ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
networks:
- app-network
#Nginx Service
webserver:
image: nginx:alpine
container_name: webserver
restart: unless-stopped
tty: true
ports:
- "80:80"
- "443:443"
volumes:
- ./:/src
- ./nginx/conf.d/:/etc/nginx/conf.d/
networks:
- app-network
#PostgreSQL Service
db:
image: postgres:latest
container_name: db
restart: always
tty: true
ports:
- "${DB_PORT:-5432}:5432"
environment:
DB_DATABASE: laravel-app
DB_USER: root
DB_PASSWORD: qwerty123
SERVICE_TAGS: dev
SERVICE_NAME: pgsql
volumes:
- dbdata:/var/lib/pgsql/
- ./pgsql/pg.cnf:/etc/pgsql/pg.cnf
networks:
- app-network
#Redis Service
redis:
image: redis:alpine
container_name: myapp-redis
networks:
- app-network
#Docker Networks
networks:
app-network:
driver: bridge
#Volumes
volumes:
dbdata:
driver: local
Dockerfile:
FROM php:8.4-fpm
# Copy composer.lock and composer.json
COPY composer.lock composer.json /var/www/
# Set working directory
WORKDIR /src
# Install dependencies
RUN apt-get update && apt-get install -y \
build-essential \
pgsql-client \
libpng-dev \
libjpeg62-turbo-dev \
libfreetype6-dev \
locales \
zip \
jpegoptim optipng pngquant gifsicle \
vim \
unzip \
git \
curl
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Install extensions
RUN docker-php-ext-install pdo_pgsql mbstring zip exif pcntl
RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/
RUN docker-php-ext-install gd
# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Add user for laravel application
RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www
# Copy existing application directory contents
COPY . /src
# Copy existing application directory permissions
COPY --chown=www:www . /src
# Change current user to www
USER www
# Expose port 9000 and start php-fpm server
EXPOSE 9000
CMD ["php-fpm"]
Какие возможные причины проблемы и как её исправить? Проверить логи контейнера: docker logs db.
Чаще всего контейнер db (PostgreSQL) в Docker Compose не запускается из‑за неверных environment‑переменных (в образе Postgres требуются POSTGRES_DB / POSTGRES_USER / POSTGRES_PASSWORD), неправильного монтирования тома (должен быть /var/lib/postgresql/data, у вас — /var/lib/pgsql) или проблем с правами на хост‑папку. Сначала выполните docker logs db — по сообщению в логах станет ясно, что именно (ownership, initdb, или отсутствует пароль); затем правьте docker-compose.yml, очистите/пересоздайте volume и перезапустите контейнер (docker-compose down -v && docker-compose up -d).
Содержание
- Краткий ответ и быстрая проверка
- Типичные причины: env, volume, права
- Тома и права: /var/lib/postgresql/data vs /var/lib/pgsql
- Что смотреть в логах: docker logs db
- Пошаговое исправление (шаблон)
- Команды для диагностики и восстановления данных
- Частые ошибки в docker-compose.yml и Dockerfile
- Дополнительные советы (Docker Desktop, SELinux, Windows/Mac)
- Источники
- Заключение
Краткий ответ и быстрая проверка
- Выполните:
docker ps -a— посмотрите статус контейнера. - Посмотрите логи:
docker logs db(илиdocker logs -f dbдля tail). - Если в логах написано про ownership, initdb или отсутствие пароля — см. разделы ниже.
Ниже — подробный разбор причин и готовые шаги для исправления.
Типичные причины: env, volume, права
Самые частые причины, когда “контейнер db не запускается” при использовании docker compose postgres:
-
Неправильные переменные окружения. Официальный образ Postgres использует переменные
POSTGRES_DB,POSTGRES_USER,POSTGRES_PASSWORD. В вашем файле используютсяDB_DATABASE,DB_USER,DB_PASSWORD— это не те переменные, которые просматривает entrypoint образа, поэтому инициализация БД не происходит. (См. документацию образа: hub.docker.com/_/postgres/). -
Неправильный путь монтирования тома. Официальный PGDATA —
/var/lib/postgresql/data. У вас вdocker-compose.ymlуказан/var/lib/pgsql/— это опечатка/неправильный путь; контейнер либо не видит ожидаемую папку, либо пытается инициализировать систему в другом месте и падает. -
Права и владелец каталога: если вы монтируете хост‑папку (или у вас уже есть данные в томе), то пользователь внутри контейнера (обычно uid 999 — postgres) должен владеть папкой данных. Проблемы с владельцем приводят к ошибкам вида “data directory … has wrong ownership” или к невозможности записать файлы.
-
Наличие непустого тома: переменные инициализации (создание БД/пользователя) срабатывают только при пустом каталоге данных. Если в томе уже есть файлы (старые данные) — образ не перезапишет их и не применит env‑переменные (подробно обсуждается в issue/документах: hub.docker.com/_/postgres/ и обсуждение на GitHub: https://github.com/docker-library/postgres/issues/203).
Тома и права: /var/lib/postgresql/data vs /var/lib/pgsql
Почему это важно и что сделать:
-
Исправьте монтирование тома в docker-compose.yml:
-
Правильно:
- dbdata:/var/lib/postgresql/data -
Неправильно:
- dbdata:/var/lib/pgsql/(как в вашем файле) -
Рекомендуется сначала использовать именованный volume (dbdata), чтобы избежать проблем с правами на хосте (особенно на Windows/Mac/Docker Desktop). Если вам нужен host‑mount — проверяйте владельца и права.
-
Если вы уже монтировали host‑директорию, проверьте и исправьте владельца:
-
На Linux:
sudo chown -R 999:999 ./путь_к_host_каталогу(uid 999 — стандартный postgres в официальном образе). Обсуждение и советы по chown в Docker Forums: https://forums.docker.com/t/postgresql-as-docker-container-not-starting-with-initial-data-from-mapped-volume/91284 и https://forums.docker.com/t/cannot-map-postgres-volume/127910 -
Если лог говорит, что initdb не выполняется (cluster уже инициализирован), и вы хотите заново инициализировать БД — удалите volume и запустите заново (данные будут потеряны, сделайте бэкап перед удалением!).
Что смотреть в логах: docker logs db
Запустите: docker logs db или в real‑time: docker logs -f db. Вот типичные сообщения и что они означают:
-
“The only variable required is POSTGRES_PASSWORD” / ошибки про отсутствие пароля
— Значит, вы не задалиPOSTGRES_PASSWORD(или задали под именемDB_PASSWORD). Решение: задатьPOSTGRES_PASSWORDвdocker-compose.yml. -
“initdb: directory “/var/lib/postgresql/data” exists but is not empty”
— В каталоге уже есть файлы, поэтому инициализация не выполнится. Удалите/очистите том или используйте новый. -
“FATAL: data directory “/var/lib/postgresql/data” has wrong ownership”
— Файлы принадлежат root или другому пользователю. Сделайтеchown -R 999:999на хосте или используйте именованный том. -
“database system is ready to accept connections”
— Успех: сервис поднят и готов.
Если контейнер быстро падает и docker logs пустые или минимальные — проверьте docker inspect db и docker ps -a для кода выхода; иногда entrypoint выбирает завершение с кодом и сообщает причину в первых строчках логов.
Пошаговое исправление (шаблон)
- Остановить и удалить контейнеры и тома (внимание: удаляет данные в именованных томах):
docker-compose down -v
- Исправить
docker-compose.yml(пример корректногоdb‑сервиса):
db:
image: postgres:latest
container_name: db
restart: always
ports:
- "${DB_PORT:-5432}:5432"
environment:
POSTGRES_DB: laravel-app
POSTGRES_USER: root
POSTGRES_PASSWORD: qwerty123
volumes:
- dbdata:/var/lib/postgresql/data
networks:
- app-network
- Убраны неверные
DB_*переменные, путь тома заменён на/var/lib/postgresql/data, убран маппинг конфигурации (если он не нужен — пока не монтируйте).
- (Опционально) Если вы монтируете host‑директорию вместо named volume, исправьте права:
sudo chown -R 999:999 ./pgsql # пример для Linux
Или через контейнер:
docker run --rm -v $(pwd)/pgsql:/data alpine chown -R 999:999 /data
- Запустить сборку:
docker-compose up -d --build docker logs -f db
-
Если видите сообщение про непустой каталог и хотите новое состояние — найдите имя тома
docker volume ls, затемdocker volume rm <имя>(либоdocker-compose down -v), после чегоdocker-compose upсоздаст том заново. -
Если нужно временно разрешить тестовый запуск без пароля (не рекомендовано в проде), можно установить переменную:
environment:
POSTGRES_HOST_AUTH_METHOD: trust
Но лучше задать POSTGRES_PASSWORD.
Команды для диагностики и восстановления данных
- Посмотреть статус контейнера:
docker ps -a
- Просмотреть логи:
docker logs db docker logs -f db
- Посмотреть монтирования и пути томов:
docker inspect db --format '{{json .Mounts}}'
- Список томов и информация:
docker volume ls
docker volume inspect <volume_name>
- Бэкап данных из тома перед удалением:
docker run --rm -v dbdata:/var/lib/postgresql/data -v $(pwd)/backup:/backup alpine \
tar -czf /backup/pgdata.tar.gz -C /var/lib/postgresql/data .
(Сохраните этот архив перед docker volume rm.)
Частые ошибки в docker-compose.yml и Dockerfile
- Переменные
DB_*вместоPOSTGRES_*— образ их игнорирует. - Неправильный путь тома (
/var/lib/pgsql/vs/var/lib/postgresql/data) — инициализация не там, где нужно. - Монтирование конфигурации в неправильный путь (
./pgsql/pg.cnf:/etc/pgsql/pg.cnf) — образ может не подхватить такой файл. Если нужен кастомный конфиг, см. документацию поpostgresи аргументы-c config_file=.... - Ожидание, что
depends_onгарантирует готовность БД — нет, он только гарантирует запуск контейнеров по порядку; для ожидания работоспособности используйте healthcheck или скрипты ожидания. - Использование
container_nameможет помешать, если этот имя уже занято. - На Windows/Mac: host‑mounts могут иметь ограничения прав и неожиданные символы; лучше именованные тома.
Дополнительные советы (Docker Desktop, SELinux, Windows/Mac)
- Docker Desktop (Windows/Mac) по‑другому монтирует хост‑папки. Если возникают странные ошибки с правами — временно используйте именованный том (
dbdata) вместо привязки хост‑папки. - На системах с SELinux (CentOS/RHEL) при монтировании host‑папки используйте селинукс‑опции:
:Zили:zв volume‑маппинге; либоchconдля назначения контекста. - Если приложение не может подключиться к БД сразу после поднятия контейнера — используйте healthcheck в compose или скрипт
wait-forв контейнере приложения, потому что Postgres может инициализироваться дольше, чем стартует контейнер приложения.
Источники
- Официальный образ PostgreSQL на Docker Hub: https://hub.docker.com/_/postgres/
- Обсуждение проблемы и прав для маппинга тома (Docker Forums): https://forums.docker.com/t/postgresql-as-docker-container-not-starting-with-initial-data-from-mapped-volume/91284
- Ошибка маппинга тома и ownership (Docker Forums): https://forums.docker.com/t/cannot-map-postgres-volume/127910
- GitHub issue: переменные окружения работают только при пустом data‑директории: https://github.com/docker-library/postgres/issues/203
- Пример решения с изменением пути данных (Habr Q&A): https://qna.habr.com/q/745737
- Похожие вопросы на StackOverflow (пример — отсутствие POSTGRES_PASSWORD): https://stackoverflow.com/questions/62663726/postgres-container-doesnt-start
Заключение
Коротко: чаще всего причина в неправильных переменных окружения и в том, что том примонтирован не туда или имеет неверные права. Проверьте логи docker logs db, в docker-compose.yml исправьте DB_* → POSTGRES_* и путь тома на /var/lib/postgresql/data, затем очистите/пересоздайте том (docker-compose down -v) и перезапустите. Если в логах встречается ошибка про ownership — выполниe chown -R 999:999 на хост‑каталоге или используйте именованный том. Удачи — и если после логов останутся точные сообщения, пришлите их — разберёмся дальше.