Docker Составьте псевдонимы имен сервисов для имен хостов.
Поскольку вы назвали свой контейнер с изображением mongo
как mongoDB
, mongodb
(без учета регистра) будет именем хоста и имя, под которым вы должны ссылаться на него из вашего Node.JS контейнера и приложения.
- Замените
localhost
в URI на mongodb
MongoDB По умолчанию в базе данных используется порт 27017. Если вы не изменили порт, вам следует указать это значение.
Добавьте порт в URI, чтобы у вас было mongodb:27017
Необязательно, но хорошая практика , реорганизуйте приложение для использования переменных среды, а не жестко закодированные значения.
Это имеет как минимум 2 преимущества:
a. Ваш код становится более гибким; б. Ваш файл Compose, указав эти значения, станет более понятным.
См. Документацию DockerHub для образа здесь
См. Документацию MongoDB для строк подключения здесь
Поиск Google возвращает много примеров с использованием Compose, MongoDB и Node.JS
Обновление: repro
Я уверен Ваша проблема может быть связана с синхронизацией контейнеров Compose. Я полагаю, что ваше приложение пытается подключиться к БД до того, как контейнер DB будет готов. Это общая проблема с Compose, и не решается с помощью Compose depends_on
. Вместо этого вы должны найти решение MongoDB (или, возможно, другой базы данных) для этого.
В моем воспроизведении index.js
(см. Ниже) вводит ложную задержку, прежде чем он пытается подключиться к базе данных. 5 секунд достаточно для готовности контейнера БД, и, таким образом, это работает:
docker-compose build --no-cache
docker-compose up
Тогда:
docker-compose logs app
Attaching to 60359441_app_1
app_1 | URL: mongodb://mongodb:27017/example
app_1 | Connected
дает Connected
, что хорошо.
В качестве альтернативы пр Помимо проблемы синхронизации, вы можете запускать контейнеры отдельно (и вы можете удалить функцию sleep
, чтобы база данных была готова до приложения:
HOST=localhost # No DNS naming
PORT=37017 # An arbitrary port to prove the point
# In one session
docker run \
--interactive --tty --rm \
--publish=${PORT}:27017 \
mongo
# In another session
docker run \
--interactive --tty --rm \
--net=host \
--env=HOST=${HOST} --env=PORT=${PORT} --env=DATA=example --env=WAIT=0 \
app
URL: mongodb://localhost:37017/example
Connected
docker -compose.yaml:
version: "3"
services:
app:
image: app
build:
context: ./app
dockerfile: Dockerfile
environment:
- HOST=mongodb
- PORT=27017
- DATA=example
- WAIT=5000
volumes:
- ${PWD}/app:/app
mongodb:
image: mongo
restart: always
# environment:
# MONGO_INITDB_ROOT_USERNAME: root
# MONGO_INITDB_ROOT_PASSWORD: example
mongo-express:
image: mongo-express
restart: always
ports:
- 8081:8081
environment:
ME_CONFIG_MONGODB_SERVER: mongodb
# ME_CONFIG_MONGODB_ADMINUSERNAME: root
# ME_CONFIG_MONGODB_ADMINPASSWORD: example
NB Поскольку я следовал вашему названию mongodb
, контейнеру mongo-express
необходимо предоставить это имя хоста через ME_CONFIG_MONGODB_SERVER
NB Другие переменные среды, показанные с изображениями mongo
и mongo-express
, являются значениями по умолчанию и поэтому являются необязательными.
Dockerfile:
FROM node:13.8.0-slim
WORKDIR /usr/src/app
COPY package.json .
RUN npm install
COPY . .
ENTRYPOINT ["node","index.js"]
index. js:
// Obtain config from the environment
const HOST = process.env.HOST;
const PORT = process.env.PORT;
const DATA = process.env.DATA;
const WAIT = parseInt(process.env.WAIT, 10);
// Create MongoDB client
var MongoClient = require("mongodb").MongoClient;
let url = `mongodb://${HOST}:${PORT}/${DATA}`;
console.log(`URL: ${url}`);
// Artificially delay the code
setTimeout(function() {
MongoClient.connect(url, function(err, db) {
if(!err) {
console.log("Connected");
}
});
}, WAIT);
NB index.js
использует среду (HOST
, PORT
, DB
) для своей конфигурации, что является хорошей практикой.
Включая mongo-express
обеспечивает возможность просматривать сервер mongo
для быстрого наблюдения за происходящим:
![enter image description here](https://i.stack.imgur.com/OBvID.png)