見出し画像

修行のために何かを作る話(最初のページ作成)

この話の続き

今回でトップページ一枚作って、リクエストに応じてトップページを返すだけのwebページまで辿り着く。

構成

RDBMSはPostgreSQL 12.5。仕事で使ってるから。

ローカルのDBはPostgreSQL on Dockerとする。他の開発環境とDBのバージョンでかち合っても良いことないので。
RailsはとりあえずDockerには乗せない。Docker for Macが遅いのが主な理由。

PostgreSQL on Docker

そんなに書くことはない。
DockerイメージはDockerHubから持ってきたものを動かすくらいだし、特段他のDockerイメージと協調することもない。
ただ起動のオプションを覚えておくのが面倒なので、起動シェル作った、くらい。

#!/bin/bash
docker run --rm -d \
 -p 5432:5432 \
 -v postgres-tmp:/var/lib/postgresql/data \
 -e POSTGRES_HOST_AUTH_METHOD=trust \
 --name blog_postgresql \
 postgres:12.5

止めるときは以下のコマンドを手打ちしているが、上記シェルに起動オプション/停止オプションを受け付けられるようにしても良いかも。そのうち。

$ docker stop blog_postgresql

DB接続と最初のページ

ローカルの接続は大した苦労はなし。
pg gemを導入し、sqlite3 gemを消し、database.ymlをよくある感じで設定したらdb:createが通った。
database.ymlのローカル部分はこんな感じ。

# config/database.yml
default: &default
 adapter: postgresql
 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
 timeout: 5000
 encoding: unicode
 username: postgres
 password:
 host: localhost
 port: 5432

development:
 <<: *default
 database: blog_development

最初のページは伝統の「工事中」ページにした。controller、route、viewだけある状態。

スクリーンショット 2021-02-14 16.19.50

RDS設定

事前の予定通りdb.t3.microでインスタンスを作成する。

RDSを作るときに以下のエラーで怒られた。

DB Subnet Group doesn't meet availability zone coverage requirement. Please add subnets to cover at least 2 availability zones. Current coverage: 1

エラーメッセージの通り、RDSインスタンスに割り当てるDBサブネットは少なくとも2つのAZにまたがっていないといけない模様。
なんでこの制約があるのかは分かっていない。
が、zennの記事でprivateとpublicのsubnetを違うAZで作っていた理由が今分かった。

対処としてはprivateのsubnetをap-northeast-1cに作り直した。
dbインスタンスは自動でprivateの方のsubnetに入ってくれていたが、これはpublicアクセス無しの設定で作ったからかな…?

databaseアクセス用のSecurity Groupを作成して、EC2からのPostgreSQLのポートへのアクセスのみ許可としてRDSインスタンスに設定して完了。

本番環境でRDSと接続する

PostgreSQLと接続するために pg gemをインストールする。
インストール時にヘッダーの不足で怒られた。postgresql-develが必要だった。

なお、この時にこちらの別Noteで記載したPLATFORMSの問題が発生したので、一回EC2にインストールしたgemを全部消して入れ直した。

$ bundle exec gem uninstall -aIx

# bundlerも消しちゃったので入れ直し。Gemfile.lockとバージョンをあわせる。
$ gem install bundler:2.2.8
$ bundle install

とりあえずdb:create…でもうちょっと苦しんだ。

$ bin/rake db:create
rake aborted!
Cannot load database configuration:
YAML syntax error occurred while parsing /path/to/config/database.yml. Please note that YAML must be consistently indented using spaces. Tabs are not allowed. Error: (<unknown>): found character that cannot start any token while scanning for the next token at line 31 column 13


Caused by:
Psych::SyntaxError: (<unknown>): found character that cannot start any token while scanning for the next token at line 31 column 13

エラーの箇所はdbのpasswordを指定してる箇所で、文字列の先頭が特殊文字だったためパースに失敗していた模様。
それなりに複雑なパスワードを生成して、それを環境変数参照で取ってきた時にうまく扱えなかった。
database.ymlの当該箇所の値をダブルクォーテーションで囲んでOK。

# in config/database.yml

password: "<%= ENV['POSTGRESQL_PASSWORD'] %>"

デプロイ&確認

以前port 3000で立ち上げてアクセスを確認していたが、あれではダメだったっぽい。
pumaとnginxの設定をして立ち上げた。
設定内容はだいたいzennの記事と以下のページを参考にした。

なおdaemonizeはPuma 5.0.0で削除されている。理由は以下の通り。

OSのsystemdに管理を任せるべきだという話の模様。理解した。

systemdでpumaの起動を管理する

pumaのドキュメンテーションは凄くしっかりしてて、systemdの書き方もサンプルがあった。

とはいえRailsでの場合もサンプルで欲しかったので以下も参考にした。

なるほどbinstubでsbin下を作ってそこにpumaコマンドを通すやり方があるのね。

なお、上記ページそれぞれにサンプルのsystemd設定があるが、自分の構築した環境ではどれも期待通り動かなかった。詳しくはこちらの別Note参照。

以下の方法で環境を構築している場合、systemdのserviceの記載はその環境を意識して設定をする必要がある。
①anyenvやrbenvなどのenv系ユーティリティツールでrubyをインストール
②そのrubyでbundler gemをインストールし、そのbundlerで他gemをインストール
③anyenvなどのinit処理を~/.bashrcに記載

上記の場合、以下のpuma.serviceで上手く動いた。
binstubは不要だった。

# /usr/lib/systemd/system.puma.service
[Unit]
Description=Puma HTTP Server
After=network.target

[Service]
Type=simple
User=webapp
Group=webapp
WorkingDirectory=/var/www/blog
ExecStart=/bin/bash -lc "puma"
Restart=always

[Install]
WantedBy=multi-user.target

nginxの導入をしたのでこちらもsystemd経由で自動起動を設定する。
デプロイフローを作る時に忘れないように。

# Nginxのインストール
$ sudo amazon-linux-extras install -y nginx1

# Nginxの起動と自動起動の設定
$ sudo systemctl start nginx && sudo systemctl enable nginx

It's work!

スクリーンショット 2021-02-12 1.41.57

疲れたよー。
まだただの教務だけどこちらです。

その他

git configのpush.defaultを知った。便利。
systemdは概略をどこかで整理したい。
binstubもなんとなくしか理解していないのでどこかで整理したい。


次はデプロイフローの自動化周りをやっていく。
Capistrano…?いや、CodeDeployとかその辺を使うと勉強になりそう。

この記事が気に入ったらサポートをしてみませんか?