Skip to content

Latest commit

 

History

History
333 lines (242 loc) · 19.7 KB

part24-rus.md

File metadata and controls

333 lines (242 loc) · 19.7 KB

Как использовать Docker сеть, чтобы связать два отдельных контейнера

Оригинал

Всем привет и рад вас снова видеть на мастер-классе по бэкенду!

На предыдущей лекции мы узнали как создать минимальный Docker образ для нашего приложения на Golang. Образ, который мы создали, был довольно небольшим, всего 17,7 МБ. Однако, я не уверен будет ли он правильно работать или нет, поскольку мы ещё не пробовали его запускать. Итак, давайте сделаем это сейчас!

Как запустить Docker контейнеры

Чтобы запустить контейнер из этого образа, мы будем использовать команду docker run. Параметр --name используется для указания имени контейнера, который мы собираемся создать. Скажем, simplebank. Затем используется параметр -p для доступа к порту 8080 извне на внешней хост-машине. Наконец, последний параметр, который мы должны указать, — это имя и тег образа - simplebank:latest.

docker run --name simplebank -p 8080:8080 simplebank:latest

Ой, у нас возникла ошибка! "Cannot load config: Config file app not found." «Не удается загрузить настройки: файл с настройками app не был найден». Это то, что я ожидал! Вы помните, что мы используем Viper для загрузки файла с настройками app.env в лекции 12? Но этого файла нет в созданном нами образе докера. На прошлой лекции мы просто скопировали двоичный исполняемый файл, но не копировали этот файл app.env с настройками в окончательный образ на этапе запуска. Поэтому, чтобы исправить ошибку, мы также должны скопировать файл app.env в этот образ. Я знаю, что это просто файл с настройками, используемый для разработки, который позволяет подключиться к локальной базе данных Postgres и использует банальный симметричный ключ для токена. Возникает вопрос, следует ли его использовать в продакшен образе? Не волнуйтесь, мы узнаем, как заменить этот файл реальным файлом с настройками для продакшена в другой лекции, когда мы будем обновлять наш рабочий процесс CI/CD, чтобы он автоматически создавал образ за нас. А пока давайте просто воспользуемся этими настройками для разработки, чтобы сначала протестировать наш Docker образ. Поскольку последняя команда docker run завершилась с ошибкой, если мы запустим docker ps -a, то увидим, что она оставила после себя запущенный контейнер simplebank. Так что давайте выполним

docker rm simplebank

чтобы удалить этот контейнер. Теперь прежде чем мы повторно соберём Docker образ, давайте запустим docker rmi, чтобы удалить старый образ simplebank.

docker rmi 58c7252992ba

Затем давайте выполним команду docker build, чтобы пересобрать его.

docker build -t simplebank:latest .

Хорошо, теперь у нас есть новый образ. Давайте запустим его!

На этот раз ошибки не возникло! Сервер успешно запущен! Здесь на рисунке вы видите предупреждение о том, что Gin работает в режиме отладки.

При переходе на продакшен, мы можем задать значение для переменной окружения GIN_MODE равное release, чтобы указать Gin, что вместо этого он должен запускать сервер в режиме release. Итак, давайте остановим сервер и попробуем изменить режим! Я удалю старый контейнер simplebank

docker rm simplebank

и запущу новый с помощью той же команды docker run, но на этот раз мы будем использовать параметр -e, чтобы задать значение для переменной окружения GIN_MODE равное release.

docker run --name simplebank -p 8080:8080 -e GIN_MODE=release simplebank:latest

И вуаля, сервер запустился, но теперь мы не видим никаких отладочных сообщений, как раньше. Так что переключение режима произошло! Если мы откроем другую вкладку терминала и запустим docker ps, то увидим, что контейнер simplebank запущен и работает вместе с контейнером базы данных postgres12.

Хорошо, теперь давайте откроем Postman и отправим запрос, чтобы убедиться, что он работает правильно. Я отправлю запрос к Login user API как показано на рисунке!

К сожалению, мы получили 500 Internal Server Error, и причина в том, что сервер не может подключиться к локальному хосту, порту 5432, что является адресом нашей базы данных Postgres. В терминале мы можем увидеть лог этого запроса (смотри рисунок).

Так что же случилось? Мы уже убедились, что контейнер postgres с БД также запущен и работает, верно? Да, но проблема в том, что, как указано в файле с настройками app.env, мы подключаемся к базе данных через localhost. Но контейнеры simplebank и postgres — это два отдельных контейнера, поэтому на самом деле у них не один и тот же сетевой IP-адрес. Мы можем выполнить эту команду docker container inspect

docker container inspect postgres12 

чтобы увидеть сетевые настройки контейнера postgres12.

Как вы видите на рисунке, он использует сеть по умолчанию bridge и его IP адрес — 172.17.0.3. Теперь давайте запустим

docker container inspect simplebank 

Вуаля, IP-адрес контейнера simplebank отличается: «172.17.0.2», хотя он работает в том же сеть по умолчанию bridge, что и контейнер postgres12. Итак, теперь вы знаете, почему мы не можем использовать адрес localhost для подключения к контейнеру Postgres.

Как мы можем это исправить? Что ж, самый простой способ — просто заменить localhost на реальный IP-адрес контейнера postgres12 в файле с настройками app.env. Как то так

DB_SOURCE=postgresql://root:[email protected]:5432/simple_bank?sslmode=disable

и пересобрать Docker образ.

Однако, такой способ не очень удобен, так как нам придется каждый раз пересобирать образ при изменении IP-адреса контейнера Postgres. На самом деле, существует намного лучший способ изменить DB_SOURCE, не пересобирая образ. Вспомните, что мы используем Viper для чтения настроек и мы можем переопределить настройки, записанные в файл app.env, значением, которое мы передаём через переменные окружения. Итак, я остановлю текущий контейнер simplebank, удалю его

docker rm simplebank

и запущу новый контейнер simplebank, но на этот раз я добавлю еще одну переменную окружения, чтобы заменить значение DB_SOURCE реальным IP-адресом контейнера postgres.

docker run --name simplebank -p 8080:8080 -e GIN_MODE=release DB_SOURCE=postgresql://root:[email protected]:5432/simple_bank?sslmode=disable simplebank:latest

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

docker run --name simplebank -p 8080:8080 -e GIN_MODE=release DB_SOURCE="postgresql://root:[email protected]:5432/simple_bank?sslmode=disable" simplebank:latest

и вуаля, сервер успешно запущен.

Теперь давайте снова отправим запрос на вход в систему, чтобы посмотреть, как он отработает!

Ура! Он успешно выполнился! Мы получили новый токен доступа. Итак, теперь вы знаете, как подключить свой контейнер к другому автономному контейнеру через его IP-адрес. Однако IP-адрес может измениться, если мы перезапустим контейнер, поэтому его использование не совсем идеально.

Давайте остановим контейнер simplebank и удалим его.

docker rm simplebank

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

Как создать определяемую пользователем сеть

Сейчас, если мы запустим docker network ls, мы увидим сеть по умолчанию bridge, который использовали наши контейнеры simplebank и postgres.

Мы можем увидеть более подробную информацию об этой сети, выполнив команду docker network inspect и передав название сети: bridge

docker network inspect bridge

Здесь на рисунке в разделе Сontainers мы видим список контейнеров, работающих в этой сети. Сейчас её использует только контейнер postgres12, поскольку мы только что удалили контейнер simplebank. Обычно контейнеры, работающие в одной сети, могут обнаруживать друг друга по имени, а не по IP-адресу. Однако, такой способ не работает для сети по умолчанию bridge. Итак, что нам нужно сделать, это: создать нашу собственную сеть и поместить в эту сеть как контейнер postgres, так и контейнер simplebank. Тогда они смогут обращаться друг к другу по именам.

Docker предоставляет несколько команд для управления сетями. Давайте воспользуемся командой docker network create для создания новой сети. Я назову это bank-network.

docker network create bank-network

Связываем два 2 отдельных контейнера

Затем мы можем использовать команду docker network connect, чтобы подключить к ней существующий контейнер postgres. Вот синтаксис.

Итак, пишем docker network connect, затем название сети: bank-network и наконец название контейнера: postgres12. Теперь, если мы выполним

docker network inspect bank-network

то увидим, что контейнер postgres12 был подключён к этой новой сети.

И если мы проинспектируем контейнер postgres12,

docker container inspect postgres12

то увидим, что теперь он подключён к двум разным сетям: bank-network, которую мы только что создали, и к сети по умолчанию bridge, к которой контейнер был подключен изначально. Совершенно нормально, когда контейнер одновременно подключен к нескольким сетям.

Хорошо, теперь давайте повторно создадим контейнер simplebank, который будет подключаться к этой новой сети. Мы будем использовать ту же команду docker run, что и раньше, но добавим ещё один параметр: --network, и передадим название сети: bank-network.

docker run --name simplebank --network bank-network -p 8080:8080 -e GIN_MODE=release DB_SOURCE="postgresql://root:[email protected]:5432/simple_bank?sslmode=disable" simplebank:latest

На этот раз контейнер simplebank будет работать в той же сети, что и Postgres, поэтому он сможет определить адрес контейнера c Postgres по его имени, поэтому давайте заменим IP-адрес в этой команде на postgres12.

docker run --name simplebank --network bank-network -p 8080:8080 -e GIN_MODE=release DB_SOURCE="postgresql://root:secret@postgres12:5432/simple_bank?sslmode=disable" simplebank:latest

Вот и всё что нужно сделать! Сервер был успешно запущен. Давайте повторно отправим запрос на вход в систему, чтобы увидеть, работает он или нет.

Ура! Запрос успешно выполнен. Потрясающе!

Таким образом, контейнер simplebank успешно связался с контейнером postgres, используя его имя вместо IP-адреса. Это довольно круто, не так ли? Теперь, если мы проинспектируем bank-network, то увидим, что к ней подключаются 2 контейнера: simplebank и postgres12.

Итак, теперь вы знаете, как воспользоваться преимуществами определяемой пользователем сети, чтобы позволить 2 автономным контейнерам взаимодействовать друг с другом по именам.

Прежде чем мы закончим, я собираюсь обновить команду make postgres, чтобы она подключалась к bank-network после создания. Затем давайте добавим все изменения, которые мы сделали до сих пор, создадим новый коммит и отправим его на GitHub.

Итак, здесь на рисунке мы видим новый коммит в этом запросе на слияние.

Когда вы работаете в команде, ваши товарищи по команде могут перейти к этому PR, чтобы провести ревью вашего кода.

Вы можете щелкнуть по любой строке, чтобы написать комментарий, и затем нажать Add single comment («Добавить одиночный комментарий») или Start a review («Начать ревью»). Вы также можете выбрать несколько строк, чтобы оставить комментарий, который будет отображаться для них всех. И как только код будет должным образом проверен и unit тесты пройдены, мы можем объединить его с основной веткой, которой в данном случае является master. Давайте нажмем Merge pull request («Осуществить запрос на слияние»)! Затем Confirm merge («Подтвердите слияние») и, наконец, удалите ветку с этим функционалом.

Вот и всё! Мы закончили! Запрос на слияние был успешно объединён с master. И на этом мы завершаем сегодняшнюю лекцию о Docker сетях.

Я надеюсь, что приобретенные из этой лекции знания будут вам полезны. Большое спасибо за время, потраченное на чтение. Желаю вам получать удовольствие от обучения и до встречи на следующей лекции!