Locomotive CMS (Ruby on Rails + Docker)

Locomotive CMS

https://www.locomotivecms.com/

Wagon(コマンドラインツール)でサイトの雛形を作成し、その雛形をEngine(サーバ)へアップロード(デプロイ)。ウェブサイトのバックエンドとしてEngineを使用しサイトの詳細を構成していくCMS。

EngineのGitHubソースマスターはRuby3.1に対応していますが、WagonのRuby対応バージョンは2.7のため、Dockerコンテナで運用する場合には、ソースマスターのEngineのみをコンテナとして稼働し、Wagonは直接ホストマシンにインストールするなどした方が良いでしょう。

WagonとEngineを共にDockerコンテナ内で動作させる場合にはRuby2.7イメージを選択します。Ruby2.7で動作するEngineの最新版はv4.1.1ですが、現時点での最新安定版となっています。

Engine

$ git clone -b v4.1.1 --single-branch https://github.com/locomotivecms/engine.git

Wagon


ドキュメント

ホストの設定

engine/spec/dummy/config/environments/development.rb

  config.hosts << 'locomotive.local'

注)Engineのソースマスター最新版をインストールした場合に必要となる処置です。


ホストマシンの /etc/hosts に上記を追加。

/etc/hosts

127.0.0.1       localhost locomotive.local

MongoDBの設定

以下該当箇所をアンコメントして有効化(ユーザ、パスワード、MongoDBサーバアドレス:ポートなどを指定)

engine/spec/dummy/config/mongoid.yml

      hosts:
        - mongodb:27017
      options:

        # The name of the user for authentication.
        user: 'user'

        # The password of the user for authentication.
        password: 'password'

        # The user's database roles.
        roles:
          - 'dbOwner'

        # Change the default authentication mechanism. Valid options are: :scram,
        # :mongodb_cr, :mongodb_x509, and :plain. (default on 3.0 is :scram, default
        # on 2.4 and 2.6 is :plain)
        auth_mech: :scram

        # The database or source to authenticate the user against. (default: admin)
        auth_source: admin

Docker環境構築

最新安定版のEngine:v4.1.1とWagonを含んだDockerイメージを作成。
注)Wagonの最新版は、Rubyバージョン3以降では対応していないため、Ruby2.7でDockerfileを作成。Wagonについては、最新バージョン以降ソースコードが更新されていないことからgemコマンドで直接インストールします。

Engineをダウンロード

$ mkdir docker_files && cd docker_files
$ git clone -b v4.1.1 --single-branch https://github.com/locomotivecms/engine.git

Dockerfileの作成

docker_files/dockerfile_engine

FROM ruby:2.7-bullseye
RUN apt-get update -qq && apt-get install -y nano imagemagick python2
RUN curl -fsSL https://deb.nodesource.com/setup_current.x | bash - && apt-get install -y nodejs && npm install --global yarn
WORKDIR /locomotive/engine
# $ git clone -b v4.1.1 --single-branch https://github.com/locomotivecms/engine.git
COPY engine /locomotive/engine
RUN bundle install && yarn
RUN gem install locomotivecms_wagon
#EXPOSE 3000

# Configure the main process to run when running the image
#CMD ["rails", "server", "-b", "0.0.0.0"]

Docker Composeファイルの作成

docker_filesの上位ディレクトリに移動してdocker-composeファイルを作成します。データベースサーバとしてEngineで指定されているMongoDB:6を選択しています。

docker-compose.yml

version: '3.7'
services:
  mongodb:
    container_name: mongodb
    image: mongo:6.0
    restart: always
    ports:
      - "27017:27017"
    volumes:
      - ./db:/data/db
    environment:
      MONGO_INITDB_ROOT_USERNAME: user
      MONGO_INITDB_ROOT_PASSWORD: password
    networks: 
      proxy-tier:
        ipv4_address: 172.20.0.2
      
  ## locomotivecms_engine
  engine:
    container_name: engine
    build: 
      context: ./docker_files
      dockerfile: dockerfile_engine
    command: bash -c "bundle exec rails s -p 3000 -b '0.0.0.0'"
    restart: always
    volumes:
      - ./docker_files/engine/spec:/locomotive/engine/spec
      - ./sites:/locomotive/sites
    ports:
      # for engine
      - "3000:3000"
      # for wagon
      - "3333:3333"
      # for webpack-livereload-plugin
      - "35729:35729"
    depends_on:
      - mongodb
    networks: 
      proxy-tier:
        ipv4_address: 172.20.0.3
        
# For IPv4 only
# docker network create --gateway 172.20.0.1 --subnet 172.20.0.0/24 containers-network

networks:
  proxy-tier:
    name: containers-network-locomotive
    external: true

前記事で投稿したホストの設定とMongoDB関連ファイルの設定をします。
engine/spec/dummy/config/environments/development.rb
engine/spec/dummy/config/mongoid.yml

コンテナを起動

$ docker compose up -d

http://localhost:3000 (—> リダイレクト http://locomotive.local:3000

サンプルサイトの起動

サンプルサイトを以下からダウンロード
wagon/spec/fixtures at master · locomotivecms/wagon · GitHub

ダウンロードしたfixturesフォルダを/locomotive/sitesフォルダにコピー
(docker-composeファイルのvolumes参照)

注)-h オプションでコンテナIPをホストとして指定すること

$ docker compose exec engine bash
# cd /locomotive/sites
# wagon serve -h 172.20.0.3 fixtures/default

http://localhost:3333

新規サイトの作成

$ docker compose exec engine bash
# cd /locomotive/sites
# wagon init mysite
# wagon serve -h 172.20.0.3 mysite
Your site is served now.
Browse http://172.20.0.3:3333

http://localhost:3333にアクセスすると下記デフォルトテキストが表示されます。

Home page

Go to app/views/pages/index.liquid to modify the home page


UIの追加: wagon generate section

# cd /locomotive/sites/wagon/mysite
# wagon generate section hero --no-global -i image_text title:text subtitle:text background_image:image_picker -p spec/test_sites/mysite
      create  app/views/sections/hero.liquid
      create  app/assets/javascripts/sections/hero.js
      append  app/assets/javascripts/sections/index.js
      insert  app/assets/javascripts/app.js
      create  app/assets/stylesheets/sections/hero.scss
      insert  app/assets/stylesheets/app.scss

下記.liquidファイルには2つの設定項目が含まれていて、上部がバックエンドのUIに関する設定で下部がそのテンプレートとなります。下部のテンプレートを以下の内容に置き換えます。

app/views/sections/hero.liquid

<section id="{{ section.anchor_id }}" class="hero hero-section is-large is-relative" {{ section.locomotive_attributes }}>
  <div style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: center / cover no-repeat url('{{ section.settings.background_image }}'); opacity: 0.4"></div>
  <div class="hero-body">
    <div class="container">
      <h1 class="title">
        {{ section.settings.title }}
      </h1>
      <h2 class="subtitle">
        {{ section.settings.subtitle }}
      </h2>
    </div>
  </div>
</section>

content type

# wagon generate content_type projects name:string client:string description:text image:file
       exist  
      create  app/content_types/projects.yml
      create  data/projects.yml
# wagon generate section --no-global -i list latest_projects title:text projects:content_type
      create  app/views/sections/latest_projects.liquid
      create  app/assets/javascripts/sections/latest_projects.js
      append  app/assets/javascripts/sections/index.js
      insert  app/assets/javascripts/app.js
      create  app/assets/stylesheets/sections/latest_projects.scss
      insert  app/assets/stylesheets/app.scss

以下ファイルのテンプレートの範囲を入れ換え

app/views/sections/latest_projects.liquid

<div id="{{ section.anchor_id }}" class="section latest-projects-section" {{ section.locomotive_attributes }}>
  <h2 class="title is-2">{{ section.settings.title }}</h2>

  <div class="columns is-multiline">
    {% for project in contents.projects %}
      <div class="column is-half">
        <div class="card">
          <div class="card-image">
            <figure class="image is-4by3">
              <img src="{% if project.image.url is blank %}https://bulma.io/images/placeholders/1280x960.png{% else %}{{ project.image.url | resize: '800x800#' }}{% endif %}" alt="{{ project.name }}">
            </figure>
          </div>
          <div class="card-content">
            <div class="media">
              <div class="media-content">
                <p class="title is-4">{{ project.name }}</p>
                <p class="subtitle is-6">{{ project.client }}</p>
              </div>
            </div>
            <div class="content">
              {{ project.description }}
            </div>
          </div>
        </div>
      </div>
    {% endfor %}
  </div>
</div>

インデックスページにセクションを表示

app/views/pages/index.liquid

---
title: Home page
published: true
sections_content:
  hero:
    settings:
      title: "Hello world!"
      subtitle: "This is my first section in action"
      background_image: "/samples/images/default.svg"
    blocks: []

  latest_projects:
    settings:
      title: "Our latest projects"
    blocks: []
---
{% extends 'layouts/default' %}

{% block 'main' %}

  {% section 'hero' %}

  {% section 'latest_projects' %}

{% endblock %}

app/views/pages/layouts/default.liquid

---
title: Default layout
is_layout: false
---
<!DOCTYPE html>
<html lang="{{ locale }}">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/css/bulma.min.css">

    {% seo %}

    {{ 'bundle.css' | stylesheet_tag }}
    {{ 'bundle.js' | javascript_tag }}

    {% if wagon %}
      <script src="http://localhost:35729/livereload.js"></script>
    {% endif %}
  </head>
  <body>
    {% block 'main' %}
    {% endblock %}
  </body>
</html>

Webpackの操作

サイトレンダリングに必要なjsファイルとcssファイルをWebpack(npm)で作成します。

package.json に記載されている依存モジュールをインストールします。

package.json

{
  "name": "Mysite",
  "version": "1.0.0",
  "description": "Assets source for the mysite website",
  "main": "index.js",
  "scripts": {
    "start": "webpack --config app/assets/webpack.dev.js --progress --colors --watch",
    "build:dev": "webpack --config app/assets/webpack.dev.js --progress",
    "build:prod": "NODE_ENV=production webpack --config app/assets/webpack.prod.js --progress --mode production",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Wagon",
  "license": "ISC",
  "dependencies": {
    "bulma": "^0.9.4"
  },
  "devDependencies": {
    "@babel/core": "^7.4.3",
    "@babel/plugin-proposal-class-properties": "^7.4.0",
    "@babel/preset-env": "^7.4.3",
    "autoprefixer": "^9.7.3",
    "babel-loader": "^8.0.5",
    "css-loader": "^0.28.11",
    "file-loader": "^1.1.11",
    "image-webpack-loader": "^4.3.0",
    "mini-css-extract-plugin": "^0.4.0",
    "optimize-css-assets-webpack-plugin": "^4.0.2",
    "postcss-flexbugs-fixes": "^3.3.1",
    "postcss-loader": "^2.1.5",
    "sass": "^1.49.9",
    "sass-loader": "^7.0.1",
    "style-loader": "^0.21.0",
    "webpack": "^4.20.2",
    "webpack-cli": "^3.1.1",
    "webpack-livereload-plugin": "^2.2.0",
    "webpack-merge": "^4.1.4"
  }
}

上記ファイル内のscriptsセクション内の以下のスクリプトに関しては、yarn または npm run-script コマンドを使用します。

build:dev
webpack --config app/assets/webpack.dev.js --progress
build:prod
NODE_ENV=production webpack --config app/assets/webpack.prod.js --progress --mode production

# yarn

# yarn start

or

# yarn build:prod

または

# npm install

# npm start

or

# export NODE_OPTIONS=--openssl-legacy-provider
# npm run-script build:prod

注)export NODE_OPTIONS=–openssl-legacy-provider

CSSフレームワークBulmaの導入

# yarn add bulma

または

# npm add bulma

app/assets/stylesheets/bulma_variables.scss

$family-sans-serif: 'Roboto Condensed', sans-serif;

// Colors
$lighter-blue: #bdd1e4;
$light-blue: #8aacd4;
$dark-blue: #224261;
$dark-grey: #636466;
$light-grey: #a7a9ac;
$brown-orange: #E3A346;

$primary: $dark-blue;
$warning: $brown-orange;

// Navbar
$navbar-height: 7.25rem !default;

app/stylesheets/app.scss
以下の内容を追加

// Bulma
@import '~bulma/bulma.sass';
@import './bulma_variables';

cssファイルの更新

# npm start

or

# npm run-script build:prod

サイトの起動

# wagon serve -h 172.20.0.3
NOTE: nokogumbo: Using Nokogiri::HTML5 provided by Nokogiri. See https://github.com/sparklemotion/nokogiri/issues/2205 for more information.
Your site is served now.
Browse http://172.20.0.3:3333

サイトのデプロイ(アップロード)

はじめにログインするサーバでユーザ認証を行います。

# cd /locomotive/sites/mysite
# wagon auth
Locomotive Sign in/up

Enter the URL of your platform? (default: https://station.locomotive.works) http://locomotive.local:3000
Enter your e-mail? [email protected]
Enter your password? 
You have been successfully authenticated.

サイトをデプロイします。

# wagon deploy test -v -d
NOTE: nokogumbo: Using Nokogiri::HTML5 provided by Nokogiri. See https://github.com/sparklemotion/nokogiri/issues/2205 for more information.
You are about to deploy a new site
Are you sure you want to perform this action? (answer yes or no) yes
What is the URL of your platform? (default: https://station.locomotive.works) http://locomotive.local:3000
What is the handle of your site? (default: a random one) 
Warning! You're about to deploy data which will alter the content of your site.
Are you sure you want to perform this action? (answer yes or no) yes

Pushing Site
  persisting mysite [done]

Pushing ContentTypes
  persisting Projects [done]
  persisting Projects with relationships [skip]

Pushing ContentEntries
  persisting Projects / Sample 1 [done]
  persisting Projects / Sample 2 [done]
  persisting Projects / Sample 3 [done]
  persisting Projects / Sample 4 [done]
  persisting Projects / Sample 1 with relationships [skip]
  persisting Projects / Sample 2 with relationships [skip]
  persisting Projects / Sample 3 with relationships [skip]
  persisting Projects / Sample 4 with relationships [skip]

Pushing Pages
  persisting 404 (en) [done]
  persisting index (en) [done]
  persisting layouts (en) [done]
  persisting layouts/default (en) [done]

Pushing Snippets

Pushing Sections
  persisting Hero [done]
  persisting Latest projects [done]

Pushing ThemeAssets
  persisting stylesheets/bundle.css [done]
  persisting javascripts/bundle.js [done]

Pushing Translations


Your site has been deployed.

To preview your site, visit: http://locomotive.local:3000/locomotive/energized-foliage-6811/preview
To edit the content of your site, visit: http://locomotive.local:3000/locomotive/sign_in

サーバにはlocomotive.local:3000、Engineにユーザ登録しているメールアドレスとパスワードを入力すると以下のファイルにデプロイ設定が反映されます。

mysite/config/deploy.yml

# development:
#   host: dev.example.com
#   email: [email protected]
#   password: apassword
#   # api_key: <your api key here>
# staging:
#   host: staging.example.com
#   email: [email protected]
#   password: apassword
#   # api_key: <your api key here>
# production:
#   host: www.example.com
#   email: [email protected]
#   password: apassword
#   # api_key: <your api key here>
#   # ssl: true  

test:
  host: locomotive.local:3000
  handle: withered-fern-xxxx
  email: [email protected]
  api_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

http://locomotive.local:3000

デプロイしたサイトのダッシュボード

Engineで編集