Начинаем работать с Ruby on Rails в Docker

Автор: admin от 1-08-2017, 11:45, посмотрело: 279

Начинаем работать с Ruby on Rails в Docker

Docker замечательно справляется с изолированием приложений и их окружений, облегчая распространение и репликацию состояний между различными средами (dev, test, beta, prod и т. д.). Его использование позволяет избавиться от проблемы «на моей машине все работает» и помогает с легкостью масштабировать приложение по мере его роста.



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



В этой статье мы возьмем простое приложение на Rails и подготовим его для использования в Docker-контейнере («докеризуем»).



Необходимые компоненты



Наше приложение будет написано под Rails 5; базу данных возьмем PostgreSQL. Если вы хотите подключить другую СУБД, то потребуется поправить несколько файлов.



Вы можете воспользоваться заранее подготовленным шаблоном для создания приложения, которое сконфигурировано с помощью Dockerfile и config/database.yml:



$ rails new --database=postgresql --skip-bundle --template=https://gist.githubusercontent.com/cblunt/1d3b0c1829875e3889d50c27eb233ebe/raw/01456b8ad4e0da20389b0b91dfec8b272a14a635/rails-docker-pg-template.rb my-app
$ cd my-app


Конфигурация базы данных



Для задания параметров базы данных мы воспользуемся переменными окружения. Они понадобятся позже для подключения к контейнеру с PostgreSQL.



Отредактируйте файл конфигурации config/database.yml



Если вы воспользовались приведенным выше шаблоном, то редактировать файл не нужно.



Добавьте в config/database.yml переменные окружения:



# config/database.yml
default: &default                                                                    
  adapter: postgresql                                                                
  encoding: unicode                                                                  
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  host: db
  username: <%= ENV.fetch('POSTGRES_USER') %>
  password: <%= ENV.fetch('POSTGRES_PASSWORD') %>

development:
  : *default                                                                       
  database: my-app_development

test:
  : *default                                                                       
  database: my-app_test

production:
  : *default                                                                       
  database: my-app_production


Создание Dockerfile



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



Для экономии дискового пространства я предпочитаю использовать базовый образ alpine-linux Ruby. Alpine linux — крошечный linux-дистрибутив, идеально подходящий для использования в контейнерах. В Docker доступен базовый образ ruby:alpine, которым мы и воспользуемся.



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



Если вы воспользовались приведенным выше шаблоном, то редактировать файл не нужно.



# /path/to/app/Dockerfile
FROM ruby:2.3-alpine

# Установка часового пояса
RUN apk add --update tzdata && 
    cp /usr/share/zoneinfo/Europe/London /etc/localtime && 
    echo "Europe/London" > /etc/timezone

# Установка в контейнер runtime-зависимостей приложения
RUN apk add --update --virtual runtime-deps postgresql-client nodejs libffi-dev readline sqlite

# Соберем все во временной директории
WORKDIR /tmp
ADD Gemfile* ./

RUN apk add --virtual build-deps build-base openssl-dev postgresql-dev libc-dev linux-headers libxml2-dev libxslt-dev readline-dev && 
    bundle install --jobs=2 && 
    apk del build-deps

# Копирование кода приложения в контейнер
ENV APP_HOME /app
COPY . $APP_HOME
WORKDIR $APP_HOME

# Настройка переменных окружения для production
ENV RAILS_ENV=production 
    RACK_ENV=production

# Проброс порта 3000 
EXPOSE 3000

# Запуск по умолчанию сервера puma
CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]                              


А что если я не хочу использовать PostgreSQL?



Если вы используете другую СУБД (например, MySQL), то для установки соответствующих пакетов потребуется внести изменения в Dockerfile.



Произвести поиск необходимых пакетов можно с помощью следующей команды Docker:



$ docker run --rm -it ruby:2.3-alpine apk search --update mysql | sort
...
mariadb-client-libs-10.1.22-r0
mariadb-dev-10.1.22-r0
mariadb-libs-10.1.22-r0
mysql-10.1.22-r0
mysql-bench-10.1.22-r0
...


Поскольку Dockerfile уже готов, пора запустить сборку Docker-образа для нашего приложения:



Собираем образ



$ docker build . -t my-app


Образ готов, можно начинать! Запустите контейнер следующей командой:



$ docker run --rm -it --env RAILS_ENV=development --env POSTGRES_USER=postgres --env POSTGRES_PASSWORD=superSecret123 --publish 3000:3000 --volume ${PWD}:/app my-app


Мы передали команде docker run несколько аргументов:




  • -it — на самом деле это 2 аргумента, которые позволяют взаимодействовать с контейнером с помощью командной оболочки (например, чтобы передать комбинацию клавиш Ctrl+C);

  • --env — позволяет передать контейнеру переменные окружения. Здесь они используются для установки параметров подключения к базе данных;

  • --rm — говорит докеру удалить контейнер после завершения его работы (например, после нажатия Ctrl+C);

  • --publish — пробрасывает порт 3000 контейнера на порт 3000 хоста. Таким образом у нас появляется возможность подключиться к сервису так, как будто он запущен напрямую на хосте (например, http://localhost:3000);

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



Запуск контейнера базы данных



Хотя контейнер с приложением и запустился, попытка открыть ссылку localhost:3000, к сожалению, приведет к ошибке:



could not translate host name “db” to address: Name does not resolve


У нас пока нет доступного приложению PostgreSQL-сервера. Сейчас мы это починим, запустив Docker-контейнер с PostgreSQL:






Совет. Не забывайте, что в Docker один контейнер должен выполнять одну и только одну функцию.



В нашем случае будет 2 контейнера: один для приложения и один для базы данных (PostgreSQL).






Запуск нового контейнера с PostgreSQL



Для остановки (и удаления) контейнера с приложением нажмите Ctrl+C, затем запустите новый контейнер с PostgreSQL:



$ docker run -d -it --env POSTGRES_PASSWORD=superSecret123 --env DB_NAME=my-app_development --name mydbcontainer postgres:9.6


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



Использование однозадачных (Single–Task) контейнеров



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



Они идеальны для разовых задач, таких как команды rails (например, bin/rails db:setup).



Для настройки базы данных в mydbcontainer мы сейчас и выполним такую команду .



Выполнение задачи rails db:migrate с использованием контейнера



Для запуска копии контейнера с приложением выполните следующую команду. Затем запустите в контейнере bin/rails db:setup и выключите его.



Обратите внимание: вам потребуется настроить переменные окружения для соединения с базой данных (они вставляются в config/database.yml, который вы ранее редактировали).



Опция --link позволит подключиться к контейнеру с PostgreSQL (mydbcontainer), используя имя хоста db:



$ docker run --rm --env RAILS_ENV=development --env POSTGRES_USER=postgres --env POSTGRES_PASSWORD=superSecret123 --link mydbcontainer:db --volume ${PWD}:/app my-app bin/rails db:create db:migrate


Флаг --rm удалит контейнер после завершения его работы.



После выполнения этой команды в контейнере mydbcontainer будет настроенная под нужны приложения база данных. Наконец-то мы сможем его запустить!



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



Давайте запустим еще один контейнер на основе образа нашего приложения. Обратите внимание на несколько дополнительных опций команды:



$ docker run --rm -it --env RAILS_ENV=development --env POSTGRES_USER=postgres --env POSTGRES_PASSWORD=superSecret123 --publish 3000:3000 --volume ${PWD}:/app --link mydbcontainer:db my-app

=> Puma starting in single mode...
=>  * Version 3.8.2 (ruby 2.4.1-p111), codename: Sassy Salamander
=>  * Min threads: 5, max threads: 5
=>  * Environment: development
=>  * Listening on tcp://0.0.0.0:3000
=>  Use Ctrl-C to stop


Откройте в браузере страницу localhost:3000, где вы должны увидеть наше приложение, работающее полностью из-под Docker!



Следующие шаги



Docker — это очень удобный инструмент разработчика. Со временем вы можете перенести в него все компоненты своего приложения (БД, redis, рабочие процессы sidekiq, cron и т. д.).



Следующим шагом будет использование Docker Compose, предназначенного для описания контейнеров и способов их взаимодействия.



Ссылки:




  • Оригинал: Rails on Docker: Getting Started with Docker and Ruby on Rails.


  • Источник: Хабрахабр

    Категория: Системное администрирование / Веб-разработка

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

    Добавление комментария

    Имя:*
    E-Mail:
    Комментарий:
    • bowtiesmilelaughingblushsmileyrelaxedsmirk
      heart_eyeskissing_heartkissing_closed_eyesflushedrelievedsatisfiedgrin
      winkstuck_out_tongue_winking_eyestuck_out_tongue_closed_eyesgrinningkissingstuck_out_tonguesleeping
      worriedfrowninganguishedopen_mouthgrimacingconfusedhushed
      expressionlessunamusedsweat_smilesweatdisappointed_relievedwearypensive
      disappointedconfoundedfearfulcold_sweatperseverecrysob
      joyastonishedscreamtired_faceangryragetriumph
      sleepyyummasksunglassesdizzy_faceimpsmiling_imp
      neutral_faceno_mouthinnocent