ガラシのパルプンテ頼み

地方産限界エンジニアのグローバル独り言

yarnが原因でdocker-compose upが実行できないときの対処法

現象

Rails開発環境を立ち上げる際に、docker-compose upコマンドを実行すると以下のエラーが出るようになった。

========================================
 Your Yarn packages are out of date!
 Please run `yarn install --check-files` to update.
========================================


To disable this check, please change `check_yarn_integrity`
to `false` in your webpacker config file (config/webpacker.yml).


yarn check v1.22.21
info Visit https://yarnpkg.com/en/docs/cli/check for documentation about this command.


Exiting

一時的な回避方法

エラーメッセージに記載されているように、プロジェクトの config/webpacker.yml ファイルを開き、development環境のcheck_yarn_integrity の値を false に設定します。 これにより、Yarnパッケージの整合性チェックを無効にすることができ、上記エラーを一時的に回避することが可能です。 今回は別件で緊急の修正タスクがあり、久々にDocker環境を立ち上げた際に上記のエラーが発生したため、修正タスクを優先しエラーの根本解決に関しては見送った形です。 設定ファイルにおいてデフォルトでtrueになっている設定をfalseに書き換えている時点で何となくきな臭さは感じていると思いますが、一時的な対応という部分を強調している理由は以下の通り。

check_yarn_integrityとは?

check_yarn_integrity は、RailsのWebpacker設定ファイル(config/webpacker.yml)にあるオプションです。このオプションが true に設定されている場合、Railsサーバーを起動する際に、 Yarnパッケージがプロジェクトの依存関係と整合しているかどうかをチェックします。これにより、開発中に依存関係の問題がある場合に早期に警告が出され、エラーの原因を特定しやすくなります。

check_yarn_integrityをfalseに設定する弊害

上述の通りcheck_yarn_integrity を false に設定すると、Yarnパッケージの整合性チェックが行われなくなります。 では具体的にどんな弊害をもたらすかというと

  1. 依存関係の不一致が見過ごされる: パッケージのバージョンがプロジェクトの要件と一致していない場合、その不一致が発見されにくくなります。これにより、予期せぬ動作やエラーが発生する可能性があります。

  2. デバッグの困難化: 依存関係に関する問題が発生した場合、問題の原因を特定するのがより困難になります。整合性チェックがないため、問題が依存関係に起因するかどうかを判断するのに追加の作業が必要になる可能性があります。

  3. 開発環境と本番環境の乖離: 本番環境では整合性チェックが行われないため、開発環境で問題が発生しなかった不一致が本番環境で問題を引き起こす可能性があります。

これらの理由から一般的には、check_yarn_integrity を true のままにしておくことが推奨されます。 これにより、依存関係の問題を早期に特定し、安定した開発環境を維持することができるためです。 ただし、冒頭で示したような特定の状況や開発フローによっては、このチェックを無効にすることもあります。

根本的な解決方法

正直各々の環境によって問題が異なるため、一貫した解決方法があるわけではありません。 以下の方法を試して一個ずつ問題を潰していく必要があります。

  1. Yarnパッケージの更新: ターミナルで yarn install --check-files コマンドを実行してください。これにより、プロジェクトに必要なパッケージが更新されます。

  2. Dockerコンテナの再ビルド: 変更を適用した後、docker-compose up --build コマンドを実行して、Dockerコンテナを再ビルドします。これにより、新しい依存関係がコンテナに適用されます。

  3. 依存関係の不一致や他の設定の問題: プロジェクトの package.json や yarn.lock ファイルを確認し、依存関係が正しく設定されていることを確認してください。

【JavaScript初心者向け】Promiseとresolveによる非同期処理について

Promiseとは?

JavaScriptで非同期処理を行う際に使われるオブジェクトです。非同期処理とは、すぐに結果が得られない処理のことを指します。例えば、Webサーバーからデータを取得する際や、一定時間後に何かを実行する場合などがこれにあたります。Promiseは、このような非同期処理が完了した後に何が起こるかを管理するために使われます。

Promiseには主に3つの状態があります:

  1. Pending(保留中):
    • 非同期処理がまだ完了していない状態です。
  2. Fulfilled(履行済み):
    • 非同期処理が成功し、完了した状態です。
  3. Rejected(拒否された):
    • 非同期処理が何らかの理由で失敗した状態です。

resolveとは?

resolvePromise内で使用される関数の一つで、Promiseを「Fulfilled(履行済み)」の状態に移行させます。つまり、非同期処理が成功したときにresolveを呼び出すことで、「この処理はうまくいった」と伝えることができます。

Promiseの基本的な使い方

Promiseを生成する基本的な構文は以下の通りです:

let promise = new Promise(function(resolve, reject) {
  // 非同期処理をここに書く

  // 成功した場合
  resolve(result);

  // 失敗した場合
  reject(error);
});

この例では、new Promiseを使って新しいPromiseを作成しています。Promiseのコンストラクタには関数が渡され、この関数はresolverejectの2つの引数を受け取ります。

  • resolve(result): 非同期処理が成功した場合に呼び出されます。resultは非同期処理の結果です。
  • reject(error): 非同期処理が失敗した場合に呼び出されます。errorはエラーの内容です。

Promiseの使用例

Webサーバーからデータを取得する簡単な例を考えてみましょう:

let dataFetching = new Promise(function(resolve, reject) {
  // データ取得の非同期処理
  fetch("https://example.com/data")
    .then(response => response.json())
    .then(data => resolve(data))  // データ取得成功
    .catch(error => reject(error));  // データ取得失敗
});

dataFetching.then(data => {
  console.log("取得したデータ:", data);
}).catch(error => {
  console.error("エラー発生:", error);
});

この例では、fetchを使ってWebサーバーからデータを取得し、成功した場合にはresolveでデータを返し、失敗した場合にはrejectでエラーを返しています。そして、dataFetchingthenメソッドでデータが取得できた場合の処理を、catchメソッドでエラーが発生した場合の処理を記述しています。

このように、Promiseresolveは非同期処理の結果を扱うための非常に便利な仕組みです。

dockerビルド時にGPGエラーが出た場合の対処法

現象

docker-compose build --no-cacheを実行した際に以下のようなエラーが発生した。

W: GPG error: http://security.debian.org/debian-security buster/updates InRelease: At least one invalid signature was encountered.

対応

  1. 未使用のイメージ、コンテナ、ネットワークを削除する docker system prune
  2. ビルド実行 docker-compose build --no-cache

上記で解消されない場合

  1. 未使用のボリュームを削除する docker system prune --volumes
  2. ビルド実行 docker-compose build --no-cache

原因

原因としては以下のようなものが考えられる。Docker関連なら大抵1が原因であることが多い。 が、文字数稼ぎのため一応ChatGPTへの壁打ちで返ってきた確認点も追記しておく。

  1. Dockerのディスクイメージサイズ使用量が100%になっている(大抵これ
  2. 無効なGPG署名: Debianのパッケージリポジトリから取得したデータのGPG署名(データの正当性を保証するための暗号化署名)が無効、または損傷している場合にこのエラーが発生します。
  3. 古いキャッシュ: ローカルのAPTキャッシュ(パッケージマネージャの一時データ)が古いか、破損していることが原因で、正しい署名を検証できない場合があります。
  4. リポジトリの一時的な問題: リポジトリ自体が一時的な問題(たとえば、サーバーの問題やメンテナンス)により、正しい署名を提供できていない可能性があります。
  5. ネットワークの問題: ネットワーク接続の問題やプロキシ、ファイアウォールの設定が原因で、リポジトリからのデータ取得が適切に行われなかった場合も考えられます。
  6. キーの期限切れ: 使用しているGPGキーが期限切れになっている場合、正しく署名を検証できなくなります。

そもそもGPGキーとはなにか

ChatGPT参照

GPGキー(GNU Privacy Guardキー)は、デジタルデータの暗号化とデジタル署名に使用される暗号化キーのペアです。これらのキーは、データの安全な送受信、データの完全性と認証の確保、およびソフトウェアパッケージの正当性の検証に利用されます。GPGキーは公開鍵暗号方式を採用しており、公開キーは他者と共有され、秘密キーは個人が秘密に保持します。このキーのペアを使用することで、安全なデジタルコミュニケーションとデータの保護が可能になります。

参考記事

note.yu9824.com

qiita.com

【GitHub Actions】CircleCIからGitHubActionsに乗り換えてRailsプロジェクトのCIを回す(RSpec・rubocop)

これまでCI/CDツールとしてはCircleCIを使っていましたが、昨今の潮流やコスト面での比較検討から弊社のプロジェクトでもGitHub Actionsへの乗り換えを実施しました。

今回はRailsのプロジェクトでGitHub ActionsによるCI/CDを適用する方法をまとめていきます。

本記事の対象読者としては以下の通りです。

  • 現状CircleCIを使っていてGitHub Actionsへの乗り換えを検討している
  • Rails製のプロダクトにGithub Actionsを適用して、RSpecとrubocopを自動で実行したい

なぜ乗り換えるのか

  • 同じことができるならほぼ無料で済むGitHub Actionsの方がコスト面でお得だから
  • GitHubでコード管理を行なっているから
  • CIの専門家がいるわけではない弊社チームにおいては、何でもできるCircleCIよりも最低限やりたいことを実現できるGithub Actionsのほうが取り回しがしやすい

CircleCIでのテスト内容

  1. Dockerイメージから環境をビルド
  2. コードのチェックアウト
  3. キャッシュからgemを復元
  4. gem install(キャッシュがあればAleady Update)
  5. gemをキャッシュに保存(キャッシュがなければ)
  6. Node.js と npm を更新(Dockerイメージに内包されているNodeバージョンがアプリのNodeのバージョンと異なるため)
  7. yarnライブラリをキャッシュから復元
  8. yarn install(キャッシュがあればAleady Update)
  9. yarnライブラリをキャッシュに保存(キャッシュがなければ)
  10. データベースをセットアップ
  11. rubocop実行
  12. RSpec実行
version: 2.1

# ビルド
jobs:
  build:
    docker:
      - image: circleci/ruby:3.0.0-node
        environment:
          RAILS_ENV: test
          POSTGRES_HOST: 127.0.0.1
      - image: circleci/postgres:11.5
        environment:
          POSTGRES_USER: app_user
          POSTGRES_DB: app_test
          POSTGRES_PASSWORD: password
          POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --locale=C"

    working_directory: ~/app_name
        
       # コードのチェックアウト
    steps:
      - checkout

      # キャッシュからgemを復元
      - restore_cache:
          keys:
            - gem-cache-v1-{{ checksum "Gemfile.lock" }}
            - gem-cache-v1-

      # gem install(キャッシュがあればAleady Update)
      - run:
          command: |
            gem install bundler
            bundle config set path 'vendor/bundle'
            bundle install --jobs=4 --retry=3

           # gemをキャッシュに保存
      - save_cache:
          paths:
            - ./vendor/bundle
          key: v1-dependencies-{{ checksum "Gemfile.lock" }}

      - run:
          name: "Node.js と npm を更新"
          command: |
            curl -sSL "https://nodejs.org/dist/v16.13.1/node-v16.13.1-linux-x64.tar.xz" | sudo tar --strip-components=2 -xJ -C /usr/local/bin/ node-v16.13.1-linux-x64/bin/node
            curl https://www.npmjs.com/install.sh | sudo bash

      # yarnライブラリをキャッシュから復元
      - restore_cache:
          keys:
            - yarn-packages-{{ checksum "yarn.lock" }}
            - yarn-packages-

      # yarn install(キャッシュがあればAleady Update)
      - run: yarn install

           # ライブラリをキャッシュに保存
      - save_cache:
          paths:
            - ~/.cache/yarn
          key: yarn-packages-{{ checksum "yarn.lock" }}

      # Database setup
      - run: bundle exec rails db:create
      - run: bundle exec rails db:migrate

      # Rubocop
      - run: bundle exec rubocop app
      # Rspec
      - run: bundle exec rspec

GitHub Actionsへの置き換え

1 .github/workflows/配下にワークフローを配置

GitHub Actionsを導入したいプロジェクトのリポジトリに移動したら、「Add file」から「Create new file」を選択して、ファイル作成画面に遷移します。

次にファイル作成画面で.github/workflowsディレクトリにYAMLファイルを配置します。

今回は「testing.yml」という名前でファイルを作成しました。

そのまま画面下までスクロールし、「Create new branch〜」のラジオボタンを選択して、新しく作成するブランチ名を入力。「Propose new file」を押下すると所定のディレクトリにtesting.ymlを配置したブランチが新たに作成されます。

作成後は自身のローカルマシンからたった今作成したブランチにチェックアウトしてワークフローファイルを編集していきます。

2 ワークフローファイルを編集する

GitHub Actionのワークフローとして書き換えたものが以下の通り。

コード内にコメントも付与していますが、以降これを題材としてGitHub Actionsで用いられる概念や用語簡単に説明していきます。

name: testing

on:
  # pushトリガーはmasterブランチへのpush時にのみ実行
  push:
    branches:
      - master
  # pull_requestはopen, synchronize, reopenのタイミングでの実行がデフォルト設定になっている
  # synchronizeはPRに変更があった場合という意味
  pull_request:

jobs:
  test:
    # ホストランナー(仮想マシン)のイメージを選択
    runs-on: ubuntu-latest
    timeout-minutes: 10
    # DB用のサービスコンテナを作成
    services:
      postgresql: # サービス名
        image: postgres:11.5 # DockerHubのイメージ参照
        ports: # 仮想マシン内で使用するポート番号
          - 5432:5432
        env: # 仮想マシン内でサービスから使用される環境変数を定義
          POSTGRES_USER: app_user
          POSTGRES_DB: app_test
          POSTGRES_PASSWORD: password
          POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --locale=C"

    # steps: コードのチェックアウトやRubyのインストールなど、特定の処理の単位
    steps:
      - name: Checkout code # ステップ名
        # uses: アクションを実行するキー。
        uses: actions/checkout@v3

      # GitHubの公式アクションとして「actions/setup-ruby」が存在するが最新バージョンの追随が遅いなどの理由からあまり使われていない模様
      # Railsのリポジトリを見ても「ruby/setup-ruby」を使用しているためこちらを採用
      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with: # アクションに与える引数を指定
          bundler-cache: true
          ruby-version: 3.0.0

      # withに「cache: yarn」を指定しても、ホストランナー上のnode_modulesをキャッシュしない
      # https://dev.classmethod.jp/articles/caching-dependencies-in-workflow-execution-on-github-actions/
      - name: Set up Node.js
        # v2ではNVMを使って複数バージョンを管理可能。単一のバージョンを指定する場合はv3を利用
        uses: actions/setup-node@v3
        with:
          node-version: 16.13.1

      # node関連の依存関係をキャッシュ
      - name: Cache node modules
        uses: actions/cache@v2
        with:
          path: node_modules # キャッシュ対象のディレクトリ
          key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }} # キャッシュ時のキー
          restore-keys: | # キャッシュの復元
            ${{ runner.os }}-node-

      - name: Bundler and gem install
        run: |
          gem install bundler
          bundle install --jobs 4 --retry 3 --path vendor/bundle

      - name: Yarn install
        run: yarn install

      - name: Database create and migrate
        run: |
          cp config/database.yml.ci config/database.yml
          bundle exec rails db:create RAILS_ENV=test
          bundle exec rails db:migrate RAILS_ENV=test

      - name: Run rubocop
        run: bundle exec rubocop app

      - name: Run rspec
        run: bundle exec rspec

3 config配下にdatabase.yml.ciを配置

database.yml.ciは、Railsアプリケーションのテスト環境で使用されるデータベース設定ファイルです。

通常、Railsアプリケーションはdatabase.ymlという名前のファイルを使用してデータベース接続情報を管理します。

ただし、CI/CDツールであるGitHub Actionsでは、通常のdatabase.ymlファイルではうまく動作しない場合があります。たとえば、CI/CD環境で使用するデータベースの接続情報が異なる場合があります。

そのため、database.yml.ciファイルを作成し、CI/CDツールで使用されるデータベース接続情報を定義することが推奨されています。

test:
  adapter: postgresql
  database: app_test
  username: app_user
  password: password
  host: localhost

GitHub Actions内で使用される基本概念、用語

イベント

冒頭のonキーでジョブの実行タイミングが制御している箇所。push、pull_request等が実行タイミングを決めるイベントキー。branchesはどのブランチにそれらが行われたらワークフローを実行するかを決めるキーです。

上述のコードでは「masterブランチにpushされた場合」「pull_requestがオープン・変更・再オープンされた場合」にワークフローを実行するよう指示しています。pull_requestイベントキーの初期値はオープン・変更・再オープン時となっていますが、typesキーでこれを変更することも可能です。

ワークフロー

GitHub Actionsでは、このファイル全体を指してワークフローという単位で数えます。

ワークフローは一つまたは複数のジョブから構成されます。

ジョブ

jobsキー配下に置かれている処理群が「ジョブ」

ジョブはその配下の一つまたは複数のステップから構成されます。

ステップ

ジョブを構成するアクションやrunに続くコマンドの集合を指します。

usesキーでアクションを、runキーでコマンドを実行します。

アクション

GitHub Actionsでは再利用製の高いコード(依存関係のキャッシュやツールチェーンのセットアップなど)を「アクション」として提供してくれています。

アクションとはGitHub、またはサードパーティ製のカスタムライブラリで、再利用製の高いコードを関数化したようなものです。

コマンド

ホストランナー上のOSで使用できるコマンドを指します。

平たく言えば普段ターミナル上で実行しているコマンド類と同様です。

ホストランナー

ワークフローが実行される仮想マシンのことです。

runs-onキーでGitHubが用意する所定のOSを指定して使用します。

まとめ

導入してみてメリットに感じたこと

  • 導入が簡単
    • 所定のディレクトリにymlを置くだけですぐに使えるのが楽
  • 当たり前だけどGitHubとの親和性が高い。
    • ワークフローの実行トリガーがイベント・ブランチに応じてかなり細かく指定できる
  • CIの所要時間が短縮された
    • これはspecのコード量や実行環境によりそうですが、弊社の環境では特に2回目以降のキャッシュ込みでの所要時間が2m程度は短縮されました

これから新たにプロジェクトをオープンし、コードのホスティングをGitHubで行う場合、GitHub Actionsを選択するのはごく自然な選択肢となりそうです。

【GitHub・SSH接続】WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!への対処法

ある日、Gitでリモートへのプッシュをかけた際にこんなエラーが発生しました。

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
SHA256:RGRZ/*********************************************.
Please contact your system administrator.
Add correct host key in /Users/XXXX/.ssh/known_hosts to get rid of this message.
Offending RSA key in /Users/XXXX/.ssh/known_hosts:2
RSA host key for [git.xxxxx.com]:XXXX has changed and you have requested strict checking.
Host key verification failed.
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.

数分前までは正常にGitコマンドが使用できていたところ、突然WARNINGなどと仰々しいプリントでエラーが出力されたのでビビり散らかしてしまいました。

今回はGitHubにSSHで接続しているユーザーが、稀にエンカウントするかもしれないタイトルのエラーについて、その原因と対処法をまとめました。

原因

GitHubはセキュリティ上の理由から、不定期でIPアドレスを変更することがあります。

これはGitHubがユーザーのリポジトリやコードなどの重要な情報を保護するために、様々なセキュリティ対策を講じているためです。

IPアドレスの変更は、主にDDoS攻撃などの攻撃からGitHubを保護するための一つの方法です。

IPアドレスを定期的に変更することにより、攻撃者が特定のIPアドレスに対して攻撃を仕掛けることを困難にし、攻撃の影響を軽減することができます。

また、GitHubはクラウドサービスプロバイダー(CSP)からサーバーを借りているおり、そのCSP側がIPアドレスの変更を実施することもあります。

CSP側のIPアドレス変更は、GitHub側から直接制御することができないため、そうした理由からも不定期なIPアドレスの変更につながる場合があります。

これらの前提を踏まえて、今回のエラーが発生した原因は何かというと、SSHで接続するリモートホストの接続先情報、つまりはGitHubのIPアドレスが変更されたことが原因でした。

過去にSSH接続を行った実績のあるリモートホストの接続先情報(公開鍵)はローカルマシンの~/.ssh/known_hosts に保存されています。

このknown_hostsファイルに保存されているGitHubのIPアドレスと、今接続しようとしているGitHubのIPアドレスとが食い違っているため、中間者攻撃ではありませんか??危険な接続先ではないですか??大丈夫ですか??システム管理者に確認して問題ないようであれば、/Users/XXXX/.ssh/known_hosts内の2行目の接続先に関する情報を見直してくださいねというような旨の警告を出してくれていたということです。

ChatGPT先生曰く

最近はググるよりもChatGPT先生に聞いた方が問題解決が早いので、脳死でエラー文をChatGPTにぶん投げてます。

今回も例に漏れず細かな原因を探る前に、大まかな問題や解決フローを探る意図でこんな感じの質問を投げてみました。

Gitでリモートリポジトリへのプッシュ操作を行った際に「WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!」
というエラーが発生しました。どのように対処すればいいですか?

余談ですが自分はAIチャットにも敬語で問いかけるタイプの人間。

ChatGPT先生から返ってきた返答は以下の通り。

このエラーメッセージは、SSH経由でリモートホストに接続したことがある場合に表示されます。
このエラーは、SSHで接続しようとするホストの公開鍵が以前と異なることを示しています。
これは、例えばリモートホストが更新された場合や、新しいホストに接続する場合に発生する可能性があります。
この問題を解決するには、以下の手順を実行してください。

対処法1(ChatGPT案)

そしてChatGPTが提案してくれた解決策がこちら。


  1. まず、警告メッセージに記載されているリモートホストのIPアドレスを確認します。
  2. 次に、リモートホストの公開鍵を削除します。これは、リモートホストに接続する前に行う必要があります。以下のコマンドを実行してください。

     ssh-keygen -R [リモートホストのIPアドレス]
    

    例えば、IPアドレスが「192.168.0.1」の場合は以下のようになります。

     ssh-keygen -R 192.168.0.1
    
  3. 再度接続を試みます。接続時にリモートホストの公開鍵を再び取得し、接続を許可するかどうかを確認するメッセージが表示されます。接続を許可する場合は、「yes」と入力してEnterキーを押します。

     ssh [ユーザー名]@[リモートホストのIPアドレス]
    
  4. 接続が成功したら、再度プッシュ操作を行ってください。

以上の手順を実行することで、SSH経由でリモートホストに接続してプッシュ操作を行うことができるようになるはずです。


このようにssh-keygen -R で指定したIPをキーに持つknowm_hostsファイル内の公開鍵を削除し、再度SSH接続を行うことで公開鍵が再登録されるまでの流れを出力してくれました。

ちなみに1の手順の「リモートホストのIPアドレス」は以下のコマンドで確認することが可能です。

$ sed -n '2p' ~/.ssh/known_hosts

これは第二引数で与えたファイルの第一引数で与えた行数を出力するコマンドで、2p(2行目)という数字がどこから出てきたかというと、冒頭のエラーメッセージの以下の箇所から参照した形です。

Offending RSA key in /Users/XXXX/.ssh/known_hosts:2

3の手順ではsshコマンドによる認証を行なったのちにプッシュ操作を〜と記載されていますが、sshコマンドの実行は省略可能です。

対処法2

今回は以下の方法で実際に解消まで漕ぎ着けました。やってることとしてはChatGPTが出力してくれた解決案を手動で実行しているに過ぎないので、詳細については割愛します。

  1. エラーメッセージに従い、~/.ssh/known_hostsの2行目を削除
vim ~/.ssh/known_hosts
  1. 展開されたknown_hostsの2行目にカーソルを移動して dd
  2. :wq で保存して終了
  3. 再度プッシュ操作を実行
  4. 以下のように対話式に接続の確認がとられるのでそれぞれにyes を入力
The authenticity of host 'github.com (xx.xx.xxx.xxx)' can't be established.
ECDSA key fingerprint is SHA256: xxxx
Are you sure you want to continue connecting 

(yes/no/[fingerprint])? yes

Warning: Permanently added 'github.com' (ECDSA) to the list of known hosts.
Warning: the ECDSA host key for 'github.com' differs from the key for the IP address ‘xx.xx.xxx.xxx'
Offending key for IP in /Users/xxxx/.ssh/known_hosts:10

Are you sure you want to continue connecting (yes/no)? yes

まとめ

  • GitHubはセキュリティ対策の一環として、不定期でIPアドレスの変更を行う
  • ローカルに保存されている接続先情報との不一致によりがWARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!が発生する
  • ~/.ssh/known_hosts のエラーメッセージに記載されている行(変更前の接続先情報)を削除し、再度SSH接続を行うことで、リモートホストの接続先情報が更新されてSSH接続が可能となる

【Figma】基本操作メモ

画面モックの作成やDTP関連の仕事でデザインツール「Figma」を使用する頻度が多くなってきたため、基本的な操作の自分用メモ

CSSの確認

右側のメニューペインから「inspect」タブを選択することで参照可能

円形を用いたチャートやローダーの作り方

  • 図形から円を作成
  • マウスオーバーして縁の内側の「Arc」をドラッグ(チャート)
  • Arcで円の形を決めた後に、円の中心の「Ratio」をドラッグ(ローダー)

図形とテキストを同時に拡大縮小する

  • ヘッダーのメニューペインから選択ツールをクリックして「Move」→「Scale」を選択する
  • オブジェクトをドラッグすると文字サイズも合わせて可変するようになる(Moveだと文字サイズは変わらない)

複数のオブジェクトをまとめる(フレーム)

  • 右側のメニューペインからClipContentにチェックを入れることでフレーム外に出たオブジェクトを非表示にできる
  • LayoutGridが使える(グリッドのガイド線を表示する)

平行四辺形を作る

  • 正方形を三つ作る
  • 正方形を選択してenterキーを押すと頂点編集モードに移行するため、上下または左右のnodeを二つ選択してドラッグ

カスタムシェイプを作る

  • node→ペンツールで繋げていく点のこと
  • paht→node同士を繋いだ線のこと
  • close path→全てのpathが繋がれて閉じているパス=面のこと。この状態になると背景色などを設定できる。
  • open path→線が終点まで至っていないパスのこと
  • vector network→結合された全てのパスが連動して動く機能

テキストをアウトライン化する

  • テキストを入力
  • ⌘ + / で検索ウインドウが開かれるので「outline」と入力
  • outline strokeを選択

画像を図形で切り抜く

  • 正方形(何らかの図形)を作成
  • ヘッダーメニューの中央三つのアイコンから「use as mask」をクリック
  • 図形がマスクに変換されるので、レイヤーパネルから切り抜きたい画像をマスクの上まで持っていく
  • 他の画像がマスクの影響を受けないように、マスクと対象の画像をグループ化しておく

塗りのブレンドモード

  • 画像を追加
  • 画像の上に図形を追加
  • 塗りを線状のグラデーションに指定
  • 右側のメニューペインの「Layer」から「Mlutiply」を選択
  • 背景画像に溶け込んど形の透過背景が設定されて、テキストを強調できる

よく使うスタイル(カラー・エフェクト)を登録する

  • 右側のメニューから「Fill」の横にある四つの点みたいなアイコンをクリック
  • +ボタンをクリックすると、nameが設定でき、現在指定されているカラーをスタイルとして登録できる
  • スタイル名を登録すルサ位に「〇〇 / 」と入力することでプレフィックスを指定できる。スタイルパネル内で同じプレフィックスを持つスタイル同士がグルーピングされる。

Constraints(制約)

  • 右のメニューペイン「Constraints」から各オブジェクトに対して上下左右への制約を指定できる
  • 制約を指定すると親オブジェクトのリサイズに対して、配置をホールドすることができる

【図解多め】HTML要素を自在に配置!CSSで上下・左右中央揃えする方法5選 | CSS入門

はじめに

CSSでの要素配置がうまくいかずに発狂した数はいざ知らず。こんにちは、地方産限界エンジニアのガラシです。

今回はフロントを触るタスクに着手している時に度々出くわしてはその都度不毛な検索を行なっている、HTML要素の中央揃えの方法について、図解とサンプル多めでまとめていきたいと思います。

この記事を読んでわかることは以下の通りです。

  • text-alignプロパティを使ってインライン要素を横中央揃えする方法がわかる
  • marginプロパティを使ってブロック要素を横中央揃えする方法がわかる
  • positionプロパティを使って要素を縦横中央揃えする方法がわかる
  • Flexboxを使って要素を縦横中央揃えする方法がわかる
  • CSSGridを使って要素を縦横中央揃えする方法がわかる

それでは早速やっていきましょう。

横中央揃え

text-alignプロパティを用いる方法(インライン要素)

以下のようにparentクラスを付与したdiv要素内に子要素としてspanタグが3つ配置されているHTMLがあります。

<div class="parent">
    <span class="child v1">child_1</span>
    <span class="child v2">child_2</span>
    <span class="child v3">child_3</span>
</div>

spanタグをはじめとするインライン要素を左右方向に配置する場合、CSSのtext-alignプロパティを親要素に指定することでこれを実現することができます。

属性値にrightを与えると右揃え、leftを与えると左揃え、centerを与えると中央揃えとなります。

.parent {
  background-color: #075985;
  width: 100%;
  height: 500px;
  // 配下のインライン要素を中央揃え
  text-align: center;
}

developer.mozilla.org

margin:0 auto;を用いる方法(ブロック要素)

次にブロック要素を左右方向にレイアウトする方法について。

シチュエーションとしては以下のように、parentクラスを付与したdiv要素内に、子要素としてchildクラスを付与したdiv要素が3つ配置されています。

<div class="parent">
    <div class="child v1">child_1</div>
    <div class="child v2">child_2</div>
    <div class="child v3">child_3</div>
</div>

divタグをはじめとするブロック要素を左右方向に対して配置する場合、各子要素に対してmargin: 0 auto; を指定することで実現することができます。

この際それぞれの子要素には横幅が指定されている必要があります。

.parent {
  background-color: #075985;
  width: 100%;
  height: 500px;
}

.child {
  // 横幅を指定
  width: 100px;
  height: 100px;
  // ブロック要素を中央揃え
  margin: 0 auto;
}

marginプロパティは与える属性値の数に応じて余白付与の対応が変化します。

以下はmarginプロパティに属性値を2つ〜4つ与えた場合のそれぞれの対応です。

.hoge {
  // 値が1つの場合は、上下左右が全て同じ値
  margin:8px; → margin: 上下左右;

  // 値が2つの場合は、上下と左右の値
  margin:10px 20px; → margin: 上下 左右;

  // 値が3つの場合は、上、左右、下、の値
  margin:10px 20px 30px; → margin: 上 左右 下;

  // 値が4つの場合は、上、右、下、左、の値
  margin:10px 20px 30px 40px; → margin: 上 右 下 左;
}

このためmargin: 0 auto;という指定は、上下に0px, 左右をauto(親要素の横幅に対して子要素の横幅100pxが中央に来るようよしなに)に配置するという意味合いとなります。

developer.mozilla.org

縦横中央揃え

positionプロパティを用いる方法

ここからは上下方向も含めた中央揃えの方法について見ていきます。まずはpositionプロパティとtransformプロパティを用いて要素を縦横中央揃えする方法から。

シチュエーションとしては、parentクラスを付与したdiv要素内に子要素としてchildクラスを付与したdiv要素が1つ配置したHTMLを例に行なっていきます。

<div class="parent">
    <div class="child">child</div>
</div>

まず親要素であるparentにposition: relative;を指定。次に子要素にposition: absolute; を指定し、top 50%, left 50%を指定します。

.parent {
  background-color: #075985;
  width: 100%;
  height: 500px;

  position: relative;
}

.child {
  background-color: #f29221;
  width: 100px;
  height: 100px;

  position: absolute;
  top: 50%;
  left: 50%;
}

この時点での要素の状態としてはこんな感じ。parentの左隅からみて、parentの上から50%, 左から50%の位置を始点に子要素を描画しています。

ここから更に子要素に対してtranslate -50%, -50% としてやることで子要素を親要素の中央に配置することができます。

.parent {
  background-color: #075985;
  width: 100%;
  height: 500px;
  position: relative;
}

.child {
  background-color: #f29221;
  width: 100px;
  height: 100px;

  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

tramslate関数はtransformプロパティ内で使用できる関数で、第一引数にX軸(横方向)、第二引数にY軸(縦方向)に対する移動値を指定できます。

上記のコードの場合、child要素それぞれの横幅の半分の幅分X軸とY軸方向にマイナス移動しています。

口頭だけだとわかりにくいのでそれぞれのプロパティと移動の対応についてガイドラインを引いたものが以下の通りです。

positionプロパティは属性値がたくさんあってややこしく感じがちですが、整理してみると然程難しくありませんし、場面や要素の種別を問わずに汎用的に配置を制御できるので覚えておくと何かと便利です。 このような配置方法も手札として持っておくことで、レイアウトのバリエーションも増えてくるものと思います。

CSSのpositionプロパティに関しては以下の動画でわかりやすく説明されているので、詳しく知りたい方はこちらもみてみるとより理解が深まるかもしれません。

youtu.be

developer.mozilla.org

developer.mozilla.org

Flexboxを用いる方法

次にFlexboxを用いて要素を縦横中央揃えしていく方法を見ていきます。 と言ってもここから先は正直あまり説明することがありません。というのもdisplayプロパティにflexgridを指定してあとはちょろちょろっと2、3行書き加えてあげればそれで中央揃えが完了してしまうからです。

FlexもGridもちゃんと説明しようとすると、軸方向に関する説明やそれに伴うプロパティの読み替えなどなど説明することは尽きないのですが、あくまでこの記事で取り扱うのは中央揃えを行う方法に関する部分のみなので、細かい説明はまた筆が乗った時の自分に任せます。

HTMLは先ほどと同じものを使用します。

<div class="parent">
    <div class="child">child</div>
</div>

CSS側で使用するコードは以下の3行のみ。これを親要素に指定して終了です。

display: flex;
justify-content: center;
align-items: center;
.parent {
  background-color: #075985;
  width: 100%;
  height: 500px;

  // Flexboxの使用を宣言
  display: flex;
  // 横方向に対して中央揃え
  justify-content: center;
  // 縦方向に対して中央揃え
  align-items: center;
}

.child {
  background-color: #f29221;
  width: 100px;
  height: 100px;
}

複数要素でも同様に縦横中央寄せが可能です。

<div class="parent">
    <div class="child v1">child_1</div>
    <div class="child v2">child_2</div>
    <div class="child v3">child_3</div>
</div>

.parent {
  background-color: #075985;
  width: 100%;
  height: 500px;

  display: flex;
  justify-content: center;
  align-items: center;
}

.child {
  background-color: #f29221;
  width: 100px;
  height: 100px;
}

.child.v1 {
  background-color: #f29221;
}
.child.v2 {
  background-color: #f87171;
}
.child.v3 {
  background-color: #e879f9;
}

なぜ子要素 (flexアイテム)が横並びなっているかについてですが、これは親要素(flexコンテナ)にdisplay: flex;を指定した際に、デフォルトでflex-direction: row;というプロパティが当たっているためです。

これはflexアイテムの並び方向を制御するプロパティで、rowは横並び、columnを指定すると縦並びにそれぞれ子要素の並び方向が変化します。このほかにもFlexboxには並び順や配置方法、要素間隔を制御する専用のプロパティがいくつもあるのですが、この場ではこれらの詳細な説明については割愛いたします。

気になる方は以下のドキュメントをご確認ください。

developer.mozilla.org

CSS Gridを用いる方法

最後にCSS Gridを用いて要素を縦横中央揃えする方法について確認していきます。

HTMLは先ほどと同じものを使用します。

<div class="parent">
    <div class="child">child</div>
</div>

.parent {
  background-color: #075985;
  width: 100%;
  height: 500px;

  display: grid;
  place-items: center;
}

終わりです。2行。

display: grid;
place-items: center;

親要素にたったこの2行を指定して終わり。圧倒的コスパ。流石に心許ないので補足で説明すると、まず1行目のdisplay: grid;はflex同様Gridの使用を宣言するものです。この親要素の配下でGridを使用しますという意味となります。

次にplace-itemsプロパティについて。こちらは本来2つの属性値を取るプロパティで、それぞれがFlexboxで言うところの'align-items'プロパティ(縦移動)とjustify-contentプロパティ(横移動)に対応しています。 ちなみにFlexboxとGridではtop, bottom, right, leftはそれぞれstart, endで表現されます。

place-items:  <align-items>, <justify-content>;

.parent {
  display: grid;

  // 縦:上寄せ、横:右寄せ
  place-items: start, end; 

  // 縦:中央寄せ、横:左寄せ
  place-items: center, start;

  // 縦:下寄せ、横:中央寄せ
  place-items: end, center;

  // 縦:中央寄せ、横:中央寄せ
  place-items: center, center;

  // 上記を省略した書き方
  place-items: center; 
}

developer.mozilla.org

まとめ

インライン要素を横中央揃えしたい

ラッパーの親要素に対して text-align: center; を指定

ブロック要素を横中央揃えしたい

各要素に横幅を指定した上で、margin: 0 auto;を指定

positionプロパティとtranslate関数で縦横中央寄せしたい

  1. 親要素にposition: relative;を指定
  2. 子要素にposition: absolute;を指定してtop, leftプロパティをそれぞれ50%にする
  3. 子要素にtranslete関数を指定して第一、第二引数にそれぞれ-50%を与える

Flexboxで縦横中央寄せしたい

親要素に以下を指定

.parent {
  display: flex;
  justify-content: center;
  align-items: center;
}

CSS Gridで縦横中央寄せしたい

親要素に以下を指定

.parent {
  display: grid;
  place-items: center; 
}