Я использую Docker для создания базы данных PostgreSQL. К сожалению, руководство по установке недостаточно подробное для меня, возможно, потому, что я новичок в докере и могу что-то упустить.
https://payloadcms.com/docs/production/deployment#docker
Это мой docker-compose.yml:
version: '3'
services:
payload:
image: node:18-alpine
ports:
- '3000:3000'
volumes:
- .:/home/node/app
- node_modules:/home/node/app/node_modules
working_dir: /home/node/app/
command: sh -c "yarn install && yarn dev"
depends_on:
- mongo
- postgres
env_file:
- .env
mongo:
image: mongo:latest
ports:
- '27017:27017'
command:
- --storageEngine=wiredTiger
volumes:
- data:/data/db
logging:
driver: none
postgres:
image: postgres:latest
ports:
- '5432:5432'
environment:
POSTGRES_DB: ExperimentOne
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- pgdata:/var/lib/postgresql/data
logging:
driver: none
pgadmin:
image: dpage/pgadmin4
environment:
PGADMIN_DEFAULT_EMAIL: [email protected]
PGADMIN_DEFAULT_PASSWORD: admin
ports:
- "5050:80"
depends_on:
- postgres
volumes:
data:
node_modules:
pgdata:
Это мой .env:
DATABASE_URI=postgres://user:[email protected]:5432/experimentOne
PAYLOAD_SECRET=1f9719d86d80cca708048d07
PAYLOAD_PUBLIC_SERVER_URL=http://localhost:3000
NEXT_PUBLIC_SERVER_URL=http://localhost:3000
Я совершенно уверен, что пароль, имя пользователя и IP-адрес верны, потому что я использую ту же информацию для подключения к базе данных с помощью pgadmin. Но IP-адрес внутри Docker не всегда один и тот же, поэтому в последний раз, когда я хотел подключиться к pgadmin, мне пришлось проверить IP-адрес в Docker, используя docker Inspect [container_id].
PAYLOAD_SECRET
, вероятно, неправильно, он был сгенерирован во время настройки полезной нагрузки, и я не знаю, что это делает, но я думаю, проблема не в этом.
Если я попытаюсь открыть:
http://localhost:3000/admin
Невозможно подключиться:
ns_error_connection_refused
Есть идеи?
Я попытался добавить переменные в .env.
Я застрял, потому что сообщение об ошибке не помогает.
ОБНОВЛЯТЬ:
Дополнительные изображения для облегчения отладки.
Измените IP-адрес в вашем DATABASE_URI на postgres, имя службы в Docker. Обновите его до:
DATABASE_URI=postgres://user:password@postgres:5432/ExperimentOne
Таким образом, Docker обрабатывает IP-адреса внутри себя.
Если вы не уверены в PAYLOAD_SECRET, просто создайте новую случайную строку и замените старую.
Кроме того, запустите полезную нагрузку журналов docker-compose, чтобы увидеть, есть ли какие-либо сообщения об ошибках при попытке запустить службу полезных данных. Внося изменения, вы можете:
docker-compose down
docker-compose up -d
И, наконец, убедитесь, что ничто другое на вашем компьютере не использует порт 3000. Если все настроено правильно, вы сможете получить к нему доступ по адресу http://localhost:3000/admin.
Спасибо, я добавил изменение в uri, перезапустил докер, но результат тот же. Я запустил docker-compose logs payload
, но вывода не было, и на порту 3000 ничего не работает.
Бег 5/5; Сетевой эксперимент-one_default Создано; Контейнер эксперимент-один-postgres-1 запущен; Контейнер эксперимент-один-монго-1 запущен; Контейнер эксперимент-один-pgadmin-1 запущен; Контейнер эксперимент-один-полезная нагрузка-1 создан.
Я добавил больше изображений для отладки. Как видите, журнал пуст.
Спасибо всем за помощь, но это скорее всего все что мне было нужно, после перезагрузки компьютера все заработало. Возможно, Docker нужно было перезапустить, а не просто запускать docker Compose.
Несколько вещей:
Но IP-адрес внутри докера не всегда одинаков
Это сделано специально. Обычно вы не хотите использовать частный IP-адрес, который Docker назначает контейнеру, а вместо этого используете имя хоста, которое Docker автоматически создает для мостовых сетей.
Как отметил @Zerx, тогда вы будете ссылаться на свой URI Postgres как postgres://user:password@postgres:5432/ExperimentOne
. Где postgres
— это имя службы, определенное в вашем файле компоновки.
У вас также отсутствует сетевой блок в вашем файле создания. Сетевой блок должен выглядеть примерно так:
networks:
myNetwork:
driver: bridge
Затем в своих сервисах добавьте ключ network
для каждого сервиса, к сети которого вы хотите подключиться.
services:
payload:
...
networks:
- myNetwork
postgres:
...
networks:
- myNetwork
При устранении проблем с сетью необходимо проверить две вещи. Во-первых, после запуска контейнеров проверьте их с помощью docker inspect <container>
и посмотрите выходные данные сети. Убедитесь, что все ваши контейнеры находятся в сети с одним и тем же именем. Контейнеры могут принадлежать нескольким сетям, но для того, чтобы два контейнера могли взаимодействовать через мостовую сеть, они оба должны быть ее явной частью.
Во-вторых, установите инструмент nmap
внутри вашего сервиса payload
(apk add nmap
), запустите как postgres, так и контейнеры полезной нагрузки, выполните команду в контейнере полезной нагрузки, а затем проверьте результаты nmap postgres -p 5432
. Если nmap сообщает, что порт закрыт или недоступен, значит, сетевое соединение между контейнерами настроено неправильно.
Еще несколько предложений:
stdin_open: true
tty: true
тогда ты сможешь docker compose exec payload bash
Временно удалите раздел command
из определения вашего сервиса. Таким образом, когда вы запускаете службу (после добавления stdin и tty сверху), вы просто получаете работающий альпийский контейнер, в котором вы можете выполнить выполнение. Это позволит вам изолировать проблему сетевого взаимодействия между этим контейнером и службой postgres и какой-либо другой конфигурацией, вызывающей ошибку.
Не пытайтесь повысить все сразу. Начните с одной службы (полезная нагрузка), затем добавляйте остальные по одной (postgres, mongo, pgadmin).
Во время отладки не отключайте драйверы журналирования. Хотя похоже, что ваша база данных postgres запущена и работает, подавляя вывод журнала, вы можете скрыть ошибки.
Блок networks:
не нужен; Compose создает сеть с именем default
и автоматически присоединяет к ней контейнеры. Я не думаю, что вам нужны и большинство других предложений здесь.
@DavidMaze Правда — Docker создаст мостовую сеть по умолчанию, но часто это не желаемое поведение. Предпочтительным и более безопасным подходом является четкое указание сетей и их типов, а затем подключение к ним только определенных сервисов (см., например, рекомендации OWASP).
Я использую Docker для создания базы данных PostgreSQL.
Вы можете использовать это в сочетании со средой разработки на основе хоста. Если ты бежишь
docker-compose up -d postgres
затем, поскольку служба postgres
объявляет ports:
, база данных будет доступна с хоста как localhost
(при условии, что вы используете Docker Desktop или обычный Docker в собственном Linux) через порт 5432 (первый номер порта).
Затем в вашей хост-среде вы можете запустить
export DATABASE_URI=postgres://user:password@localhost:5432/experimentOne
yarn dev
Отсюда вы используете совершенно обычную среду разработки Node/Yarn, за исключением того, что база данных работает в контейнере.
Эта настройка не использует контейнер payload
, и вы можете удалить его. Это просто попытка очень косвенным путем запустить Node в контейнере, но в остальном игнорируя экосистему образов Docker; в большинстве случаев вам будет проще запускать Node напрямую без Docker.
Использование сетевого режима хоста увеличивает поверхность атаки скомпрометированного контейнера, особенно если на сервере выполняются неконтейнерные службы. Для этой настройки нет смысла использовать ее через мостовую сеть.
Я думаю, что удаление контейнера, в котором выполняется приложение, и простое размещение человеком вопроса «запускать Node напрямую без Docker» не дает ответа на вопрос и обходит любые проблемы, препятствующие взаимодействию между контейнерами. Существует множество причин, по которым может быть желательно или даже необходимо запускать сервер приложений в Docker. Запуск контейнеров Node в Docker — это обычная установка, которая не игнорирует экосистему образов Docker.
Я не призываю использовать здесь хост-сети и согласен, что в целом это плохая идея. Настройка Compose изо всех сил старается избежать создания собственного образа для приложения до такой степени, что переопределение command:
повторяется yarn install
при каждом запуске, потому что ничто другое этого не делает. Использование инструментов разработки хоста там, где это уместно, может значительно упростить задачу — хотите ли вы docker-compose run payload yarn add ...
каждый раз, когда у вас появляется новая зависимость?
Я пропустил это в файле компоновки. Это хороший момент. Я просто предположил, что в контейнере запущено реальное приложение (поскольку каталог хоста был привязан к контейнеру, что характерно для настроек разработки).
Я думаю, что DATABASE_URI должен быть ExperimentOne вместо ExperimentOne, потому что это имя базы данных. Но после исправления результат все тот же.