DevOps

Почему в 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:

yaml
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:

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).


Содержание


Краткий ответ и быстрая проверка

  1. Выполните: docker ps -a — посмотрите статус контейнера.
  2. Посмотрите логи: docker logs db (или docker logs -f db для tail).
  3. Если в логах написано про 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 выбирает завершение с кодом и сообщает причину в первых строчках логов.


Пошаговое исправление (шаблон)

  1. Остановить и удалить контейнеры и тома (внимание: удаляет данные в именованных томах):
bash
docker-compose down -v
  1. Исправить docker-compose.yml (пример корректного db‑сервиса):
yaml
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, убран маппинг конфигурации (если он не нужен — пока не монтируйте).
  1. (Опционально) Если вы монтируете host‑директорию вместо named volume, исправьте права:
bash
sudo chown -R 999:999 ./pgsql # пример для Linux

Или через контейнер:

bash
docker run --rm -v $(pwd)/pgsql:/data alpine chown -R 999:999 /data
  1. Запустить сборку:
bash
docker-compose up -d --build
docker logs -f db
  1. Если видите сообщение про непустой каталог и хотите новое состояние — найдите имя тома docker volume ls, затем docker volume rm <имя> (либо docker-compose down -v), после чего docker-compose up создаст том заново.

  2. Если нужно временно разрешить тестовый запуск без пароля (не рекомендовано в проде), можно установить переменную:

yaml
environment:
 POSTGRES_HOST_AUTH_METHOD: trust

Но лучше задать POSTGRES_PASSWORD.


Команды для диагностики и восстановления данных

  • Посмотреть статус контейнера:
bash
docker ps -a
  • Просмотреть логи:
bash
docker logs db
docker logs -f db
  • Посмотреть монтирования и пути томов:
bash
docker inspect db --format '{{json .Mounts}}'
  • Список томов и информация:
bash
docker volume ls
docker volume inspect <volume_name>
  • Бэкап данных из тома перед удалением:
bash
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 может инициализироваться дольше, чем стартует контейнер приложения.

Источники


Заключение

Коротко: чаще всего причина в неправильных переменных окружения и в том, что том примонтирован не туда или имеет неверные права. Проверьте логи docker logs db, в docker-compose.yml исправьте DB_*POSTGRES_* и путь тома на /var/lib/postgresql/data, затем очистите/пересоздайте том (docker-compose down -v) и перезапустите. Если в логах встречается ошибка про ownership — выполниe chown -R 999:999 на хост‑каталоге или используйте именованный том. Удачи — и если после логов останутся точные сообщения, пришлите их — разберёмся дальше.

Авторы
Проверено модерацией
Модерация
Почему в Docker Compose не запускается PostgreSQL?