Как открыть порт в контейнере для локального хоста И связать постоянные данные с контейнером? - PullRequest
5 голосов
/ 15 июня 2019

Я использую dockerode для создания нового Docker-контейнера PostgreSQL. Я хочу иметь возможность:

  1. Открытый порт 5432 на локальном хосте
  2. Пусть контейнер использует каталог на локальном хосте в качестве постоянного хранилища данных

Мне удалось получить работающую реализацию, которая создает контейнер Docker и предоставляет порт 5432 на локальном хосте со следующим кодом:

docker.createContainer({
      Image: "postgres",
      Env: [`POSTGRES_PASSWORD=postgres`],
      HostConfig: {
        PortBindings: {
          "5432/tcp": [{ HostPort: "5432" }]
        },
      },
      ExposedPorts: {
        "5432/tcp": {}
      },
      name: "container-name"
})
  • В этой реализации данные не являются постоянными - перезапуск контейнера всегда будет начинаться с «свежей» БД
    • Мне нужны постоянные данные

Из прочтения документации Docker REST API (и прочтения множества публикаций сообщества) я обнаружил, что мне нужно использовать параметр Binds. Я обновил свой код до следующего:

docker.createContainer({
      Image: "postgres",
      Env: [`POSTGRES_PASSWORD=postgres`],
      HostConfig: {
        PortBindings: {
          "5432/tcp": [{ HostPort: "5432" }]
        },
        // NEW CODE
        Binds: [
          "/path/on/host/machine:/path/on/container"
        ],
      },
      ExposedPorts: {
        "5432/tcp": {}
      },
      name: "container-name"
})
  • Однако после добавления параметра Binds, Я больше не могу подключиться к базе данных с хост-компьютера

Может кто-нибудь сказать мне, что я здесь делаю не так? Я не могу понять, что Binds должно быть в этой конкретной настройке. В конце концов, мне не понадобится база данных, доступная для локального компьютера, но сейчас мне нужно быть в состоянии для целей тестирования. Заранее спасибо!

ОБНОВЛЕНИЕ 1 - 6/15/2019

Я перепроверил это с такой же настройкой, как и предлагалось, которая действительно не сильно отличалась от того, что я уже делал. Однако эти предложения помогли мне встать на правильный путь и понять, где была моя ошибка.

Кажется, проблема возникла из-за того, что я пытался повторно использовать каталог на локальном хосте, который уже использовался для другой настройки базы данных. Я думал, что это было поддержано; Я предполагаю, что что-то мне не хватает?

В любом случае у меня сейчас это работает, но я не совсем понимаю, почему я не могу повторно использовать тот же каталог на моем хост-компьютере, который я использовал при запуске контейнеров из командной строки.

Разъяснение

Я не упомянул, что могу заставить это работать, запустив контейнер из командной строки. Проблема в том, что при попытке использовать dockerode - однако, я не думаю, что это проблема с Dockerode, а скорее из-за некоторых недоразумений, которые я имею с Docker REST API.

Я могу использовать один и тот же каталог для всех баз данных ЕСЛИ Я запустил контейнеры из командной строки, , но не при запуске контейнеров с помощью Docker REST API ( dockerode в моем случае) .

ОБНОВЛЕНИЕ 2 - 6/15/2019

Кажется, что-то не так с путем, который генерировал мой код. После того, как я прошел через это, кажется, я просто упустил из виду эту ошибку. Как ни странно, я не получил никаких ошибок в контейнере при проверке журналов - вот почему я не думал, что с этим путем что-то не так.

Таким образом, для тех, кто сталкивается с этим, может быть достаточно просто исправить путь, на который вы ссылались на хост-машине.

С учетом сказанного я пометил принятое решение mchawre - его решение было правильным для первоначального вопроса, который я задал. Кажется, остальные проблемы были связаны с ошибкой.

(я бы хотел, чтобы в журналах Docker было указано что-то вроде «нет такого каталога» для контейнера, когда он запускался, хотя это привело бы к гораздо более быстрому разрешению)

Соответствующая информация Я нашел следующую информацию здесь:

Предупреждение: переменные, специфичные для Docker, будут иметь эффект, только если вы запустите контейнер с пустым каталогом данных; любая ранее существующая база данных останется нетронутой при запуске контейнера.

  • Думаю, именно поэтому я решил эту проблему, но пока не уверен на 100%

1 Ответ

3 голосов
/ 15 июня 2019

Я попробовал это с моей стороны, и все работает правильно. Пожалуйста, обратитесь ниже шагов:

  1. Сначала я установил dockerode на мою машину npm install dockerode.
  2. Выяснил мои machine ip и port, на которых выставлен демон Docker.
  3. Создан run.js файл, содержащий код для запуска контейнера postgres с внешними томами.
var Docker = require('dockerode');
var dockerHostIP = "192.168.0.33"
var dockerHostPort = 2375

var docker = new Docker({ host: dockerHostIP, port: dockerHostPort });

docker.createContainer({
Image: "postgres",
Env: [`POSTGRES_PASSWORD=postgres`],
HostConfig: {
PortBindings: {
  "5432/tcp": [{ HostPort: "5432" }]
  },
  // NEW CODE
  Binds: [
    "/root/dir:/tmp"
    ],
    },
    ExposedPorts: {
    "5432/tcp": {}
    },
    name: "container-name"
}).then(function(container) {
  return container.start();
})

ПРИМЕЧАНИЕ: /root/dir - это каталог на моем хосте, а /tmp - один внутри контейнера.

  1. Запустил файл js node run.js
  2. Кажется, что Postgres работает и может подключиться к нему с моего хоста
$ psql postgresql://postgres:postgres@localhost:5432/postgres
psql (11.3)
Type "help" for help.

postgres=# \l
                                 List of databases
   Name    |  Owner   | Encoding |  Collate   |   Ctype    |   Access privileges
-----------+----------+----------+------------+------------+-----------------------
 postgres  | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
 template0 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
(3 rows)

postgres=#
  1. Также проверил содержимое каталога /root/dir на моем хосте, чтобы убедиться, что он правильно смонтирован.
$ ls /root/dir/
test.txt
$

Пожалуйста, попробуйте это со своей стороны и дайте мне знать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...