Circleciを使ってEC2へ自動デプロイ

完成したymlファイル(testは容量がかかるので、コメントアウトにしている)

version: 2
jobs:
  # test:
  #   machine:
  #     image: circleci/classic:edge
  #   steps:
  #     - checkout
  #     - run:
  #         name: docker-compose build
  #         command: docker-compose build
  #     - run:
  #         name: docker-compose up
  #         command: docker-compose up -d
  #     - run:
  #         name: sleep for waiting db
  #         command: sleep 120
  #     - run:
  #         name: rails db:create
  #         command: docker-compose run app bin/rails db:create
  #     - run:
  #         name: rails db:migrate (skip db:seed)
  #         command: docker-compose run app bin/rails db:migrate
  #     - run:
  #         name: rails db:test:prepare
  #         command: docker-compose run app bin/rails db:test:prepare
  #     - run:
  #         name: rails webpacker:install
  #         command: docker-compose run app bin/rails webpacker:install
  #     - run:
  #         name: rspec
  #         command: docker-compose run app rspec
  #     - run:
  #         name: docker-compose down
  #         command: docker-compose down
  # deploy ジョブ: EC2 に SSH 接続して、デプロイを実行する
  deploy:
    machine:
      image: circleci/classic:edge
    steps:
      - checkout
      # CircleCIに登録した秘密鍵を呼び出す。
      - add_ssh_keys:
          fingerprints: #sshの暗号化されたもの。
            - 19:a4:94:21:15:c9:5c:c6:75:8a:94:4a:9c:1f:37:da
      - run: ssh ${USER_NAME}@${HOST_NAME} 'cd myapp && git pull'
    #   - run: ssh ${USER_NAME}@${HOST_NAME} 'cd myapp && git pull && docker-compose run python ./manage.py migrate'
workflows:
  version: 2
  test_and_deploy:
    jobs:
      # - test
      # requiresなどが必要ない時は、:はいらない。今はdeployのみを行っているので、
      # - deploy:
      - deploy
        # requires:
        #   - test
          filters:
                    branches:
                        only: main

一番時間がかかったところはいつもssh周り

  • EC2とGHを、EC2で作成したpem形式のkeyでssh接続する。その鍵をcircleciのsshにも登録する。 

f:id:kaz08:20210329174252j:plain

その他に、

  • circleci>project>環境変数(Environment Variables)に、HOST_NAME, USER_NAMEにそれぞれipアドレス、ec2-user名を記入して、上の.ymlに格納している。

  • また、circleci>project>set sshで、deploy key, user keyもセットしておく。
    参考:

circleci.com

qiita.com

suwaru.tokyo

ssh connect port 22: Operation timed outでsshログインができなかったときの対処法

結論

ec2のセキュリティグループでもう一度マイipを選択し直す。

なぜ

port22に入るipが変わっている可能性があるから。家には複数のwifiがあり、たまに切り替わる。そこでipが変わってしまったから、ファイアーウォールが入れてくれなかったんだと思う。
ってことは、定期的に起こるエラーなので注意。

参考:

qiita.com

RailsにJSを書く前に、yarn, npm, webpack, webpacker, ES6を理解する。

  • npmを便利にしたものが、yarn

  • JSは、ES5からES6へ。クラスやアロー関数などが使えるようになった。(babelで変換可)

  • 上記のファイルの依存関係等をいい感じにまとめてくれるのが、webpackで、Railsにフィットさせるためのwebpackerというのがある。

npm

JavaScript(正確にはNode.jsモジュール)のパッケージマネージャです。言ってみれば、JavaScript世界におけるRubygemです。

npm = rubyでいうgem

npm install bootstrap

npmは、ダウンロードしたパッケージを./node_modulesに保存し、パッケージのリストを./package.jsonに保存します

yarn

npmよりずっと高速です。

npmより新しいパッケージマネージャです。yarnはnpmのリポジトリからパッケージを取得する点は同じ

ES6

クラス、アロー関数などでJSが書けるようになった

Babel

全てのブラウザでES6が動くわけではないので、EC5に変換するためのファイル。

Webpack

yarn, npm es5,es6などの依存関係を綺麗にまとめるもの。

webpacker

RailsアプリケーションにWebpackをいい感じに取り込めるgem

ルール

  • application.jsは、app/javascript/packs配下に置かれる。

  • viewにjsをincludeするには、

view
<%= javascript_pack_tag 'pages/index' %>

↓

app/javascript/packs/index.js
//ここにjsを書く。

参考;

https://techracho.bpsinc.jp/hachi8833/2020_01_16/85940

Rails 6: Webpacker+Yarn+Sprocketsを十分理解してJavaScriptを書く: 後編(翻訳)|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社

webpack

Webpackerを使ったRailsでのJavaScript開発 - クックパッド開発者ブログ

webpack学習の基本のき

Mysql2::Error: Table 'myapp_development.post_tags' doesn't exist のエラー解決

背景

postを削除しようとしたら、このエラーが起こった。

解決のプロセス

mysqlのテーブルを見てみる

mysql> use myapp_development
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+-----------------------------+
| Tables_in_myapp_development |
+-----------------------------+
| ar_internal_metadata        |
| comments                    |
| impressions                 |
| likes                       |
| posts                       |
| posts_tags                  |
| relationships               |
| schema_migrations           |
| tags                        |
| users                       |
+-----------------------------+
10 rows in set (0.01 sec)

mysql>

schembaを見てみる

create_table "posts_tags", id: false, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
    t.bigint "post_id", null: false
    t.bigint "tag_id", null: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["post_id"], name: "index_posts_tags_on_post_id"
    t.index ["tag_id"], name: "index_posts_tags_on_tag_id"
  end

post_tagsを削除しようとしているのはなぜ?

これが原因だった。

post.rb
has_many :post_tags, dependent: :destroy

以前、タグを新しいテーブルを作成し、改良したときに、古いテーブルを消し忘れていた事が原因だった。

mysql8.0のエラー Plugin caching_sha2_password could not be loaded: /usr/lib/x86_64-linux-gnu/mariadb19/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory

MySQL5.7までの認証プラグインには mysql_native_password がデフォルトで使用されていましたが、MySQL8.0より新たに追加された caching_sha2_password

プラグインがもともとコードに書かれていたのに無いと言うことは、migrateとかをすればいいと思う。

http://blog.s-style.co.jp/2018/05/1807/

・新規dockerfileに以下を追加する

FROM ruby:2.6

WORKDIR /tmp
RUN apt update && apt install -y lsb-release \ 
    && apt remove -y libmariadb-dev-compat libmariadb-dev

RUN wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-common_8.0.18-1debian10_amd64.deb \
    https://dev.mysql.com/get/Downloads/MySQL-8.0/libmysqlclient21_8.0.18-1debian10_amd64.deb \
    https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-community-client-core_8.0.18-1debian10_amd64.deb \
    https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-community-client_8.0.18-1debian10_amd64.deb \
    https://dev.mysql.com/get/Downloads/MySQL-8.0/libmysqlclient-dev_8.0.18-1debian10_amd64.deb

RUN dpkg -i mysql-common_8.0.18-1debian10_amd64.deb \
    libmysqlclient21_8.0.18-1debian10_amd64.deb \
    mysql-community-client-core_8.0.18-1debian10_amd64.deb \
    mysql-community-client_8.0.18-1debian10_amd64.deb \
    libmysqlclient-dev_8.0.18-1debian10_amd64.deb

nginxをdockerから起動したら、エラーが消えた。

参考

taker.hatenablog.com

github.com

Pumaについて

bindle exec puma -d

指定する場合

bundle exec puma -C config/puma.rb

pumaはサーバのソケットを開いたままリスタートできます。要するに、ユーザーに対してサーバを開放したままサーバのリスタートができるということです。ユーザーを待たせることがないため、pumaを速くすることに貢献しています。

hot resrartと呼ばれるやつ

停止

kill -SIGUSR2 `(cat tmp/pids/server.pid)`

or

bundle exec pumactl restart

https://arma-search.jp/article/ruby-puma#i-2

ソケットとは?

pumaの設定

threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
threads threads_count, threads_count
port        ENV.fetch("PORT") { 3000 }
environment ENV.fetch("RAILS_ENV") { "development" }
plugin :tmp_restart

app_root = File.expand_path("../..", __FILE__)
#{myapp_root}/tmp/sockets/puma.sock に bind している
bind "unix://#{myapp_root}/tmp/sockets/puma.sock"

「environment」

pumaをどの環境で動作させるかを指定します。デフォルトは'development'になっています。

「daemonize」

rackサーバーをデーモンにして起動するかどうか

pidfile」

pidファイルを配置するパスを指定します。 tmp/pids/puma.pidに配置するほうが良いと思います。

state_path」 サーバー情報を記載したstateファイルを配置するパスを指定します。 stateファイルはpumactlコマンドでサーバーを操作するのに使用します。 railsの場合、特別このようなファイルを配置するディレクトリはないので今回はtmp/pids/以下に配置

「Cluster mode」

クラスタモードとは複数のワーカープロセスを起動し、そのプロセスそれぞれでスレッドプールを持ちリクエストを処理する仕組みです。 ワーカープロセスの数は以下のように指定します。 Workerの数をマシンが持つCore数を超えないように気をつけて下さい。

「Thread Pool」 Pumaはスレッドによってリクエストを処理します。スレッドをスレッドプールに貯めておく数の下限から上限を指定することが出来ます。

「bind」 サーバーをどのように接続するかをURIで指定。シンプルにTCPで接続する場合tcp://0.0.0.0:80、またWebサーバーの前段にnginxをなどを置き、そこからUNIX Socket経由で接続する場合はunix:///var/run/puma.sockのように指定します。 f:id:kaz08:20210301104547p:plain

なんでNginxを使うのか、高速化と処理の負担を分散させる。

Nginx: 静的,画像を処理

↓↑UNIXドメインソケット(unix://の意味はこれか。)

Pumaは動的なファイルの処理に集中できる


スタートしてみた

# bundle exec puma
Puma starting in single mode...
* Puma version: 5.1.1 (ruby 2.6.6-p146) ("At Your Service")
*  Min threads: 5
*  Max threads: 5
*  Environment: development
*          PID: 36

ハンズオン

nginxとpumaの設定、連携が書かれていてわかりやすい。

Mac1台にnginxでWebサーバとPumaでアプリサーバを立てる