Докеризация Rails-приложения для производственного развертывания

После многих лет использования ручных инструментов для развертывания приложений Ruby on Rails, несколько лет назад я изменил свою стратегию развертывания на использование контейнеров Docker, и это было отличное решение!

Этот учебник предназначен для новичков, которые хотят докеризировать свое новое (или существующее) Rails-приложение.

ℹ️ Вы можете скачать все файлы на моем репозитории Github.


Оглавление

  • Зачем докеризировать мое Rails-приложение?
  • Начиная с базового Rails-приложения
    • Настройка
  • Давайте начнем!
    • Файл config/database.yml
    • Dockerfile
    • .dockerignore
    • Сборка контейнера
  • Переходим к производству!
    • Файл Docker Compose
    • Запуск нашего приложения
    • Доступ к консоли Rails
  • Обновление контейнеров
  • Настройте свой веб-сервер
  • Заключительный совет!

Зачем докеризировать мое Rails-приложение?

Превращение вашего Rails-приложения в контейнеры docker для развертывания на производстве может ускорить ваше развертывание, предотвратить ошибки и значительно облегчить переход от одного поставщика услуг к другому. Это облегчило мою жизнь (и я уверен, что может облегчить и вашу!).

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

Также легко обновлять контейнер, запускать тесты, использовать CI/CD и автоматически развертывать новую версию.

Начнем с базового Rails-приложения

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

Настройка

Все настраивается на локальной машине. Rails подключается к PostgreSQL через порт 5432 и обслуживает приложение для браузеров через порт 3000.

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

Ниже приведен скриншот работающего приложения.

Давайте начнем!

Есть несколько шагов для создания контейнера для запуска нашего приложения.

  1. Настройте конфигурацию подключения к базе данных.
  2. Напишите dockerfile и создайте контейнер.
  3. Загрузите контейнер на любой провайдер (бесплатно и по желанию).
  4. Напишите файл Docker Compose для выполнения вашего приложения на продакшене.

Файл config/database.yml.

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

default: &default
  adapter: postgresql
  port: 5432
  pool: 5
  timeout: 5000
  host: localhost
  username: postgres
  password: postgres

development:
  <<: *default
  database: devel_db

test:
  <<: *default
  database: test_db

production:
  <<: *default
  database: production_db
Войти в полноэкранный режим Выход из полноэкранного режима

Как вы можете видеть, вся конфигурация подключения к базе данных привязана к текущему окружению. Это может работать для локальных сред, но в качестве хорошей практики мы должны изменить их на переменные среды, чтобы мы могли легко настроить их для любой новой среды, в которой мы публикуем наше приложение.

Давайте пока изменим host, username и password. Остальные параметры также можно изменить, но я не хочу, чтобы этот учебник был слишком сложным 😉

host: <%= ENV['DB_HOST'] || 'localhost' %>
username: <%= ENV['DB_USERNAME'] || 'postgres' %>
password: <%= ENV['DB_PASSWORD'] || 'postgres' %>
Вход в полноэкранный режим Выйти из полноэкранного режима

⚠️ Обратите внимание, что мы установили значения по умолчанию для всего.

Dockerfile

Следующим шагом будет создание файла Dockerfile в корневом каталоге вашего приложения. Этот файл будет инструктировать docker о том, как собрать приложение на основе выбранного вами образа.

Я решил использовать образ ruby:2.7.6-bullseye, потому что он основан на Debian 11 (Bullseye), а мне нравится (и я привык) к этому дистрибутиву.

FROM ruby:2.7.6

# Directory where the app will be installed on the container
WORKDIR /app

# Install NodeJS 14 repository
RUN curl -fsSL https://deb.nodesource.com/setup_14.x | bash -

# Update the system and install NodeJS
RUN apt-get update && apt-get -y install 
  nodejs 
  vim 
  && rm -rf /var/lib/apt/lists/*

# Install ruby gems
COPY Gemfile Gemfile.lock ./
RUN bundle install

# Install Yarn globally
RUN npm install -g yarn

# Run `yarn install`
COPY package.json yarn.lock ./
RUN yarn install

# Copy the application file to the container
COPY . .

# Pre-compile assets for production
RUN RAILS_ENV=production bundle exec rails assets:precompile

# Sets the default command that will run when the container starts
CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"]
Вход в полноэкранный режим Выход из полноэкранного режима

ℹ️ Больше информации о Dockerfile можно найти по этой ссылке.

Файл .dockerignore

Есть файлы и папки, которые мы не хотим копировать в наш контейнер docker, потому что они не имеют отношения к приложению или будут сгенерированы при создании контейнера. Это папки сборки, временные файлы, журнал и т.д.

Создайте файл .dockerignore в корневой папке вашего проекта и добавьте в него эти строки:

node_modules/
log/
tmp/
Войти в полноэкранный режим Выйти из полноэкранного режима

Сборка контейнера

Теперь пришло время собрать контейнер нашего приложения.

⚠️ ВАЖНО: Атрибут tag — это имя контейнера. Обязательно измените его на имя вашего репозитория Doker Hub или используйте любое имя, если вы не собираетесь размещать его в облаке.

docker build . --tag fshayani/dockerizing_rails_application:latest
Вход в полноэкранный режим Выход из полноэкранного режима

После успешной сборки контейнера мы загрузим его в Docker Hub. Таким образом, я смогу автоматически загрузить его на свой рабочий сервер.

ℹ️ Это необязательный шаг. Вы можете пропустить этот шаг, если собираетесь собрать контейнер и использовать его на одной машине.

docker push fshayani/dockerizing_rails_application:latest
Вход в полноэкранный режим Выход из полноэкранного режима

Переходим к производству!

Теперь, когда мы создали наш контейнер приложений (и, возможно, разместили его в облаке; а вы?), пришло время перейти на производственный сервер и развернуть это приложение!

Нам нужно указать Docker, как получить и запустить контейнер, и это можно легко сделать с помощью docker compose.

ℹ️ Существуют и другие технологии для развертывания контейнеров в производстве вместо Docker Compose, такие как Kubernetes, Docker Swarm, AWS ECS и т.д.; но это не входит в рамки данного руководства.

Файл Docker Compose

Создайте файл docker-compose.yml на производственном сервере. Он может быть размещен где угодно, но будьте организованы! 😉

services:
  app: # That's the name of our application container
    image: fshayani/dockerizing_rails_application:latest # The container Docker will use
    ports:
     - 3000:3000 # Map localhost:3000 to the container's port 3000
    environment:
      - DB_HOST=db # The name of our PostgreSQL container
      - DB_USERNAME=postgres # PostgreSQL credentials
      - DB_PASSWORD=postgres
      - RAILS_ENV=production # We are on Production now!
      - RAILS_SERVE_STATIC_FILES=true # Assets were already built by Dockerfile ;)
      - RAILS_LOG_TO_STDOUT=true # So we can see Rails logs with `docker compose logs` command
      - RAILS_MASTER_KEY=my_ultra_top_secret_master_key!! # Use you master key. There are better ways to keep this secret.
    depends_on:
      - db # Will start the container `db` before

  db:
    image: postgres:14
    environment:
      - POSTGRES_USER=postgres # Will create a instance of PostgreSQL with this credentials
      - POSTGRES_PASSWORD=postgres
    volumes:
      - postgres:/var/lib/postgresql/data # Map PostgreSQL data to a persistant volume called `postgres`

volumes:
  postgres: # Create a persistant volume on local machine, so we do not loose our DB on restarts

Вход в полноэкранный режим Выход из полноэкранного режима

Запуск нашего приложения

Теперь, когда все готово, давайте запустим наше приложение на рабочем сервере!

⚠️ ВНИМАНИЕ: Если мы впервые запускаем приложение на сервере,
вероятно, ваша база данных будет пуста. У вас есть два варианта: dump и restore.
вашу базу данных в контейнере db или создать новую с нуля, выполнив сначала эту команду:

docker compose up
Войти в полноэкранный режим Выйдите из полноэкранного режима

и откройте браузер на http://localhost:3000 😄 Вы увидите, что ваше приложение запущено!

ℹ️ СОВЕТ: Добавьте флаг -d к команде, чтобы запустить ее в фоновом режиме.

Доступ к консоли Rails

С помощью Docker Compose мы можем взаимодействовать с нашим контейнером и выполнять на нем любые команды (включая bash при необходимости).

docker compose exec app bundle exec rails console
Вход в полноэкранный режим Выход из полноэкранного режима

Обновление контейнеров

Когда вы создаете новую версию своего приложения и хотите развернуть ее на продакшене, все, что вам нужно сделать, это:

  1. Создайте новый образ.
  2. Снова отправить его в облако.
  3. Вытащить его на производственный сервер (docker compose pull).
  4. Перестроить стек docker compose (docker compose down; docker compose up).

Настройте свой веб-сервер

Теперь, когда ваше приложение развернуто на рабочем сервере, вам нужно настроить любой веб-сервер (Apache, Nginx и т.д.) для обратного проксирования любых обращений к вашему домену на порт 3000 на localhost.

Это тема для другого поста 😉

Последний совет!

Существует приложение Watchtower, которое может автоматически получать любой новый контейнер, загруженный вами в Docker Hub, автоматически извлекать его и перестраивать стек docker compose. Взгляните на него 😉

Оцените статью
devanswers.ru
Добавить комментарий