Глава 6. Добавляем базу данных: Postgres
Содержание
Не знаю как вы, но я очень вдохновлён нашим развитием. Мы постепенно совершенствуем свои навыки и теперь в шаговой доступности от своего приложения Dockerized Rails имеющего все те возможности, которые мы применяем когда запускаем Rails локально.
Тем не менее есть одно явное упущение: мы не настроили базу данных. Подавляющему большинству приложений Rails требуется постоянное хранилище.
В этой главе мы исправим его, основываясь на своём опыте добавления сервера Redis, для подключения базы данных Postgres.
При чтении данной главы помните об сохранении в памяти всей большой картины. Изучаемые вами навыки применимы ко всем службам, которые вы можете пожелать добавить в своё приложение, будь то запуск фоновых заданий (таких как Sidekiq), Elasticsearch или некий интерфейс JavaScript для API Rails.
Для применения в своём приложении Rails мы хотим запустить некий сервер Postgres. Этот процесс очень похож на то как мы добавляли Redis.
В своей предыдущей главе мы начали своё ознакомление с тем как запускать Redis при помощи docker run
.
Однако теперь, когда у нас уже имеется некий опыт по добавлению служб, давайте позаботимся о сохранности колёс и перепрыгнем сразу
к настройке Postres при помощи Compose.
Давайте добавим в свой файл docker-compose.yml
Postgres:
version: '3'
services:
web:
build: .
ports:
- "3000:3000"
volumes:
- .:/usr/src/app
redis:
image: redis
» database:
» image: postgres
» environment:
» POSTGRES_USER: postgres
» POSTGRES_PASSWORD: some-long-secure-password
» POSTGRES_DB: myapp_development
Мы определили некую новую службу database
применив
официальный образ
postgres
. Мы полагаемся на установленную по умолчанию в этом образе инструкцию
CMD
- CMD ["postgres"]
которая
запустит наш сервер Postgres.
Как и в случае с redis
нашей новой службе
database
не требуется установление соответствия порта или тома. Мы не хотим в своём
приложении наличия доступа к нашей базе данных извне и нам не требуется монтировать какие бы то ни было файлы в этот
контейнер Postres.
Нам приходится, тем не менее, определять некое новое свойство с названием environment
.
Вы скорее всего догадались что оно делает: оно указывает Docker на необходимость настройки последующих переменных
среды внутри этого контейнера. Здесь мы определяем что POSTGRES_USER
должен быть
установлен в postgres
; POSTGRES_PASSWORD
следует определить значением some-long-secure-password
; а
POSTGRES_DB
надлежит настроить на
myapp_development
.
Зачем мы это сделали?
В точности как и версия Postres без Docker позволяет вам определять некие переменные окружения, то же самое
справедливо идля нашей версии с Docker.
Когда запускается Postres, если установлена POSTGRES_USER
, именно это
значение будет применяться в качестве имени учётной записи для суперпользователя. Аналогично, если установлен
POSTGRES_PASSWORD
, он будет применяться в качестве пароля данного суперпользователя.
Наконец, если установлена POSTGRES_DB
, именно она будет применяться в качестве
базы данных по умолчанию, которая создаётся при запуске.
Не очень разумно иметь пароль нашей базы данных в данном файле docker-compose.yml
:
этот файл должен фиксироваться контролем версий, но существует риск для безопасности фиксации файлов, содержащих
секретные коды. Мы вернёмся к этому вопросу позднее. Помимо этого, чисто технически, нам не требуется устанавливать
POSTGRES_USER
, так как это значение имеется у нас установленным по умолчанию.
Тем не менее, я включил его, поскольку хорошей практикой
является делать такие вещи настраиваемыми.
Хорошо. Имея эти обновления docker-compose.yml
, мы можем запустить Postres:
$ docker-compose up -d database
Мы запустили свою службу database
в отключённом режиме (detached). Вы можете
убедиться что она поднята и исполняется при помощи:
$ docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------
myapp_database_1 docker-entrypoint.sh pos… Up 5432/tcp
myapp_redis_1 docker-entrypoint.sh red… Up 6379/tcp
myapp_web_1 bin/rails s -b 0.0.0.0 Up 0.0.0.0:3000->3000/tcp
Теперь у нас имеются три контейнера для нашего приложения и мы можем видеть своё новое прибавление - нашу базу данных - она исполняется.
В качестве дальнейшей проверки мы можем просмотреть вывод контейнера этой базы данных:
$ docker-compose logs database
Attaching to myapp_database_1
...
database_1 | PostgreSQL init process complete; ready for start up.
database_1 |
database_1 | 2019-01-15 10:07:29.394 UTC [1] LOG: listening on IPv4 address
"0.0.0.0", port 5432
database_1 | 2019-01-15 10:07:29.394 UTC [1] LOG: listening on IPv6 address
"::", port 5432
database_1 | 2019-01-15 10:07:29.397 UTC [1] LOG: listening on Unix socket
"/var/run/postgresql/.s.PGSQL.5432"
database_1 | 2019-01-15 10:07:29.409 UTC [60] LOG: database system was shut
down at 2019-01-15 10:07:29 UTC
database_1 | 2019-01-15 10:07:29.414 UTC [1] LOG: database system is ready
to accept connections
Помните, что эта команда отображает регистрационные записи самого контейнера - то есть его вывод отличается от вывода файла регистрационных записей Postgres.
По мере того вам будет становиться всё удобнее и удобнее при использовании Compose, вы обнаружите что вы доверяете
ему делать всё что вам нужно. Скорее всё что вам потребуется для проверки того что некая служба исполняется, это быстрый
запуск docker-compose ps
(а порой вы даже можете пропускать и это).
Однако так как запуск служб подобных Postres внутри некого контейнера всё ещё внове для нас, давайте проделаем дополнительный шаг вручную подключившись к нему с другого контейнера, в точности как мы проделывали это с Redis. При обучении, по крайней мере для меня лично, это помогало моей уверенности в работе с данными инструментами.
Как это было и в случае с Redis, наш образ postgres
поступает с предустановленным
psql
- клиентом Postgres. Это означает что мы можем зацепиться прицепом к своей новой
службе database
чтобы запустить одноразовый контейнер на основе своего образа
postgres
. Тем не менее, вместо применения для этого образа установленную по умолчанию
команду, которая запускает сервер Postgres, мы вместо этого исполним некую команду для
запуска клиента Postgres.
Мы можем сделать это при помощи такой команды:
$ docker-compose run --rm database psql -U postgres -h database
В ней мы сообщаем: "Запусти новый одноразовый контейнер (run --rm
) для
нашей службы database
и исполни внутри него команду
psql -u postgres -h database
". Эта команда запустит нужного нам клиента Postres,
сообщит ему о необходимости подключения к имеющемуся хосту с именем database
от имени пользователя postgres
. Мы полагаемся на тот факт, что Compose магическим
образом настраивает сетевую среду для нашего приложения с настроенной DNS с тем чтобы указанное название хоста
database
достигало того контейнера, в котором запущена наша служба
database
.
Вместо run --rm
нам возможно придётся применить
exec
, который мог бы избежать запуска некого нового контейнера и вместо этого
исполнил бы соответствующую команду в уже запущенном контейнере с базой данных. Однако мы намеренно желаем дополнительно
убедиться в подключении из иного контейнера.
Когда вы выполните эту команду, вы получите приглашение на ввод пароля:
Password for user postgres:
Пройдите далее и введите some-long-secure-password
- тот пароль, который
мы установили в своём файле docker-compose.yml
. Он должен быть принят и вы получите
приглашение psql
:
psql (11.1 (Debian 11.1-1.pgdg90+1))
Type "help" for help.
postgres=#
Исключительно. Мы подключились к своей службе database
, исполняющей Postres
и что всё работает как мы и надеялись. Когда вы будете готовы, вы можете покинуть своего клиента
psql
набрав \q <Enter>
.
Только что мы рассмотрели как поднять свою базу данных и достичь её из другого контейнера в своей сетевой среде приложения. Однако прежде чем мы начнём её применять, нам понадобится настроить своё приложение Rails на подключение к ней.
Давайте это сделаем прямо сейчас.
Обо всём по порядку. Чтобы заставить наше приложение Rails общаться с Postgres, нам нужно установить соответствующий
gem клиента Postgres. Откройте свой Gemfile
и обновите его чтобы заменить:
gem 'sqlite3'
на:
gem 'pg', '~> 1.0'
Для реальной установки этого нового gem нам потребуется исполнить bundle install
,
что мы делаем для перестроения своего образа (мы обсудим это в Главае 9,
Расширенное управление Gem. Давайте остановим свой сервер Rails:
$ docker-compose stop web
и после этого выполним повторную сборку своего образа:
$ docker-compose build web
Building web
Step 1/8 : FROM ruby:2.6
...
Step 6/8 : RUN bundle install
...
Installing pg 1.1.4 with native extensions
...
Bundle complete! 16 Gemfile dependencies, 69 gems now installed.
Bundled gems are installed into `/usr/local/bundle`
...
Removing intermediate container 9b01b1fa29fc
---> f9e6330d40b6
Step 7/8 : COPY . /usr/src/app/
---> 70fb0e2e0091
Step 8/8 : CMD ["bin/rails", "s", "-b", "0.0.0.0"]
---> Running in 16cc0923b855
Removing intermediate container 16cc0923b855
---> d4ffbe8f72d3
Successfully built d4ffbe8f72d3
Successfully tagged myapp_web:latest
Имея установленным gem Postgres, мы можем перейти к настройке своего database.yml
.
Когда мы создали свой проект Rails, мы сделали это с установками по умолчанию, которые предполагали что мы применяем для
своей базы данных sqlite
. Теперь, когда мы вместо неё настроили Postgres,
выработанный файл database.yml
не является верным. Нам необходимо изменить его
на нечто более подходящее.
Давайте откроем config/database.yml
в неком редакторе и заменим его содержимое
следующими настройками Postgres:
default: &default
adapter: postgresql
encoding: unicode
host: <%= ENV.fetch('DATABASE_HOST') %>
username: <%= ENV.fetch('POSTGRES_USER') %>
password: <%= ENV.fetch('POSTGRES_PASSWORD') %>
database: <%= ENV.fetch('POSTGRES_DB') %>
pool: 5
variables:
statement_timeout: 5000
development:
<<: *default
test:
<<: *default
database: myapp_test
production:
<<: *default
К счастью, всё выглядит для нас достаточно знакомым.
Мы определили наиболее важные установки (host
,
username
, password
и
database
) через переменные среды. Обычно это рассматривается в качестве
хорошей практики, однако, как мы
увидим позднее, Docker предоставляет некий даже более безопасных подход. В настоящий момент, тем не менее,
эти переменные среды не установлены для нашей веб службы web
.
Давайте исправим это. Нам придётся изменить свой docker-compose.yml
чтобы
обеспечить эти переменные настроенными на наш контейнер приложения Rails, подобно следующему:
version: '3'
services:
web:
build: .
ports:
- "3000:3000"
volumes:
- .:/usr/src/app
» environment:
» DATABASE_HOST: database
» POSTGRES_USER: postgres
» POSTGRES_PASSWORD: some-long-secure-password
» POSTGRES_DB: myapp_development
redis:
image: redis
database:
image: postgres
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: some-long-secure-password
POSTGRES_DB: myapp_development
В нашем мире до Docker мы обычно устанавливали значение DATABASE_HOST
в
localhost
, так как эта база данных исполнялась бы в нашей локальной машине.
Здесь, однако, мы определяем название той службы, которая исполняет Postgres: database
.
Это приводит к разрешению имён для контейнеров службы нашей database
благодаря DNS, предоставляемой нашей сетевой средой приложения.
Мы также настраиваем переменные среды POSTGRES_USER
,
POSTGRES_PASSWORD
и POSTGRES_DB
на соответствие настройкам для данной службы database
; это означает, что наша служба
web
будет иметь верные параметры доступа для регистрации в нашей базе данных.
Это должно теперь работать, однако обратим ваше внимание на то, что теперь у нас достаточно много переменных среды и
два дубля для служб web
и database
.
Мы также сказали, что не будем включать секретные коды в свой файл docker-compose.yml
чтобы мы могли зафиксировать их в своём источнике репозитория. Давайте убъём двух зайцев одним залпом и выделим переменные
среды в отдельные файлы.
Прежде всего давайте создадим некие каталоги для хранения своих специфичных для среды настроек:
$ mkdir -p .env/development
Затем создайте соответствующий файл .env/development/web
(без какого бы то ни было
расширения файла), который сожержит особые для службы web
переменные среды:
DATABASE_HOST=database
и другой файл, .env/development/database
, содержащий следующее для нашей
службы database
:
POSTGRES_USER=postgres
POSTGRES_PASSWORD=some-long-secure-password
POSTGRES_DB=myapp_development
Теперь нам требуется сообщить Compose о необходимости использования этих файлов вместо явной установки значений
переменных напрямую. Мы делаем это с помощью соответствующей директивы env_file
:
version: '3'
services:
web:
build: .
ports:
- "3000:3000"
volumes:
- .:/usr/src/app
» env_file:
» - .env/development/database
» - .env/development/web
redis:
image: redis
database:
image: postgres
» env_file:
» - .env/development/database
Мы могли бы назвать файлы своей среды как угодно, но я выбрал простую осмысленную схему именования. Точно также вы
можете применять любую файловую структуру и соглашения об именовании которые вам нравятся для данных файлов переменных
среды (в настоящее время в .env
), при условии вы верно ссылаетесь на них в самом
файле Compose.
Закончив это небольшое форматирование мы готовы создавать свои базы данных для разработки и тестирования при помощи
стандартной команды bin/rails db:create
нацелив эту команду на свою службу
web
:
$ docker-compose run --rm web bin/rails db:create
В данном случае мы воспользовались run --rm
вместо
exec
, так как у нас в данный момент исполняется контейнер
web
, который не имеет наших вновь добавленных переменных окружения пока мы его
не перезапустим. Это сделает наш новый одноразовый контейнер, который и запускает данную команду.
Вы должны обнаружить следующий вывод, отображающий что наша база данных была успешно создана:
Database 'myapp_development' already exists
Created database 'myapp_test'
Вы могли бы заметить, что наша база данных myapp_development
уже существует,
что несколько странно, так как это самый первый раз когда мы просим её создания. Это происходит по той причине, что
наш образ postgres
автоматически создаст некую базу данных при своём самом первом
запуске; если она устанавливается, он применяет своё значение переменной среды POSTGRES_DB
в качестве того самого названия для этой таблицы. В нашем случае это myapp_development
,
и именно по этой причине данная таблица уже имеется.
Отлично, мы уже почти на месте.
Получив настроенный на применение запущенной в контейнере базы данных Postgres Rails и создав базы данных, окончательный шаг
состоит в запуске нашего сервера Rails с вновь установленными настройкой и переменными среды. Однако поскольку Compose
будет только повторно применять для сервера имеющийся контейнер, нам придётся в явном виде сообщить ему о необходимости
повторной сборки контейнера для своей службы web
.
Вот как мы это делаем:
$ docker-compose up -d --force-recreate web
Параметр --force-recreate
сообщает: "Собери заново контейнер этой
службы."
Теперь двигайтесь далее и зайдите на http://localhost:3000
чтобы убедиться что
ваше приложение подключилось к Postgres; если всё хорошо, вы обнаружите стандартный экран запуска Rails, в то время как в случае
невозможности подключения ActiveRecord возбудит некую ошибку PG::ConnectionBad
.
Мы сделали это - он поднят и исполняется с Postgres.
Мы знаем, что настроив своё приложение Rails для общения с нашей базой данных Postgres это наше приложение Rails успешно запустилось; однако мы полагаемся на отсутствие ошибки в качестве подтверждения того что наша база данных корректно подключилась. Хотя с технической точки зрения это всё что нам требуется, давайте убедимся что всё работает должным образом выполняя взаимодействие с базой данных нашего приложения. Это также позволит нам получить дополнительную практику при разработке своего приложения Rails с Docker через CLI Compose.
Давайте выработаем для своего приложения Rails некий базовый UsersController
.
Для ускорения мы намерены воспользоваться командой Rails generate scaffold
:
$ docker-compose exec web \
bin/rails g scaffold User first_name:string last_name:string
invoke active_record
create db/migrate/20190115100954_create_users.rb
create app/models/user.rb
invoke resource_route
route resources :users
invoke scaffold_controller
create app/controllers/users_controller.rb
invoke erb
create app/views/users
create app/views/users/index.html.erb
create app/views/users/edit.html.erb
create app/views/users/show.html.erb
create app/views/users/new.html.erb
...
Пользователи Linux: владение файлами | |
---|---|
Убедитесь что вы выполнили
За дополнительными подробностями отсылаем к Дополнению A. Владельцы файлов и полномочия. |
Теперь нам требуется запустить миграцию для создания своей таблицы Users
.
web
. Вы уже должны начать привыкать к запуску стандартных команд Rails,
нацеленных на нашу веб- службу с использованием Compose, в точности так:
$ docker-compose exec web bin/rails db:migrate
== 20190115100954 CreateUsers: migrating ===================================
-- create_table(:users)
->> 0.0585s
== 20190115100954 CreateUsers: migrated (0.0587s) ==========================
Ладно, всё дложно пройти успешно - давайте попробуем. Имея всё ещё запущенным данное приложение, перейдите в
своём браузере к http://localhost:3000/users
. Вы должны обнаружить знакомые
строительные леса (scaffold) Rails и перечисленных пользователей как это показано на следующем рисунке. Убедитесь что у
вас имеется возможность создавать и удалять пользователей.
Великолепно, у нас имеется Postgres целиком настроенный в Compose.
Это прекрасно что мы настроили свою базу данных и поэтому мы теперь способны удерживать данные в своём приложении Rails. Однако, в настоящий момент существует основной провал в том как это работает. Давайте рассмотрим в чём состоит проблема и как его обойти.
Часть философии применения Docker состоит в том, что мы должны рассматривать контейнеры как эфемерные - одноразовые раскручиваемые нами штуки, которые мы применяем и затем удаляем. Однако наша база данных Postgres запускается в некотором контейнере и удерживает наши данные записывая и изменяя файлы на диске внутри самого контейнера. Что произойдёт с нашими данными когда мы удалим свой контейнер базы данных? Ага, вы уже догадались: мы скажем пока- пока всем своим горячо любимым данным. Как- то не совсем то чего бы мы хотели.
Теперь, когда мы намерены сохранять в своей базе данных важную информацию, нам необходимо подумать об этом слегка более аккуратно.
В точности как и в своём коде, в котором мы пытаемся отделить часто изменяющиеся вещи от тех которые не так этому подвержены, мы желаем отделить свои данные от самих контейнеров, которые их создают и применяют их. Наши данные следует хранить отдельно от самих контейнеров, которые их и исполняют. Таким образом мы можем удалять, уничтожать и воссоздавать такой контейнер не касаясь самих данных.
Ответ такой: мы храним постоянные данные в томах, которые по своей природе отсоединены от самого жизненного цикла контейнеров. Даже если мы удаляем некий контейнер с каким- то подключённым томом, сам том продолжит существовать независимо, сохраняя в безопасности наши данные. Затем мы можем воссоздать этот контейнер, подцепить этот том и всё шито- крыто.
Docker позволяет нам создавать несколько различных видов томов, каждый из которых выполняет собственное задание. Например, мы уже видели как смонтировать некий локальный том. Однако существует и другой вид тома, который лучше отвечает нашей цели. На самом деле нас не заботит где или как хранятся наши файлы, нас беспокоит лишь то, что они хранятся где- то отдельно. Для этого мы можем создать некий именованный том: автономную корзину (bucket) файлового хранилища, полностью управляемую Docker.
Но хватит теории; давайте посмотрим как это делать практически.
Именованные тома могут создаваться и управляться посредством соответствующей команды docker
volume
. Хотя об этом и стоит знать, раз уж мы применяем Compose, мы можем ему позволить обрабатывать
всё необходимое управление такими томами за нас.
Вот наш docker-compose.yml
изменённый для хранения наших постоянных данных
в неком томе:
1: version: '3'
-
- services:
-
5: web:
- build: .
- ports:
- - "3000:3000"
- volumes:
10: - .:/usr/src/app
- env_file:
- - .env/development/database
- - .env/development/web
-
15: redis:
- image: redis
-
- database:
- image: postgres
20: env_file:
- - .env/development/database
- volumes:
- - db_data:/var/lib/postgresql/data
-
25: volumes:
- db_data:
Самый первый шаг состоит в том чтобы сообщить Compose что нам требуется некий именованный том. Именованные тома
определяются под имеющимся свойством верхнего уровня volumes
(строка 25);
здесь мы определили некий именованный том с названием db_data
(строка 26).
Затем нам требуется сообщить Compose о необходимости монтирования этого именованного тома внутри своего контейнера
базы данных с применением уже знакомого нам свойства volumes
(строка 22).
Монтирование некого именованного тома аналогично монтированию какого- то локального каталога (строка 10) - единственное
отличие в том, что та часть, которая расположена до имеющейся точки ссылается на само название такого именованного тома
вместо локального пути. Здесь (строка 23) мы сообщаем, "Смонтируй наш именованный том
db_data
в /var/lib/postgresql/data
" -
том каталоге, в котором наш образ Postgres хранит свои файлы базы данных которые мы желаем видеть
постоянными.
Хорошо, давайте раскрутим это. Мы уже изменили определение своего Compose для нашей службы database
,
поэтому нам потребуется перезапустить его. Однако, опять же, поскольку Compose повторно использует тот же самый
контейнер для некоторой службы пока мы не попросим его о чём- то ином, нам придётся в явном виде сообщать Compose о
необходимости создавать заново этот контейнер database
чтобы прихватывать
настройки своего нового тома.
Вначале остановим свою службуdatabase
:
$ docker-compose stop database
Затем давайте явным образом удалим её контейнер:
$ docker-compose rm -f database
Compose не запросит у нас подтверждения перед удалением этого контейнера - параметр принудительного исполнения
-f
(force) сообщает о необходимости двигаться далее и выполнить это.
Хорошо, самое время вернуть нашу базу данных обратно:
$ docker-compose up -d database
Creating volume "myapp_db_data" with default driver
Creating myapp_database_1 ... done
Так как наш новый том теперь смонтирован в данном контейнере, мы стёрли все предыдущие базы данных и хранимые данные, следовательно нам требуется воссоздать необходимые базы данных и выполнить миграцию.
Давайте сделаем это сейчас:
$ docker-compose exec web bin/rails db:create db:migrate
Database 'myapp_development' already exists
Created database 'myapp_test'
== 20190115100954 CreateUsers: migrating ===================================
-- create_table(:users)
->> 0.0127s
== 20190115100954 CreateUsers: migrated (0.0143s) ==========================
Замечательно, теперь давайте убедимся что наше приложение всё ещё работает. Посетим в своём браузере
http://localhost:3000/users
и убедимся что нам видны строительные подпорки
нашего User
. Великолепно - наш том представляется работающим.
Давайте докажем что наши данные теперь остаются постоянно даже когда мы удаляем их контейнер базы данных. Прежде всего нам требуется запомнить некие данные: добавим одного или более пользователей через подмостки Rails. на следующем рисунке я создал для себя некого отдельного пользователя:
Теперь когда у нас имеются некие сохранённые данные, давайте остановим свой контейнер базы данных:
$ docker-compose stop database
Stopping myapp_database_1 ... done
а затем и удалим его (вам потребуется выдать подтверждение после получения запроса):
$ docker-compose rm database
Going to remove myapp_database_1
Are you sure? [yN] y
Removing myapp_database_1 ... done
Затем мы воссоздадим его и запустим его через:
$ docker-compose up -d database
Если это работает, мы должны увидеть данные своего пользователя, в точности как это было до того как мы удалили свой
контейнер базы данных. Перезагрузите свой браузер (http://localhost:3000/users
) и
... наши данные всё ещё здесь. Ура!
Но где на самом деле мои данные? | |
---|---|
Мы сказали что Docker управляет некой областью файловой системы для именованных томов, но где она расположена
в действительности? Мы можем обнаружить где расположен наш именованный том
Как мы можем видеть, именованные тома хранятся в |
В этой главе мы изучили как устанавливать и настраивать некую базу данных для своего приложения Rails - то что требуется для большинства приложений Rails.
Давайте повторим то что мы прошли:
-
При помощи Compose мы запустили некий сервер Postgres в контейнере.
-
Мы убедились что наш сервер Postgres был запущен подключившись с помощью клиента Postgres из некого отдельного контейнера.
-
Мы настроили своё приложение Rails на общение с Postgres установив требующийся gem Postgres, изменив свой файл
database.yml
и запустив соответствующую задачу Rake для создания требуемой базы данных. -
Мы продвинули свою новую базу данных, создав подмостки, выполнив миграции а также вставки, удаления и обновления записей.
-
Мы обсудили почему будет хорошей мыслью отделить наши контейнеры базы данных от сам их данных, которые мы хотим видеть постоянными.
-
Наконец, мы воспользовались именованным томом для хранения своих данных обособленно, позволяя нам управлять их жизненным циклом независимо от самого контейнера.
Теперь нам уже известно как добавлять две службы: Redis и Postgres. Вы должны быть способны применять те же самые знания для добавления прочих служб, о которых вы можете помышлять. {Прим. пер.: например, взамен Potgres поставить MS SQL Server, ха!} На самом деле в своей следующей главе мы добавим ещё одну службу, когда отвлечёмся от внутренних технологий чтобы изучить как внедрять современный интерфейс для вашего приложения Rails.