<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	
	xmlns:georss="http://www.georss.org/georss"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	>

<channel>
	<title>GCP | みんたく</title>
	<atom:link href="https://mintaku-blog.net/category/develop/gcp/feed/" rel="self" type="application/rss+xml" />
	<link>https://mintaku-blog.net</link>
	<description>みんたくの技術ブログ</description>
	<lastBuildDate>Thu, 28 Mar 2024 17:28:15 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.0.11</generator>

<image>
	<url>https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2018/06/cropped-ipad-820272_640.jpg?fit=32%2C32&#038;ssl=1</url>
	<title>GCP | みんたく</title>
	<link>https://mintaku-blog.net</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">144480658</site>	<item>
		<title>Cloud BuildにRSpecを組み込んでCI/CDパイプラインを構築する</title>
		<link>https://mintaku-blog.net/cloudbuild-rspec/</link>
					<comments>https://mintaku-blog.net/cloudbuild-rspec/#respond</comments>
		
		<dc:creator><![CDATA[みんたく]]></dc:creator>
		<pubDate>Sat, 05 Dec 2020 03:16:32 +0000</pubDate>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[GCP]]></category>
		<guid isPermaLink="false">https://mintaku-blog.net/?p=1755</guid>

					<description><![CDATA[<p>RailsにRSpecを導入して、Cloud BuildでCI/CDパイプラインを構築するところまでをまとめています。 RailsにRSpecを導入する ま …</p>
The post <a href="https://mintaku-blog.net/cloudbuild-rspec/">Cloud BuildにRSpecを組み込んでCI/CDパイプラインを構築する</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></description>
										<content:encoded><![CDATA[<p>RailsにRSpecを導入して、Cloud BuildでCI/CDパイプラインを構築するところまでをまとめています。</p>
<h2>RailsにRSpecを導入する</h2>
<p>まずはRailsにRSpecを導入します。</p>
<p>実際にローカル環境でRSpecによるテストができるところまでの手順をまとめています。</p>
<h3>「rspec-rails」、「factory_bot_rails」、「rails-controller-testing」のインストール</h3>
<p>Gemfileを以下の3つのGemを追加しbundle installします。</p>
<p>・Gemfile</p><pre class="crayon-plain-tag">group :development, :test do
  gem 'rspec-rails'
  gem 'factory_bot_rails'
  gem 'rails-controller-testing'
end</pre><p></p>
<h3>RSpecに必要なファイルを生成する</h3>
<p>以下のコマンドでRSpecに必要なファイルを生成します。</p><pre class="crayon-plain-tag">$ bundle exec rails generate rspec:install</pre><p>&nbsp;</p>
<p>成功すると以下の3つのファイルが生成されていることが確認できます。</p><pre class="crayon-plain-tag">.rspec
spec/spec_helper.rb
spec/rails_helper.rb</pre><p></p>
<h3>RSpec実行に必要な設定をする</h3>
<p>Factory Botの設定をrails_helper.rbに追加します。</p>
<p>・spec/rails_helper.rb</p><pre class="crayon-plain-tag">RSpec.configure do |config|

  ...

  config.include FactoryBot::Syntax::Methods
end</pre><p>&nbsp;</p>
<p>Rails.loggerのログを出力するには以下を追加します。</p><pre class="crayon-plain-tag">Rails.logger = Logger.new(STDOUT)</pre><p>&nbsp;</p>
<p>rspec用のテストファイルを作成するために、application.rbに以下を追加します。</p>
<p>・application.rb</p><pre class="crayon-plain-tag">config.generators do |g|

...

  g.test_framework :rspec,
                   fixtures: true,
                   view_specs: false,
                   helper_specs: false,
                   routing_specs: false,
                   controller_specs: true,
                   request_specs: false
  g.fixture_replacement :factory_bot, dir: "spec/factories"
end</pre><p>&nbsp;</p>
<p>.rspecに以下を追加するとテストの実行結果が見やすくなります。</p>
<p>・.rspec</p><pre class="crayon-plain-tag">--format documentation</pre><p>&nbsp;</p>
<h3>テストを作成する</h3>
<p>factoriesやcontrollerを用意し、テストを作成していきます。</p>
<p>今回はテスト作成の過程は省略します。詳しくは以下の記事などを参考にしてください。</p>

<div class="ys-blog-card">
	<div class="ys-blog-card__container">
					<figure class="ys-blog-card__image">
				<img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn.qiita.com%252Fassets%252Fpublic%252Farticle-ogp-background-afbab5eb44e0b055cce1258705637a91.png%3Fixlib%3Drb-4.0.0%26w%3D1200%26blend64%3DaHR0cHM6Ly9xaWl0YS11c2VyLXByb2ZpbGUtaW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnFpaXRhLWltYWdlLXN0b3JlLnMzLmFwLW5vcnRoZWFzdC0xLmFtYXpvbmF3cy5jb20lMkYwJTJGMjU4MjE5JTJGcHJvZmlsZS1pbWFnZXMlMkYxNjgwNTY3NTg2P2l4bGliPXJiLTQuMC4wJmFyPTElM0ExJmZpdD1jcm9wJm1hc2s9ZWxsaXBzZSZiZz1GRkZGRkYmZm09cG5nMzImcz02MjM5ZWY2ZGQzYzY5NTE1NzFjYTNhZTAxODA2YTUwNQ%26blend-x%3D120%26blend-y%3D467%26blend-w%3D82%26blend-h%3D82%26blend-mode%3Dnormal%26s%3D8a3ae59c828745ab802ed15fe5247ba2?ixlib=rb-4.0.0&amp;w=1200&amp;fm=jpg&amp;mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTk2MCZoPTMyNCZ0eHQ9JUUzJTgwJTkwUmFpbHMlRTMlODAlOTElRTUlOUYlQkElRTYlOUMlQUMlRTclOUElODQlRTMlODElQUFBUEklRTMlODMlODYlRTMlODIlQjklRTMlODMlODglRTMlODElQUUlRTYlOUIlQjglRTMlODElOEQlRTYlOTYlQjkmdHh0LWFsaWduPWxlZnQlMkN0b3AmdHh0LWNvbG9yPSUyMzFFMjEyMSZ0eHQtZm9udD1IaXJhZ2lubyUyMFNhbnMlMjBXNiZ0eHQtc2l6ZT01NiZ0eHQtcGFkPTAmcz1mNzU3NTdiMDNhYTFkMGNmZTQ4MTI0M2VlYTc3YjBkOQ&amp;mark-x=120&amp;mark-y=112&amp;blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTgzOCZoPTU4JnR4dD0lNDBrLXBlbmd1aW4tc2F0byZ0eHQtY29sb3I9JTIzMUUyMTIxJnR4dC1mb250PUhpcmFnaW5vJTIwU2FucyUyMFc2JnR4dC1zaXplPTM2JnR4dC1wYWQ9MCZzPWRjYmQ1YjU1Y2EzYTU3MzI4NzI0NzQ1NTdiZjU2NzJk&amp;blend-x=242&amp;blend-y=480&amp;blend-w=838&amp;blend-h=46&amp;blend-fit=crop&amp;blend-crop=left%2Cbottom&amp;blend-mode=normal&amp;s=61d27baeec9f515f64f141cd85d98a8f" alt="">			</figure>
				<div class="ys-blog-card__text">
			<p class="ys-blog-card__title">
				<a class="ys-blog-card__link" href="https://qiita.com/k-penguin-sato/items/defdb828bd54729272ad">【Rails】基本的なAPIテストの書き方 #RSpec - Qiita</a>
			</p>
							<div class="ys-blog-card__dscr">
					概要 Railsで作成されたAPIのテストについてこちらを参考に必要最低限の情報&hellip;				</div>
										<div class="ys-blog-card__domain">qiita.com</div>
					</div>
	</div>
</div>

<p>例として本のデータを取得するAPIの本コントローラのshowメソッドに対してテストを行います。</p>
<p>・spec/factories/books.rb</p><pre class="crayon-plain-tag">FactoryBot.define do
  factory :book do
    name {'テスト本'}
  end
end</pre><p>&nbsp;</p>
<p>・spec/controllers/books_controller_spec.rb</p><pre class="crayon-plain-tag">describe Api::BooksController, type: :controller do
  context '/api/books' do
    describe 'GET #show' do
      render_views

      before do
        @book = create(:book)
        get :show, params: { id: @book.id }
        @json = JSON.parse(response.body)
      end

      it '200チェック' do
        expect(response).to be_success
        expect(response.status).to eq 200
      end

      it '本データチェック' do
        expect(@json[name]).to eq(@book.name)
      end

    end
  end
end</pre><p>&nbsp;</p>
<p>ローカルでテストが実行できるか確認します。</p><pre class="crayon-plain-tag">$ docker-compose exec web bundle exec rspec</pre><p>&nbsp;</p>
<p>正常にテストが成功すると以下のようなログが出力されます。</p><pre class="crayon-plain-tag">Finished in 0.58604 seconds (files took 4.32 seconds to load)
2 examples, 0 failures</pre><p>&nbsp;</p>
<h2>Cloud BuildでRSpecを組み込む</h2>
<p>ローカルでのRSpecによるテストが確認できたら、Cloud BuildにRSpecを組み込んでCI/CDパイプラインを構築していきます。</p>
<h3>Dockerfileの作成</h3>
<p>Rubyの公式イメージを元に作成しています。</p>
<p>テストする際のDBの接続先はMariaDBを使用します。</p>
<p>・Dockerfile</p><pre class="crayon-plain-tag">FROM ruby:2.5.8-alpine3.11

RUN set -ex \
  &amp;&amp; apk update \
  &amp;&amp; apk upgrade \
  &amp;&amp; apk add --no-cache \
    build-base \
    bash \
    curl \
    nodejs \
    tzdata \
    mariadb \
    mariadb-client \
    mariadb-dev \
    openrc \
    libc6-compat \
    gcompat \
  &amp;&amp; mkdir -p /run/openrc \
  &amp;&amp; touch /run/openrc/softlevel \
  &amp;&amp; rc-status \
  &amp;&amp; /etc/init.d/mariadb setup \
  &amp;&amp; gem install bundler

RUN mkdir /app_name
ENV APP_ROOT /app_name
WORKDIR $APP_ROOT

ADD ./Gemfile $APP_ROOT/Gemfile
ADD ./Gemfile.lock $APP_ROOT/Gemfile.lock

RUN bundle install
ADD . $APP_ROOT</pre><p></p>
<h3>テスト用のDB設定</h3>
<p>database.ymlに以下のようにテスト用のDBを設定します。</p>
<p>・database.yml</p><pre class="crayon-plain-tag">test:
  adapter: mysql2
  encoding: utf8
  reconnect: false
  pool: 5
  username: root
  password: password
  database: test_db</pre><p></p>
<h3>テスト実行用のシェルスクリプト作成</h3>
<p>Cloud Buildで実行するシェルスクリプトを作成します。</p>
<p>MariaDBを起動して、DBを作成しテストを実行できる環境を整えます。その後、テストを実行します。</p>
<p>・rspec.sh</p><pre class="crayon-plain-tag">#!/bin/bash

# MariaDBの起動
rc-service mariadb start

# テスト用DB作成・マイグレーション
RAILS_ENV=test rails db:create db:migrate

# RSpecテスト実行
RAILS_ENV=test bundle exec rspec</pre><p>&nbsp;</p>
<p>Dockerイメージを作成し、RSpecのテストを行いGAEにデプロイする</p>
<p>cloudbuild-staging.yamlのスクリプトでDockerイメージの作成、RSpecのテスト、GAEのステージング環境にデプロイを行います。いわゆるCI/CDパイプラインを構築して、実行しています。</p>
<p>Gitでプッシュするとcloudbuild.yamlのスクリプトが自動で実行されるようにしています。</p>
<p>Cloud BuildとGitの連携方法に関してはここでは省略しています。</p>
<p>・cloudbuild-staging.yaml</p><pre class="crayon-plain-tag">steps:
- name: 'alpine'
  args: ['echo', '${_ENVIRONMENT}']
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'gcr.io/$PROJECT_ID/cloud-build-rspec', '.']
- name: 'gcr.io/$PROJECT_ID/cloud-build-rspec'
  args: ['/bin/bash', 'rspec.sh']
- name: 'gcr.io/cloud-builders/gcloud'
  args: ['app', 'deploy', 'app-staging.yaml']</pre><p></p>
<h2>Cloud BuildでRSpecによる自動テストの動作確認</h2>
<h3>テスト失敗時</h3>
<p><img data-attachment-id="1758" data-permalink="https://mintaku-blog.net/cloudbuild-rspec/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2020-12-04-11-47-03/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/12/66bc48dce88fffeb13e8b9e7468914af.png?fit=642%2C568&amp;ssl=1" data-orig-size="642,568" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="スクリーンショット 2020-12-04 11.47.03" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/12/66bc48dce88fffeb13e8b9e7468914af.png?fit=300%2C265&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/12/66bc48dce88fffeb13e8b9e7468914af.png?fit=642%2C568&amp;ssl=1" loading="lazy" class="aligncenter size-full wp-image-1758" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/12/66bc48dce88fffeb13e8b9e7468914af.png?resize=642%2C568&#038;ssl=1" alt="" width="642" height="568" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/12/66bc48dce88fffeb13e8b9e7468914af.png?w=642&amp;ssl=1 642w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/12/66bc48dce88fffeb13e8b9e7468914af.png?resize=300%2C265&amp;ssl=1 300w" sizes="(max-width: 642px) 100vw, 642px" data-recalc-dims="1" /></p>
<p>テスト失敗した際の挙動を確認します。</p>
<p>テストが失敗するとCloud Buildのステップが停止し、デプロイされることはありません。</p>
<p>&nbsp;</p>
<h3>テスト成功時</h3>
<p><img data-attachment-id="1757" data-permalink="https://mintaku-blog.net/cloudbuild-rspec/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2020-12-04-11-44-46/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/12/8598053bbfd3757798c574887266d953.png?fit=646%2C570&amp;ssl=1" data-orig-size="646,570" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="スクリーンショット 2020-12-04 11.44.46" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/12/8598053bbfd3757798c574887266d953.png?fit=300%2C265&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/12/8598053bbfd3757798c574887266d953.png?fit=646%2C570&amp;ssl=1" loading="lazy" class="aligncenter size-full wp-image-1757" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/12/8598053bbfd3757798c574887266d953.png?resize=646%2C570&#038;ssl=1" alt="" width="646" height="570" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/12/8598053bbfd3757798c574887266d953.png?w=646&amp;ssl=1 646w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/12/8598053bbfd3757798c574887266d953.png?resize=300%2C265&amp;ssl=1 300w" sizes="(max-width: 646px) 100vw, 646px" data-recalc-dims="1" /></p>
<p>テスト成功時の挙動を確認します。</p>
<p>テストが成功すると、そのままGAEへのデプロイが始まり、無事完了しました。</p>
<p>参考<br />

<div class="ys-blog-card">
	<div class="ys-blog-card__container">
					<figure class="ys-blog-card__image">
				<img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn.qiita.com%252Fassets%252Fpublic%252Farticle-ogp-background-afbab5eb44e0b055cce1258705637a91.png%3Fixlib%3Drb-4.0.0%26w%3D1200%26blend64%3DaHR0cHM6Ly9xaWl0YS11c2VyLXByb2ZpbGUtaW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnFpaXRhLWltYWdlLXN0b3JlLnMzLmFtYXpvbmF3cy5jb20lMkYwJTJGOTI0NDMlMkZwcm9maWxlLWltYWdlcyUyRjE1MTUzMDE0MzA_aXhsaWI9cmItNC4wLjAmYXI9MSUzQTEmZml0PWNyb3AmbWFzaz1lbGxpcHNlJmJnPUZGRkZGRiZmbT1wbmczMiZzPTMxYTUxOTYwMDQ5NmZkODIxYzRmYWRkNjg0OWEzYjdh%26blend-x%3D120%26blend-y%3D467%26blend-w%3D82%26blend-h%3D82%26blend-mode%3Dnormal%26s%3D629b82b84ed85c57d016578c4f910980?ixlib=rb-4.0.0&amp;w=1200&amp;fm=jpg&amp;mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTk2MCZoPTMyNCZ0eHQ9UmFpbHM1JUUzJTgxJUI4JUUzJTgxJUFFUnNwZWMlRTUlQjAlOEUlRTUlODUlQTUlRTMlODElOEIlRTMlODIlODklRTUlQUUlOUYlRTglQTElOEMlRTclQTIlQkElRTglQUElOEQlRTMlODElQkUlRTMlODElQTcmdHh0LWFsaWduPWxlZnQlMkN0b3AmdHh0LWNvbG9yPSUyMzFFMjEyMSZ0eHQtZm9udD1IaXJhZ2lubyUyMFNhbnMlMjBXNiZ0eHQtc2l6ZT01NiZ0eHQtcGFkPTAmcz0yYjIyZDUxZGZiODMxMjNiNzQ5YTdhYzNlYmRmMjc2YQ&amp;mark-x=120&amp;mark-y=112&amp;blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTgzOCZoPTU4JnR4dD0lNDByeW91emkmdHh0LWNvbG9yPSUyMzFFMjEyMSZ0eHQtZm9udD1IaXJhZ2lubyUyMFNhbnMlMjBXNiZ0eHQtc2l6ZT0zNiZ0eHQtcGFkPTAmcz05MzQ4MjVlNTA0ZjFjZmQ3YzVhODdiYTAwYTU1MzgwOQ&amp;blend-x=242&amp;blend-y=480&amp;blend-w=838&amp;blend-h=46&amp;blend-fit=crop&amp;blend-crop=left%2Cbottom&amp;blend-mode=normal&amp;s=8b94ca1a5b685ea586f15bb1cbf49af9" alt="">			</figure>
				<div class="ys-blog-card__text">
			<p class="ys-blog-card__title">
				<a class="ys-blog-card__link" href="https://qiita.com/ryouzi/items/de7336e6175530723b30">Rails5へのRspec導入から実行確認まで #Ruby - Qiita</a>
			</p>
							<div class="ys-blog-card__dscr">
					株式会社TECH LUCKという会社で代表兼エンジニアをしている齊藤です。 DX&hellip;				</div>
										<div class="ys-blog-card__domain">qiita.com</div>
					</div>
	</div>
</div>
</p>

<div class="ys-blog-card">
	<div class="ys-blog-card__container">
					<figure class="ys-blog-card__image">
				<img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn.qiita.com%252Fassets%252Fpublic%252Farticle-ogp-background-afbab5eb44e0b055cce1258705637a91.png%3Fixlib%3Drb-4.0.0%26w%3D1200%26blend64%3DaHR0cHM6Ly9xaWl0YS11c2VyLXByb2ZpbGUtaW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnFpaXRhLWltYWdlLXN0b3JlLnMzLmFtYXpvbmF3cy5jb20lMkYwJTJGOTIzNTklMkZwcm9maWxlLWltYWdlcyUyRjE1MTU0MDEwNTc_aXhsaWI9cmItNC4wLjAmYXI9MSUzQTEmZml0PWNyb3AmbWFzaz1lbGxpcHNlJmJnPUZGRkZGRiZmbT1wbmczMiZzPWJkMDA4YjE0MTgyNTBiZDZkYTI2MmIyMWU5Y2RiMWU1%26blend-x%3D120%26blend-y%3D462%26blend-w%3D90%26blend-h%3D90%26blend-mode%3Dnormal%26mark64%3DaHR0cHM6Ly9xaWl0YS1vcmdhbml6YXRpb24taW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnMzLWFwLW5vcnRoZWFzdC0xLmFtYXpvbmF3cy5jb20lMkZxaWl0YS1vcmdhbml6YXRpb24taW1hZ2UlMkZiYjVjYzY5OWQzYTk1Y2NiOGQwMDYyNGY1ZDY5YjczNjE1ZTIxZWI4JTJGb3JpZ2luYWwuanBnJTNGMTUxMTE0NDk2OD9peGxpYj1yYi00LjAuMCZ3PTQ0Jmg9NDQmZml0PWNyb3AmbWFzaz1jb3JuZXJzJmNvcm5lci1yYWRpdXM9OCZiZz1GRkZGRkYmYm9yZGVyPTIlMkNGRkZGRkYmZm09cG5nMzImcz1hMzNiNDc5NTlkOTk3ZDg1ZmRkNGJjNmJlOGNhZDA0Yw%26mark-x%3D186%26mark-y%3D515%26mark-w%3D40%26mark-h%3D40%26s%3Dbd5952a35f6da25c79b93e05a964eb9f?ixlib=rb-4.0.0&amp;w=1200&amp;fm=jpg&amp;mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTk2MCZoPTMyNCZ0eHQ9R29vZ2xlJTIwQ2xvdWQlMjBCdWlsZCVFMyU4MSVBN1JTcGVjJUUzJTgxJUFFJUUzJTgzJTg2JUUzJTgyJUI5JUUzJTgzJTg4JUUzJTgyJTkyJUU4JUExJThDJUUzJTgxJTg2JnR4dC1hbGlnbj1sZWZ0JTJDdG9wJnR4dC1jb2xvcj0lMjMxRTIxMjEmdHh0LWZvbnQ9SGlyYWdpbm8lMjBTYW5zJTIwVzYmdHh0LXNpemU9NTYmdHh0LXBhZD0wJnM9N2M2NmZjYTZjZjI5ZWE2MmEwNTc2MmU4MTk2YTFkMGQ&amp;mark-x=120&amp;mark-y=112&amp;blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTgzOCZoPTU4JnR4dD0lNDBlbnRhMDcwMSZ0eHQtY29sb3I9JTIzMUUyMTIxJnR4dC1mb250PUhpcmFnaW5vJTIwU2FucyUyMFc2JnR4dC1zaXplPTM2JnR4dC1wYWQ9MCZzPTA3Y2QyY2Q1ODg2ZWJjMmMzMGUzYzY0OTE5ZWMwZDQ4&amp;blend-x=242&amp;blend-y=454&amp;blend-w=838&amp;blend-h=46&amp;blend-fit=crop&amp;blend-crop=left%2Cbottom&amp;blend-mode=normal&amp;txt64=5bKp5omL55yM56uL5aSn5a2m&amp;txt-x=242&amp;txt-y=539&amp;txt-width=838&amp;txt-clip=end%2Cellipsis&amp;txt-color=%231E2121&amp;txt-font=Hiragino%20Sans%20W6&amp;txt-size=28&amp;s=97c7b1f9ccdd80567a11ca644127076e" alt="">			</figure>
				<div class="ys-blog-card__text">
			<p class="ys-blog-card__title">
				<a class="ys-blog-card__link" href="https://qiita.com/enta0701/items/34e896792f5533a8275c">Google Cloud BuildでRSpecのテストを行う #Rails - Qiita</a>
			</p>
							<div class="ys-blog-card__dscr">
					先日、Google Cloud BuildとGithubの連携が発表され、CIの&hellip;				</div>
										<div class="ys-blog-card__domain">qiita.com</div>
					</div>
	</div>
</div>The post <a href="https://mintaku-blog.net/cloudbuild-rspec/">Cloud BuildにRSpecを組み込んでCI/CDパイプラインを構築する</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></content:encoded>
					
					<wfw:commentRss>https://mintaku-blog.net/cloudbuild-rspec/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1755</post-id>	</item>
		<item>
		<title>Firebase HostingからCloud Runに独自ドメインを移管する</title>
		<link>https://mintaku-blog.net/run-domain/</link>
					<comments>https://mintaku-blog.net/run-domain/#respond</comments>
		
		<dc:creator><![CDATA[みんたく]]></dc:creator>
		<pubDate>Thu, 29 Oct 2020 08:52:47 +0000</pubDate>
				<category><![CDATA[GCP]]></category>
		<category><![CDATA[Firebase]]></category>
		<guid isPermaLink="false">https://mintaku-blog.net/?p=1691</guid>

					<description><![CDATA[<p>Firebase Hostingに紐づいた独自ドメインをからCloud Runに移管する方法を紹介します。 Cloud Runに紐づけるドメインのリソースを …</p>
The post <a href="https://mintaku-blog.net/run-domain/">Firebase HostingからCloud Runに独自ドメインを移管する</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></description>
										<content:encoded><![CDATA[<p>Firebase Hostingに紐づいた独自ドメインをからCloud Runに移管する方法を紹介します。</p>
<h2>Cloud Runに紐づけるドメインのリソースをデプロイ</h2>
<p><img data-attachment-id="1693" data-permalink="https://mintaku-blog.net/run-domain/image4/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image4.png?fit=1999%2C356&amp;ssl=1" data-orig-size="1999,356" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image4" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image4.png?fit=300%2C53&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image4.png?fit=800%2C142&amp;ssl=1" loading="lazy" class="aligncenter size-large wp-image-1693" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image4.png?resize=800%2C142&#038;ssl=1" alt="" width="800" height="142" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image4.png?resize=1024%2C182&amp;ssl=1 1024w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image4.png?resize=300%2C53&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image4.png?resize=768%2C137&amp;ssl=1 768w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image4.png?resize=1536%2C274&amp;ssl=1 1536w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image4.png?w=1999&amp;ssl=1 1999w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image4.png?w=1600&amp;ssl=1 1600w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>事前に独自ドメインに紐づけるリソースをCloud Runにデプロイしておきます。デプロイすると上の画像のようにサービスが追加されていることが確認できます。</p>
<h2>マッピングの追加</h2>
<p><img data-attachment-id="1695" data-permalink="https://mintaku-blog.net/run-domain/image2-3/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image2-1.png?fit=1084%2C844&amp;ssl=1" data-orig-size="1084,844" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image2" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image2-1.png?fit=300%2C234&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image2-1.png?fit=800%2C623&amp;ssl=1" loading="lazy" class="aligncenter size-large wp-image-1695" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image2-1.png?resize=800%2C623&#038;ssl=1" alt="" width="800" height="623" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image2-1.png?resize=1024%2C797&amp;ssl=1 1024w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image2-1.png?resize=300%2C234&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image2-1.png?resize=768%2C598&amp;ssl=1 768w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image2-1.png?w=1084&amp;ssl=1 1084w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>Cloud Runのカスタムドメインを管理からマッピングの追加を行います。</p>
<p>Cloud Runにデプロイした独自ドメインと紐付けたいリソースを選択し、紐づける独自ドメインを入力します。</p>
<p>ドメインの確認ができていない場合は、ウェブマスターセントラルに進んで確認を完了させます。</p>
<p>&nbsp;</p>
<h2>DNSレコードの更新</h2>
<p><img data-attachment-id="1692" data-permalink="https://mintaku-blog.net/run-domain/image5/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image5.png?fit=1114%2C1412&amp;ssl=1" data-orig-size="1114,1412" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image5" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image5.png?fit=237%2C300&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image5.png?fit=800%2C1014&amp;ssl=1" loading="lazy" class="aligncenter size-large wp-image-1692" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image5.png?resize=800%2C1014&#038;ssl=1" alt="" width="800" height="1014" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image5.png?resize=808%2C1024&amp;ssl=1 808w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image5.png?resize=237%2C300&amp;ssl=1 237w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image5.png?resize=768%2C973&amp;ssl=1 768w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image5.png?w=1114&amp;ssl=1 1114w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>所有権の証明が完了したら、DNSレコードを更新します。表示されたDNSレコードをCloud DNSに登録します。</p>
<p>今回は既に設定する独自ドメインがFirebase Hostingに紐づいているため、そのDNSレコードを削除して登録します。このタイミングでFirebase Hostingされている既存のサイトが見れなくなるので注意が必要です。</p>
<p>大体15分ほど経つと、Cloud Runのリソースに設定した独自ドメインが紐づきます。</p>
<p>&nbsp;</p>
<p><img data-attachment-id="1696" data-permalink="https://mintaku-blog.net/run-domain/image1-4/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image1-1.png?fit=804%2C418&amp;ssl=1" data-orig-size="804,418" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image1" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image1-1.png?fit=300%2C156&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image1-1.png?fit=800%2C416&amp;ssl=1" loading="lazy" class="aligncenter size-full wp-image-1696" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image1-1.png?resize=800%2C416&#038;ssl=1" alt="" width="800" height="416" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image1-1.png?w=804&amp;ssl=1 804w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image1-1.png?resize=300%2C156&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image1-1.png?resize=768%2C399&amp;ssl=1 768w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>上の画像のようにCloud Runのサービス詳細画面のURLにあるカスタムドメインの欄に紐付けたいドメインが表示されていれば完了です。</p>
<p>&nbsp;</p>
<h2>Firebase Hostingの画面で独自ドメインの設定が解除されたか確認</h2>
<p><img data-attachment-id="1694" data-permalink="https://mintaku-blog.net/run-domain/image3-2/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image3-1.png?fit=1998%2C850&amp;ssl=1" data-orig-size="1998,850" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image3" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image3-1.png?fit=300%2C128&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image3-1.png?fit=800%2C341&amp;ssl=1" loading="lazy" class="aligncenter size-large wp-image-1694" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image3-1.png?resize=800%2C341&#038;ssl=1" alt="" width="800" height="341" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image3-1.png?resize=1024%2C436&amp;ssl=1 1024w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image3-1.png?resize=300%2C128&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image3-1.png?resize=768%2C327&amp;ssl=1 768w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image3-1.png?resize=1536%2C653&amp;ssl=1 1536w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image3-1.png?w=1998&amp;ssl=1 1998w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image3-1.png?w=1600&amp;ssl=1 1600w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>Firebase Hostingの画面にアクセスすると、ドメインの紐付けが解除されており、「設定が必要です」となっているため、後は必要に応じてドメインを削除しましょう。</p>The post <a href="https://mintaku-blog.net/run-domain/">Firebase HostingからCloud Runに独自ドメインを移管する</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></content:encoded>
					
					<wfw:commentRss>https://mintaku-blog.net/run-domain/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1691</post-id>	</item>
		<item>
		<title>【Nuxt.js】Firebase Hosting + Cloud RunでSSRする方法</title>
		<link>https://mintaku-blog.net/nuxt-run/</link>
					<comments>https://mintaku-blog.net/nuxt-run/#respond</comments>
		
		<dc:creator><![CDATA[みんたく]]></dc:creator>
		<pubDate>Mon, 19 Oct 2020 04:45:55 +0000</pubDate>
				<category><![CDATA[Firebase]]></category>
		<category><![CDATA[GCP]]></category>
		<category><![CDATA[Nuxt.js]]></category>
		<guid isPermaLink="false">https://mintaku-blog.net/?p=1679</guid>

					<description><![CDATA[<p>Firebase HostingでホスティングしたNuxt.jsプロジェクトを一部Cloud RunでSSRする方法を紹介します。なおFirebase Ho …</p>
The post <a href="https://mintaku-blog.net/nuxt-run/">【Nuxt.js】Firebase Hosting + Cloud RunでSSRする方法</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></description>
										<content:encoded><![CDATA[<p>Firebase HostingでホスティングしたNuxt.jsプロジェクトを一部Cloud RunでSSRする方法を紹介します。なおFirebase HostingとCloud Runは同じプロジェクト内で作成する必要があります。</p>
<h2>Nuxt.jsのアプリをコンテナ化し、Container Registryに登録し、Cloud Runにデプロイする方法</h2>
<h3>Cloud BuildとCloud Runの有効化</h3>
<p>まずはCloud Build APIとCloud Run APIを有効化しておきます。</p><pre class="crayon-plain-tag"># Cloud Buildの有効化
$ gcloud services enable cloudbuild.googleapis.com</pre><p></p><pre class="crayon-plain-tag"># Cloud Runの有効化
$ gcloud services enable run.googleapis.com</pre><p>&nbsp;</p>
<h3>nuxt.config.jsの変更</h3>
<p>nuxt.config.jsにserverオプションを追加します。</p>
<p>hostはlocalhostや127.0.0.1ではなく、0.0.0.0に設定する必要があります。</p>
<p>&nbsp;</p>
<p>・nuxt.config.js</p><pre class="crayon-plain-tag">export default {
  server: {
    port: 3000, // default: 3000
    host: '0.0.0.0', // default: localhost,
    timing: false
  }
}</pre><p>&nbsp;</p>
<h3>cloudbuild.yamlを作成する</h3>
<p>cloudbuild.yamlの書き方は以下の公式サイトを参考にしています。</p>
<p>コンテナイメージをビルドして、Container Registryにプッシュしています。その後、Container RegistryからCloud Runにデプロイしています。</p>
<p>参考：</p>

<div class="ys-blog-card">
	<div class="ys-blog-card__container">
					<figure class="ys-blog-card__image">
				<img src="https://i0.wp.com/docs.cloud.google.com/_static/cloud/images/social-icon-google-cloud-1200-630.png?w=800&#038;ssl=1" alt="" data-recalc-dims="1">			</figure>
				<div class="ys-blog-card__text">
			<p class="ys-blog-card__title">
				<a class="ys-blog-card__link" href="https://cloud.google.com/cloud-build/docs/deploying-builds/deploy-cloud-run?hl=ja">Cloud Build を使用した Cloud Run へのデプロイ &nbsp;|&nbsp; Google Cloud Documentation</a>
			</p>
										<div class="ys-blog-card__domain">cloud.google.com</div>
					</div>
	</div>
</div>

<p>&nbsp;</p>
<p>・cloudbuild.yaml</p><pre class="crayon-plain-tag">steps:
  # Build the container image
  - name: 'gcr.io/cloud-builders/docker'
    args: ['build', '-t', 'gcr.io/test-staging/nuxt-ssr', '.']
  # Push the container image to Container Registry
  - name: 'gcr.io/cloud-builders/docker'
    args: ['push', 'gcr.io/test-staging/nuxt-ssr']
  # Deploy container image to Cloud Run
  - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    entrypoint: gcloud
    args: ['run', 'deploy', 'nuxt-ssr-test', '--image', 'gcr.io/test-staging/nuxt-ssr', '--region', 'asia-northeast1', '--platform', 'managed', '--port', '3000']
images:
  - gcr.io/test-staging/nuxt-ssr</pre><p>&nbsp;</p>
<h3>Dockerfileを作成する</h3>
<p>次にNuxt.jsのアプリをコンテナ化するためにDockerfileを作成します。</p>
<p>参考：</p>

<div class="ys-blog-card">
	<div class="ys-blog-card__container">
					<figure class="ys-blog-card__image">
				<img src="https://i0.wp.com/v2.nuxt.com/preview.png?w=800&#038;ssl=1" alt="" data-recalc-dims="1">			</figure>
				<div class="ys-blog-card__text">
			<p class="ys-blog-card__title">
				<a class="ys-blog-card__link" href="https://ja.nuxtjs.org/faq/deployment-cloud-run/">Nuxt 2 - Google Cloud Run</a>
			</p>
							<div class="ys-blog-card__dscr">
					Nuxt を Google Cloud Run にどうやってデプロイするのか？				</div>
										<div class="ys-blog-card__domain">ja.nuxtjs.org</div>
					</div>
	</div>
</div>

<p>&nbsp;</p>
<p>・Dockerfile</p><pre class="crayon-plain-tag">FROM node:14

# https://docs.docker.jp/engine/reference/builder.html#workdir
WORKDIR /usr/src/app

COPY package.json ./
RUN npm install

COPY . .

# https://docs.docker.jp/engine/reference/builder.html#expose
# EXPOSE 命令はコンテナの実行時に、所定ネットワーク上のどのポートをリッスンするかを指定
EXPOSE 3000

RUN npm run build

CMD [ "npm", "run", "start" ]</pre><p>&nbsp;</p>
<p>gcloud initした後に以下のコマンドでcloudbuild.yamlのコマンドが走ります。</p><pre class="crayon-plain-tag">$ gcloud builds submit</pre><p>&nbsp;</p>
<p>成功すると、Container Registryにコンテナイメージが登録され、Cloud Runにコンテナがデプロイされていることが確認できます。</p>
<p>・Container Registry</p>
<p><img data-attachment-id="1682" data-permalink="https://mintaku-blog.net/nuxt-run/image2-2/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image2-e1602640857173.png?fit=1999%2C104&amp;ssl=1" data-orig-size="1999,104" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image2" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image2-e1602640857173.png?fit=300%2C16&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image2-e1602640857173.png?fit=800%2C41&amp;ssl=1" loading="lazy" class="aligncenter wp-image-1682 size-large" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image2-e1602640857173-1024x53.png?resize=800%2C41&#038;ssl=1" alt="" width="800" height="41" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image2-e1602640857173.png?resize=1024%2C53&amp;ssl=1 1024w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image2-e1602640857173.png?resize=300%2C16&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image2-e1602640857173.png?resize=768%2C40&amp;ssl=1 768w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image2-e1602640857173.png?resize=1536%2C80&amp;ssl=1 1536w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image2-e1602640857173.png?w=1999&amp;ssl=1 1999w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image2-e1602640857173.png?w=1600&amp;ssl=1 1600w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>&nbsp;</p>
<p>・Cloud Run</p>
<p><img data-attachment-id="1683" data-permalink="https://mintaku-blog.net/nuxt-run/image1-3/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image1.png?fit=1796%2C96&amp;ssl=1" data-orig-size="1796,96" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image1" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image1.png?fit=300%2C16&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image1.png?fit=800%2C43&amp;ssl=1" loading="lazy" class="aligncenter size-large wp-image-1683" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image1.png?resize=800%2C43&#038;ssl=1" alt="" width="800" height="43" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image1.png?resize=1024%2C55&amp;ssl=1 1024w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image1.png?resize=300%2C16&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image1.png?resize=768%2C41&amp;ssl=1 768w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image1.png?resize=1536%2C82&amp;ssl=1 1536w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image1.png?w=1796&amp;ssl=1 1796w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image1.png?w=1600&amp;ssl=1 1600w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>&nbsp;</p>
<h3>Cloud Runにデプロイしたリソースにメンバーとロールの追加</h3>
<p><img data-attachment-id="1681" data-permalink="https://mintaku-blog.net/nuxt-run/image3/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image3.png?fit=1384%2C898&amp;ssl=1" data-orig-size="1384,898" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image3" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image3.png?fit=300%2C195&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image3.png?fit=800%2C519&amp;ssl=1" loading="lazy" class="aligncenter size-large wp-image-1681" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image3.png?resize=800%2C519&#038;ssl=1" alt="" width="800" height="519" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image3.png?resize=1024%2C664&amp;ssl=1 1024w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image3.png?resize=300%2C195&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image3.png?resize=768%2C498&amp;ssl=1 768w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/10/image3.png?w=1384&amp;ssl=1 1384w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>Cloud Runにデプロイしたままでは、デプロイしたアプリは誰もアクセスすることができません。</p>
<p>アクセスできるようにするために、Cloud Runにデプロイしたリソースにメンバーとロールを追加します。</p>
<p>ここでは全てのユーザが見れるようにメンバーを「allUsers」にし、ロールを「Cloud Run起動元」で追加します。「allUsers」すると、デプロイしたリソースは一般公開され、インターネット上から誰でもアクセスできる状態になるため、注意していください。</p>
<p>保存後、Cloud Runに記載されているURLにアクセすることができるようになります。</p>
<p>&nbsp;</p>
<h2>Firebase HostingからCloud Runにリクエストをリダイレクトする</h2>
<p>Firebase HostingでホスティングしたNuxt.jsプロジェクトを一部Cloud RunでSSRします。Cloud RunでSSRしたいリソースをfirebase.jsonのrewritesに追加します。</p>
<p>今回の場合は、/testsをCloud Runのリソースを使うようにします。つまり、/testsへのアクセスがあった場合にFirebase Hostingのリソースを使わずに、Cloud Runのリソースを使うようリクエストをリダイレクトします。</p>
<p>なおFirebase Hostingの/testsのリソースは空にしておかないと、正常にリダイレクトされないので注意しましょう。</p>
<p>serviceIdは先ほどデプロイしたCloud Runのサービス、regionはCloud Runで使用しているリージョンを選択します。後はfirebase.jsonをデプロイして完了です。</p>
<p>・firebase.json</p><pre class="crayon-plain-tag">...

  "rewrites": [
  {
    "source": "/tests",
    "run": {
      "serviceId": "nuxt-ssr-test",
      "region": "asia-northeast1"
    }
  }
],

...</pre><p>&nbsp;</p>The post <a href="https://mintaku-blog.net/nuxt-run/">【Nuxt.js】Firebase Hosting + Cloud RunでSSRする方法</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></content:encoded>
					
					<wfw:commentRss>https://mintaku-blog.net/nuxt-run/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1679</post-id>	</item>
		<item>
		<title>【Rails】Google Analytics Reporting APIでレポートデータ取得する方法</title>
		<link>https://mintaku-blog.net/rails-ga/</link>
					<comments>https://mintaku-blog.net/rails-ga/#respond</comments>
		
		<dc:creator><![CDATA[みんたく]]></dc:creator>
		<pubDate>Sat, 05 Sep 2020 03:03:43 +0000</pubDate>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[GCP]]></category>
		<category><![CDATA[その他]]></category>
		<guid isPermaLink="false">https://mintaku-blog.net/?p=1558</guid>

					<description><![CDATA[<p>RailsでGoogle Analytics Reporting APIでレポートデータ取得する方法をまとめました。レポートデータ取得処理を独自クラス化し、 …</p>
The post <a href="https://mintaku-blog.net/rails-ga/">【Rails】Google Analytics Reporting APIでレポートデータ取得する方法</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></description>
										<content:encoded><![CDATA[<p>RailsでGoogle Analytics Reporting APIでレポートデータ取得する方法をまとめました。レポートデータ取得処理を独自クラス化し、JSON形式のレスポンスで返すところまでを紹介しています。</p>
<h2>Google Analytics Reporting APIの設定準備</h2>
<p>Google Analytics Reporting APIの設定は以下の記事を参考にしました。</p>
<ul>
<li>プロジェクトの作成</li>
<li>サービスアカウントの作成</li>
<li>秘密鍵のJSONファイルを生成 ← あとで使います</li>
<li>Googleアナリティクスにユーザ追加</li>
<li>ビューIDの確認 ← あとで使います</li>
</ul>
<p>参考：<a href="https://qiita.com/ryota-sasabe/items/a5efd2aac244cfcce5c7" target="_blank" rel="noopener noreferrer">Google Analytics API を叩いてデータを取得するまでの流れ（Ruby）</a></p>
<p>&nbsp;</p>
<h2>RailsでGoogleアナリティクスレポートデータ取得処理をクラス化</h2>
<p>Googleアナリティクスレポートデータ取得処理を独自クラス化し、コントローラで使えるようにします。</p>
<p>先程生成した秘密鍵のJSONファイルは「analytics_auth.json」として配置し、authメソッドでGoogleアナリティクスAPIに認証を行ってからレポートデータを取得しにいきます。</p>
<p>report_pv_count_by_dateメソッドで、取得開始日と取得終了日を引数(デフォルトは当日)で指定してその期間のレポートデータを取得できるようにします。</p>
<p>・lib/analytics.rb</p><pre class="crayon-plain-tag">require 'google/apis/analyticsreporting_v4'

class Analytics

  # レポート対象を指定してオブジェクトを生成
  # @param [String] base_url レポート対象サイトのURL
  # @param [String] view_id ビューID
  def initialize(base_url, view_id)
    @base_url = base_url
    @view_id = view_id
    @analytics = Google::Apis::AnalyticsreportingV4
    auth
  end

  # 指定した期間のページごとのPVを集計
  # @param [String] date 日付を表す文字列
  # @return [Hash] 累計PV及びページごとのPV
  def report_pv_count_by_date(start_date = 'today', end_date = 'today')
    date_range = @analytics::DateRange.new(start_date: start_date, end_date: end_date)
    metric = @analytics::Metric.new(expression: 'ga:users', alias: 'users')
    dimension = @analytics::Dimension.new(name: 'ga:pagePath')
    order_by = @analytics::OrderBy.new(field_name: 'ga:users', sort_order: 'DESCENDING')
    request = @analytics::GetReportsRequest.new(
      report_requests: [@analytics::ReportRequest.new(
        view_id: @view_id,
        metrics: [metric],
        date_ranges: [date_range],
        dimensions: [dimension],
        order_bys: [order_by],
      )]
    )
    response = @client.batch_get_reports(request)
    data = response.reports.first.data
    return {
      total: data.totals.first.values.first,
      pages: data.rows.map do |row|
        {
          url: @base_url + row.dimensions.first,
          dir: row.dimensions.first,
          views: row.metrics.first.values.first
        }
      end
    }
  end

  private

  # GoogleアナリティクスAPIに認証
  # 同ディレクトリにanalytics_auth.jsonを配置
  def auth
    scope = ['https://www.googleapis.com/auth/analytics.readonly']
    @client = @analytics::AnalyticsReportingService.new
    @client.authorization = Google::Auth::ServiceAccountCredentials.make_creds(
      json_key_io: File.open('analytics_auth.json'),
      scope: scope
    )
  end

end</pre><p>&nbsp;</p>
<p>独自クラスを作成したら、呼び出せるようにapplication.rbに以下を追記します。</p>
<p>・config/application.rb</p><pre class="crayon-plain-tag">require_relative 'boot'

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module AppName
  class Application &lt; Rails::Application

    ...

    # 独自クラスパス指定
    config.autoload_paths += %W(#{config.root}/lib) ←追加

    ...

  end
end</pre><p>&nbsp;</p>
<p>uninitialized constantエラーで定義したクラスを読むことができない場合は、config/initializersディレクトリ配下にrequirements.rbファイルを作成し、以下を追記してください。</p>
<p>・config/initializers/requirements.rb</p><pre class="crayon-plain-tag">require Rails.root.join('lib/analytics.rb')</pre><p>&nbsp;</p>
<h2>クラス化したGoogleアナリティクスレポートデータ取得メソッド呼び出し</h2>
<p>実際にコントローラで呼び出してみます。初期化のBASE_URLとVIEW_IDは環境変数として.envに設定し呼び出して使うようにします。</p>
<p>フロントからパラメータ(取得開始日・取得終了日)をPOSTし、それらを引数にして実行しています。レスポンスはJSON形式で返すようにしています。</p>
<p>あとはroutes.rbにルーティングを設定して完了です。</p>
<p>・app/controllers/api/analytics_controller.rb</p><pre class="crayon-plain-tag">class Api::AnalyticsController &lt; Api::ApplicationController

  def report
    analytics = ::Analytics.new(ENV['BASE_URL'], ENV['VIEW_ID'])

    render json: analytics.report_pv_count_by_date(params[:start_date], params[:end_date])
  end

end</pre><p>以上、RailsでGoogle Analytics Reporting APIでレポートデータ取得する方法でした。</p>The post <a href="https://mintaku-blog.net/rails-ga/">【Rails】Google Analytics Reporting APIでレポートデータ取得する方法</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></content:encoded>
					
					<wfw:commentRss>https://mintaku-blog.net/rails-ga/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1558</post-id>	</item>
		<item>
		<title>Go + Gin + GormでREST APIを実装してGAEにデプロイする</title>
		<link>https://mintaku-blog.net/go-gin/</link>
					<comments>https://mintaku-blog.net/go-gin/#respond</comments>
		
		<dc:creator><![CDATA[みんたく]]></dc:creator>
		<pubDate>Mon, 13 Jul 2020 13:53:12 +0000</pubDate>
				<category><![CDATA[GCP]]></category>
		<category><![CDATA[Go]]></category>
		<guid isPermaLink="false">https://mintaku-blog.net/?p=1569</guid>

					<description><![CDATA[<p>Go + Gin + GormでREST APIをさくっと実装してGAEにデプロイしてみました。 そもそもGoの本やGoに関する情報を読んだ感じ、多くのこと …</p>
The post <a href="https://mintaku-blog.net/go-gin/">Go + Gin + GormでREST APIを実装してGAEにデプロイする</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></description>
										<content:encoded><![CDATA[<p>Go + Gin + GormでREST APIをさくっと実装してGAEにデプロイしてみました。</p>
<p>そもそもGoの本やGoに関する情報を読んだ感じ、多くのことが標準ライブラリでまかなえるため、基本はFWやORMを使わないのが「Goらしい手法」とのことなので、次は標準ライブラリのみでも実装してみたいと思います。</p>
<p>参考：<a href="https://employment.en-japan.com/engineerhub/entry/2018/06/19/110000" target="_blank" rel="noopener noreferrer">https://employment.en-japan.com/engineerhub/entry/2018/06/19/110000</a></p>
<p>参考：<a href="https://golang.org/doc/effective_go.html" target="_blank" rel="noopener noreferrer">https://golang.org/doc/effective_go.html</a></p>
<h2>Ginとは</h2>
<p>Ginとは軽量かつシンプルなインターフェイスが特徴のGoのWebアプリケーションフレームワークです。</p>
<p>また、GoのWebアプリケーションの中では比較的初期から開発されているので安定して使われています。</p>
<h2>Gormとは</h2>
<p>Goでよく使われているORMの一種です。</p>
<p>そもそもORM(O/Rマッピング)とは、オブジェクト指向言語におけるオブジェクトと、リレーショナルデータベースにおけるレコードとを対応づけることです。</p>
<p>ORMによって、リレーショナルデータベースのレコードがオブジェクトとして直感的に扱えるようになり、リレーショナルデータベースにアクセスするプログラムを記述する処理を容易にすることが可能になります。</p>
<h2>プロジェクト構成</h2>
<p>Getパラメータで本検索をして、その結果をJSON形式で返す簡単なAPIを実装していきます。</p>
<p>以下の記事を参考にプロジェクト構成を組んでみました。元々Railsを書いていたこともあり、この構成が今のところしっくりきました(今後勉強していくうちによりより構成が見つかる気がします)。</p>
<p>参考：<a href="https://qiita.com/Asuforce/items/0bde8cabb30ac094fcb4" target="_blank" rel="noopener noreferrer">https://qiita.com/Asuforce/items/0bde8cabb30ac094fcb4</a></p>
<p>sample-go-api<br />
├── controller<br />
│ └──book_controller.go<br />
├── db<br />
│ └── db.go<br />
├── entity<br />
│ └── book.go<br />
├── main.go<br />
├── server<br />
│ └── server.go<br />
├── service<br />
│ └── book_service.go<br />
├── .env.development<br />
├── .env.production<br />
├── .gcloudignore<br />
├── .gitgnore<br />
├── app.yaml<br />
├── docker-compose.yml<br />
├── go.mod<br />
├── go.sum<br />
├── main.go</p>
<h2>DB・モデル実装</h2>
<p>ローカル用にDockerでさくっとMySQLを立ち上げてDBを作成します。</p>
<p>・docker-compose.yml</p><pre class="crayon-plain-tag">version: '3'
services:
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: db
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    ports:
      - "3306:3306"</pre><p>&nbsp;</p>
<p>docker-compose.ymlができたら、起動します。</p><pre class="crayon-plain-tag">$ docker-compose up -d</pre><p>&nbsp;</p>
<p>次にGormとMySQLをgo getでインストールします。</p><pre class="crayon-plain-tag">$ go get github.com/jinzhu/gorm
$ go get github.com/jinzhu/gorm/dialects/mysql</pre><p>&nbsp;</p>
<p>本モデルを作成します。</p>
<p>booksテーブルのカラムを定義します。</p>
<p>・entity/book.go</p><pre class="crayon-plain-tag">package entity

import (
  "time"
)

type Book struct {
  Id uint
  Title string `gorm:"size:128"`
  Category int
  Author string `gorm:"size:64"`
  CreatedAt time.Time
}</pre><p>&nbsp;</p>
<p>DB周りを実装していきます。今回はGAEに本番環境をデプロイするので、developmentとproductionと2つの環境を作りました。そのため、godotenvライブラリを使って実行する環境を取得します。</p>
<p>実行環境に合ったDB接続を行います。ローカルはDockerで立ち上げたMySQL、本番はCloud SQLを使っています。</p>
<p>DB初回起動時にマイグレーションが行われるようにしています。</p>
<p>・db/db.go</p><pre class="crayon-plain-tag">package db

import (
  "os"

  "github.com/jinzhu/gorm"
  _ "github.com/jinzhu/gorm/dialects/mysql"
  "github.com/joho/godotenv"

  "github.com/sample/sample-go-api/entity"
)

var (
  db *gorm.DB
  err error
)

// DB初期化
func Init() {
  // 実行環境取得
  env := os.Getenv("ENV")

  if "production" == env {
    env = "production"
  } else {
    env = "development"
  }

  // 環境変数取得
  godotenv.Load(".env." + env)
  godotenv.Load()

  // DB接続
  db, err = gorm.Open("mysql", os.Getenv("CONNECT"))

  if err != nil {
    panic(err)
  }

  autoMigration()
}

// DB取得
func GetDB() *gorm.DB {
  return db
}

// DB接続終了
func Close() {
  if err := db.Close(); err != nil {
    panic(err)
  }
}

// マイグレーション
func autoMigration() {
  db.AutoMigrate(&amp;entity.Book{})
}</pre><p>&nbsp;</p>
<p>ローカル環境用のenv。</p>
<p>・.env.development</p><pre class="crayon-plain-tag">CONNECT=user:password@tcp(localhost:3306)/db?parseTime=true</pre><p>&nbsp;</p>
<p>本番環境用のenv。</p>
<p>・.env.production</p><pre class="crayon-plain-tag">CONNECT=user:password@unix(/cloudsql/sample-project:sample-zone:sample-instance)/sample_db?parseTime=true</pre><p>&nbsp;</p>
<h2>Bookサービスの実装</h2>
<p>検索処理を実装していきます。送られてきたGETパラメータからそれぞれのカラム検索を行います。</p>
<p>Gormを使っていますが、このくらいのSQLならわざわざORMを使わなくても良い気がしますね。</p>
<p>・service/book_service.go</p><pre class="crayon-plain-tag">package book

import (
  "github.com/sample/sample-go-api/db"
  "github.com/sample/sample-go-api/entity"
)

type Service struct{}

type book entity.Book

type Parameter struct {
  title string
  category int
  author string
}

// 検索
func (s Service) Search(title string, category int, author string) ([]Book, error) {

  // DB接続
  db := db.GetDB()

  // 本モデルから作成
  var book []Book

  // パラメータセット
  p := Parameter{title, category, author}

  // DB接続確認
  if err := db.Take(&amp;book).Error; err != nil {
    return nil, err
  }

  // 本検索クエリ
  tx := db
  tx = tx.Find(&amp;book)

  // タイトル
  if p.title != "" {
    tx = tx.Where("title = ?", p.title).Find(&amp;book)
  }

  // カテゴリ
  if p.category != 0 {
    tx = tx.Where("category = ?", p.category).Find(&amp;book)
  }

  // 著者
  if p.author != "" {
    tx = tx.Where("author = ?", p.author).Find(&amp;book)
  }

  return book, nil
}</pre><p>&nbsp;</p>
<h2>Bookコントローラの実装</h2>
<p>Ginをgo getでインストールしておきます。</p><pre class="crayon-plain-tag">$ go get -u github.com/gin-gonic/gin</pre><p>&nbsp;</p>
<p>コントローラを実装します。*gin.ContextでGETパラメータを取得してサービスの検索メソッドに投げています。</p>
<p>検索結果を受け取ってJSON形式で返しています。</p>
<p>・controller/book_controller.go</p><pre class="crayon-plain-tag">package book

import (
  "fmt"
  "net/http"
  "strconv"

  "github.com/gin-gonic/gin"

  book "github.com/sample/sample-go-api/service"
)

type Controller struct{}

// 検索 GET /books
func (pc Controller) Index(c *gin.Context) {
  // パラメータ取得
  title := c.Query("title")
  category, _ := strconv.Atoi(c.Query("category"))
  author := c.Query("author")

  // 検索処理
  var s book.Service
  p, err := s.Search(title, category, author)

  // 検索結果を返す
  if err != nil {
    c.AbortWithStatus(http.StatusNotFound)
    fmt.Println(err)
  } else {
    c.JSON(http.StatusOK, p)
  }
}</pre><p>&nbsp;</p>
<h2>サーバ周り実装</h2>
<p>ルーティング・CORS設定・サーバ起動を実装しています。</p>
<p>・server/server.go</p><pre class="crayon-plain-tag">package server

import (
  "net/http"

  "github.com/gin-gonic/gin"

  book "github.com/sample/sample-go-api/controller"
)

// 初期化
func Init() {
  r := router()

  r.Run()
}

// ルーティング
func router() *gin.Engine {
  r := gin.Default()

  // CORS対応
  r.Use(CORS())

  // ルーティング
  u := r.Group("/books")
  {
    ctrl := book.Controller{}
    u.GET("", ctrl.Index)
  }

  return r
}

// CORS
func CORS() gin.HandlerFunc {
  return func(c *gin.Context) {
    c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
    c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
    c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
    c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")

    if c.Request.Method == "OPTIONS" {
      c.AbortWithStatus(http.StatusNoContent)
      return
    }

    c.Next()
  }
}</pre><p>&nbsp;</p>
<p>main.goの実装</p>
<p>最後にmain.goからDBとサーバを起動して完了です。後は.gitignoreにenvファイルを追加しておきましょう。</p><pre class="crayon-plain-tag">package main

import (
  "github.com/sample/sample-go-api/db"
  "github.com/sample/sample-go-api/server"
)

func main() {
  db.Init()
  server.Init()
}</pre><p>&nbsp;</p>
<h2>GAEにデプロイする</h2>
<p>完成したAPIをGAEにデプロイします。</p>
<p>Goのバージョンは1.12、インスタンスクラスは一番下のF1を指定します(デフォルトF1ですが)。</p>
<p>正規表現 /.* にパスが一致するURLへのすべてのリクエストはmainパッケージのhandle関数で処理されます。</p>
<p>ENVでproductionを指定することでCloud SQLに接続するようにしています。</p>
<p>参考：https://cloud.google.com/appengine/docs/standard/go/config/appref?hl=ja</p><pre class="crayon-plain-tag">runtime: go112
service: sample-go-api-production
instance_class: F1
handlers:
  - url: /.*
    script: auto
env_variables:
  ENV: production</pre><p>&nbsp;</p>
<p>以下のコマンドでGAEにデプロイして完了です。</p><pre class="crayon-plain-tag">$ gcloud app deploy</pre><p></p>The post <a href="https://mintaku-blog.net/go-gin/">Go + Gin + GormでREST APIを実装してGAEにデプロイする</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></content:encoded>
					
					<wfw:commentRss>https://mintaku-blog.net/go-gin/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1569</post-id>	</item>
		<item>
		<title>「Jamstack」アーキテクチャによるWeb開発【Nuxt.js×MicroCMS×Firebase】</title>
		<link>https://mintaku-blog.net/jamstack/</link>
					<comments>https://mintaku-blog.net/jamstack/#respond</comments>
		
		<dc:creator><![CDATA[みんたく]]></dc:creator>
		<pubDate>Fri, 03 Jul 2020 14:01:26 +0000</pubDate>
				<category><![CDATA[Nuxt.js]]></category>
		<category><![CDATA[Firebase]]></category>
		<category><![CDATA[アーキテクチャ]]></category>
		<category><![CDATA[GCP]]></category>
		<guid isPermaLink="false">https://mintaku-blog.net/?p=1537</guid>

					<description><![CDATA[<p>新規開発で「Jamstack」アーキテクチャを取り入れて開発したので、その過程やメリットなどについてまとめておきます。 Jamstack構成にあたり以下のサ …</p>
The post <a href="https://mintaku-blog.net/jamstack/">「Jamstack」アーキテクチャによるWeb開発【Nuxt.js×MicroCMS×Firebase】</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></description>
										<content:encoded><![CDATA[<p>新規開発で「Jamstack」アーキテクチャを取り入れて開発したので、その過程やメリットなどについてまとめておきます。</p>
<p>Jamstack構成にあたり以下のサービスを活用しています。</p>
<ul>
<li>静的サイトジェネレータ：Nuxt.js</li>
<li>ヘッドレスCMS：microCMS</li>
<li>ホスティングサービス：Firebase Hosting</li>
</ul>
<h2>Jamstackとは</h2>
<p>Jamstack(ジャムスタック)とはウェブサイトを実現するためのJAMの頭文字からなる技術の組み合わせです。JAMはそれぞれJavaScript・API・ Markupを表しています。</p>
<p>Jamstackは、サーバとフロントを疎結合にし、サーバが担っていた機能を外部化してフロントだけで扱いやすくする構成となっています。</p>
<p>公式サイト：<a href="https://jamstack.org/" target="_blank" rel="noopener noreferrer">https://jamstack.org/</a></p>
<h2>Jamstackの特徴</h2>
<ul>
<li>Webサイトの各ページのHTMLファイルは事前に静的サイトジェネレータで生成</li>
<li>ブラウザからアクセス時にCDNから配信</li>
<li>Webサーバに依存しないサーバレスな構成</li>
</ul>
<p>Jamstackは以上のような特徴が挙げられます。</p>
<p>閲覧専用でユーザごとにコンテンツの出し分けがないようなWebサービスに最も適していると考えられます。パッと思いつくのは、ユーザ認証等がないWebメディアやコーポレートサイトで効果を発揮しそうです。</p>
<h2>Jamstackで使われるサービス</h2>
<p>このようなJamstack構成を実現させるために、以下のようなサービスが使われます。</p>
<ul>
<li>静的サイトジェネレータ</li>
<li>ヘッドレスCMS</li>
<li>ホスティングサービス</li>
</ul>
<p>Jamstackアーキテクチャの採用にあたり今回開発した新規サービスでは、静的サイトジェネレータはNuxt.js、ヘッドレスCMSはmicroCMS、ホスティングサービスはFirebase Hostingを採用しています。</p>
<p>ホスティングサービスは他にNetlifyが有名(そもそもNetlifyのCEOがJamstack提唱したっぽい)で、そちらはWebhookによるトリガが可能(Firebase Hostingではできないっぽい？)なので、ヘッドレスCMSから記事投稿時にWebhookによる通知をして、自動ビルドできます。</p>
<p>Firebase Hostingでは調べた限りでは、Webhookによるトリガができないようなので、新規サービスではGitプッシュ時とスケジューリングで1日1回自動ビルドするように運用しています。どうしてもその日に公開したい記事の場合は手動でビルド・デプロイといった感じです。</p>
<h2>Jamstack導入のメリット</h2>
<p>Jamstackには以下のようメリットがあります。</p>
<p>・高パフォーマンス<br />
→nuxt generateによってデプロイ前にあらかじめ静的ページを生成することでCDN配信が可能となり、より高いパフォーマンスを実現できました。</p>
<p>・高セキュリティ<br />
→コンテンツ等はあらかじめ静的ファイルとしてホスティングしているため、サーバ側のプロセスが必要最低限のAPIに集約され、脆弱性に対する攻撃対象の減少が期待できます。</p>
<p>・コスト削減<br />
→主にコンテンツ配信の手段として利用するため、コストの削減が可能となります。</p>
<p>・SEO向上<br />
→SSGによるページ遷移の高速化・サーバ側でレンダリングしたHTMLを読み込むことにより、SEO向上が期待できます。</p>
<p>また、コンテンツにおけるAPIレスポンスは、ビルドのタイミングで全部取得してホスティングしているため、安定的な稼働が可能となります。</p>
<p>逆に言えば、ビルド時にAPIがおかしかったらエラーがでるため、デプロイ前に気づくことができるのも良い点かと思います。</p>
<h2>Jamstack採用において</h2>
<p>今回の新規サービスでは、認証機能やユーザ登録・更新処理などが追加実装されたため、完全なJamstack構成というより、部分的Jamstack構成になりました。</p>
<p>もし、認証機能やユーザ登録・更新処理などがなくコンテンツのみの場合は以下のような構成になります。</p>
<p><img data-attachment-id="1555" data-permalink="https://mintaku-blog.net/jamstack/%e6%96%b0%e8%a6%8f%e3%82%b5%e3%83%bc%e3%83%92%e3%82%99%e3%82%b9%e3%81%ab%e3%81%8a%e3%81%91%e3%82%8bjamstack%e6%a7%8b%e6%88%90%e3%82%b3%e3%83%b3%e3%83%86%e3%83%b3%e3%83%84%e3%81%ae%e3%81%bf%e3%81%ae-2/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/82b91a00e4e1849240ed56b95f23673e.png?fit=960%2C540&amp;ssl=1" data-orig-size="960,540" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="新規サービスにおけるJamstack構成(コンテンツのみの場合)" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/82b91a00e4e1849240ed56b95f23673e.png?fit=300%2C169&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/82b91a00e4e1849240ed56b95f23673e.png?fit=800%2C450&amp;ssl=1" loading="lazy" class="aligncenter size-full wp-image-1555" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/82b91a00e4e1849240ed56b95f23673e.png?resize=800%2C450&#038;ssl=1" alt="" width="800" height="450" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/82b91a00e4e1849240ed56b95f23673e.png?w=960&amp;ssl=1 960w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/82b91a00e4e1849240ed56b95f23673e.png?resize=300%2C169&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/82b91a00e4e1849240ed56b95f23673e.png?resize=768%2C432&amp;ssl=1 768w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>これが静的ファイルのみで構成される一般的なJamstack構成になると思います。Firebase HostingからCDN配信で完結しているため、サイトの高速化・高セキュリティ・サーバレスとなります。</p>
<p>なんとかヘッドレスCMSからの記事投稿をトリガに自動ビルド・デプロイできれば理想型って感じですかね。</p>
<p>&nbsp;</p>
<p>実際の新規サービスでは認証機能等あるので、以下のような構成になります。</p>
<p><img data-attachment-id="1553" data-permalink="https://mintaku-blog.net/jamstack/gcp%e5%9b%b3%e8%a7%a3/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/08752a3329319d2e60dfc60c4cdd5b51.png?fit=960%2C540&amp;ssl=1" data-orig-size="960,540" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="GCP図解" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/08752a3329319d2e60dfc60c4cdd5b51.png?fit=300%2C169&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/08752a3329319d2e60dfc60c4cdd5b51.png?fit=800%2C450&amp;ssl=1" loading="lazy" class="aligncenter size-full wp-image-1553" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/08752a3329319d2e60dfc60c4cdd5b51.png?resize=800%2C450&#038;ssl=1" alt="" width="800" height="450" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/08752a3329319d2e60dfc60c4cdd5b51.png?w=960&amp;ssl=1 960w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/08752a3329319d2e60dfc60c4cdd5b51.png?resize=300%2C169&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/08752a3329319d2e60dfc60c4cdd5b51.png?resize=768%2C432&amp;ssl=1 768w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p><img data-attachment-id="1554" data-permalink="https://mintaku-blog.net/jamstack/%e6%96%b0%e8%a6%8f%e3%82%b5%e3%83%bc%e3%83%92%e3%82%99%e3%82%b9%e3%81%ab%e3%81%8a%e3%81%91%e3%82%8bjamstack%e6%a7%8b%e6%88%90%e2%91%a1-2/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/98f711aee4d84aeb00b97dbf0e5335a5.png?fit=960%2C540&amp;ssl=1" data-orig-size="960,540" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="新規サービスにおけるJamstack構成②" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/98f711aee4d84aeb00b97dbf0e5335a5.png?fit=300%2C169&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/98f711aee4d84aeb00b97dbf0e5335a5.png?fit=800%2C450&amp;ssl=1" loading="lazy" class="aligncenter size-full wp-image-1554" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/98f711aee4d84aeb00b97dbf0e5335a5.png?resize=800%2C450&#038;ssl=1" alt="" width="800" height="450" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/98f711aee4d84aeb00b97dbf0e5335a5.png?w=960&amp;ssl=1 960w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/98f711aee4d84aeb00b97dbf0e5335a5.png?resize=300%2C169&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/06/98f711aee4d84aeb00b97dbf0e5335a5.png?resize=768%2C432&amp;ssl=1 768w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<ul>
<li>コンテンツはあらかじめビルドしてある静的ファイルをFirebase HostingからCDN配信</li>
<li>認証はFirebase Authenticationを利用</li>
<li>ユーザ登録やユーザ情報更新等は別途APIからやり取り</li>
</ul>
<p>コンテンツの表示スピードの高速化やSEO向上、ユーザ情報登録・更新や検索のみサーバを使っているのでコストの削減もでき、Jamstackの恩恵を十分に受けられていると感じています。</p>
<h2>まとめ</h2>
<p>実際にJamstackアーキテクチャで新規サービスを開発してみて、サイトスピードが高速化し安定的に稼働していていい感じです。</p>
<p>毎回ビルドするといった手間はありますが、CI/CDツールを取り入れればそんな手間ではなくなります。</p>
<p>静的化できるファイルが多くある場合は、Jamstackアーキテクチャを取り入れるのが良さそうですね。</p>
<div id="gtx-trans" style="position: absolute; left: 38px; top: 2037.06px;">
<div class="gtx-trans-icon"></div>
</div>The post <a href="https://mintaku-blog.net/jamstack/">「Jamstack」アーキテクチャによるWeb開発【Nuxt.js×MicroCMS×Firebase】</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></content:encoded>
					
					<wfw:commentRss>https://mintaku-blog.net/jamstack/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1537</post-id>	</item>
		<item>
		<title>Firebaseで複数のサイトをHostingする方法</title>
		<link>https://mintaku-blog.net/firebase-hosting-multisite/</link>
					<comments>https://mintaku-blog.net/firebase-hosting-multisite/#respond</comments>
		
		<dc:creator><![CDATA[みんたく]]></dc:creator>
		<pubDate>Sat, 02 May 2020 08:01:49 +0000</pubDate>
				<category><![CDATA[GCP]]></category>
		<category><![CDATA[Firebase]]></category>
		<guid isPermaLink="false">https://mintaku-blog.net/?p=1437</guid>

					<description><![CDATA[<p>Firebaseで複数のサイトをHostingし、プロジェクトのリソースを共有する方法をメモしておきます。 1つのFirebaseプロジェクトで複数サイトを …</p>
The post <a href="https://mintaku-blog.net/firebase-hosting-multisite/">Firebaseで複数のサイトをHostingする方法</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></description>
										<content:encoded><![CDATA[<p>Firebaseで複数のサイトをHostingし、プロジェクトのリソースを共有する方法をメモしておきます。</p>
<p>1つのFirebaseプロジェクトで複数サイトを登録することで、プロジェクト内のリソース(AuthenticationやStorageなど)を共有することができます。</p>
<p><span style="font-size: 8px;">参考：<a href="https://firebase.google.com/docs/hosting/multisites" target="_blank" rel="noopener noreferrer">Share project resources across multiple sites</a></span></p>
<h2>前提条件</h2>
<p>前提条件として、既に1つのサイトがFirebase Hostingによって紐付けられデプロイされている状態として進めていきます。</p>
<p>また、プロジェクトを作成し定ない場合は、firebase initを実行して環境設定から行ってください。</p>
<p>また、Firebase CLIがインストールされてない場合は、以下のコマンドからインストールしてください。</p><pre class="crayon-plain-tag">$ npm install -g firebase-tools</pre><p>&nbsp;</p>
<h2>Firebaseにてサイトの追加</h2>
<p>既に1つサイトが存在し、2つ目以降のサイトを登録する場合、Firebase Hosting画面にてサイトを追加する必要があります。</p>
<p>Firebase Hosting画面の詳細設定から「別のサイトを追加」を押下します。</p>
<p><img data-attachment-id="1438" data-permalink="https://mintaku-blog.net/firebase-hosting-multisite/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2020-04-10-15-48-36/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/04/02d858a72edbbe91aa1a82148fb7bb4e.png?fit=824%2C480&amp;ssl=1" data-orig-size="824,480" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="スクリーンショット 2020-04-10 15.48.36" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/04/02d858a72edbbe91aa1a82148fb7bb4e.png?fit=300%2C175&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/04/02d858a72edbbe91aa1a82148fb7bb4e.png?fit=800%2C466&amp;ssl=1" loading="lazy" class="aligncenter size-full wp-image-1438" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/04/02d858a72edbbe91aa1a82148fb7bb4e.png?resize=800%2C466&#038;ssl=1" alt="" width="800" height="466" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/04/02d858a72edbbe91aa1a82148fb7bb4e.png?w=824&amp;ssl=1 824w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/04/02d858a72edbbe91aa1a82148fb7bb4e.png?resize=300%2C175&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/04/02d858a72edbbe91aa1a82148fb7bb4e.png?resize=768%2C447&amp;ssl=1 768w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>&nbsp;</p>
<p>追加したサイト名を入力し、「サイトの追加」を押下します。</p>
<p><img data-attachment-id="1439" data-permalink="https://mintaku-blog.net/firebase-hosting-multisite/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2020-04-10-15-45-08/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/04/9f143dbf8f1821fec575415fa15fc36e.png?fit=2022%2C386&amp;ssl=1" data-orig-size="2022,386" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="スクリーンショット 2020-04-10 15.45.08" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/04/9f143dbf8f1821fec575415fa15fc36e.png?fit=300%2C57&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/04/9f143dbf8f1821fec575415fa15fc36e.png?fit=800%2C152&amp;ssl=1" loading="lazy" class="aligncenter size-large wp-image-1439" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/04/9f143dbf8f1821fec575415fa15fc36e.png?resize=800%2C152&#038;ssl=1" alt="" width="800" height="152" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/04/9f143dbf8f1821fec575415fa15fc36e.png?resize=1024%2C195&amp;ssl=1 1024w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/04/9f143dbf8f1821fec575415fa15fc36e.png?resize=300%2C57&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/04/9f143dbf8f1821fec575415fa15fc36e.png?resize=768%2C147&amp;ssl=1 768w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/04/9f143dbf8f1821fec575415fa15fc36e.png?resize=1536%2C293&amp;ssl=1 1536w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/04/9f143dbf8f1821fec575415fa15fc36e.png?w=2022&amp;ssl=1 2022w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/04/9f143dbf8f1821fec575415fa15fc36e.png?w=1600&amp;ssl=1 1600w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>これで準備完了です。</p>
<p>&nbsp;</p>
<h2>デプロイターゲットの作成</h2>
<p>複数のサイトを登録したら、それぞれにデプロイターゲットを作成する必要があります。</p>
<p>デプロイターゲットを作成し、サイトのホスティングを適用するには、プロジェクトのディレクトリのルートから以下のコマンドを実行します。</p><pre class="crayon-plain-tag">$ firebase target:apply hosting target-name resource-name</pre><p></p>
<ul>
<li>target-name : デプロイ先であるHostingサイトの(自身で定義した)一意の識別子</li>
<li>resource-name : Firebaseプロジェクトにリスト表示されるHostingサイトの名前</li>
</ul>
<p>&nbsp;</p>
<p>例えば、プロジェクトがsampleで先程のサイトの追加にsample-subを追加した場合、既にsample-siteがあり、sample-site2を追加する場合は、以下のコマンドで作成します。</p>
<p>・sample-siteの登録</p>
<p>サイト追加前の既にHostingされているsampleに対して、sample-siteを作成します。</p><pre class="crayon-plain-tag">$ firebase target:apply hosting sample-site sample</pre><p>&nbsp;</p>
<p>・sample-site2の登録</p>
<p>先程、サイト追加したsample-subに対して、新しく追加するsample-site2を作成します。</p><pre class="crayon-plain-tag">$ firebase target:apply hosting sample-site2 sample-sub</pre><p>&nbsp;</p>
<p>上記コマンドで作成が完了すると、.firebasercファイルに以下のように自動で追加されているのが確認できます。</p>
<p>・.firebaserc</p><pre class="crayon-plain-tag">...

  "targets": {
    "sample": {
      "hosting": {
        "sample-site": [
          "sample"
        ],
        "sample-site2": [
          "sample-sub"
        ]
      }
    }
  },

...</pre><p>&nbsp;</p>
<h2>firebase.jsonをそれぞれのターゲットに合わせて編集</h2>
<p>次に、先程作成したターゲットにあわせてfirebase.jsonを編集していきます。これでターゲットに合わせたデプロイが可能となります。</p>
<p>・firebase.json</p><pre class="crayon-plain-tag">{
  "hosting": [
    {
      "target": "sample-site",
      "public": "dist",
      "ignore": [
        "firebase.json",
        "**/.*",
        "**/node_modules/**"
      ],
      "rewrites" : [
        {
          "source": "**",
          "destination": "/index.html"
        }
      ]
    },
    {
      "target": "sample-site2",
      "public": "dist",
      "ignore": [
        "firebase.json",
        "**/.*",
        "**/node_modules/**"
      ],
      "rewrites" : [
        {
          "source": "**",
          "destination": "/index.html"
        }
      ]
    }
  ]
}</pre><p>&nbsp;</p>
<h2>複数サイトのデプロイ方法</h2>
<p>以下のコマンドで、指定したターゲットのリソースのみのデプロイします。</p><pre class="crayon-plain-tag">$ firebase deploy --only hosting:target-name</pre><p>先程の例だと以下のコマンドを実行することで、それぞれをデプロイすることができます。</p><pre class="crayon-plain-tag">$ firebase deploy --only hosting:sample-site</pre><p></p><pre class="crayon-plain-tag">$ firebase deploy --only hosting:sample-site2</pre><p>&nbsp;</p>
<h2>「TypeError: Cannot read property &#8216;deploys&#8217; of undefined」エラーで、デプロイが失敗する</h2>
<p>「TypeError: Cannot read property &#8216;deploys&#8217; of undefined」エラーで、デプロイが失敗する場合がありましたが、以下を参考にして解決しました。。</p>
<p><span style="font-size: 8px;">参考：<a href="https://github.com/firebase/firebase-tools/issues/902" target="_blank" rel="noopener noreferrer">Hosting deploy fails with multiple sites in the project · Issue #902 · firebase/firebase-tools</a></span></p>
<p>複数サイトのプロジェクトが別々の場合に発生しました。</p>
<p>登録する複数サイトが別々のプロジェクトであっても、同じFirebasenoプロジェクト内であれば、.firebaercとfirebase.jsonを共通に持っておく必要があります。</p>
<p>それぞれ別のプロジェクトだからそのプロジェクトだけのデプロイターゲットを作成するのではなく、FirebaseプロジェクトのHosting全てを設定ファイルを記載することで解決できました。</p>The post <a href="https://mintaku-blog.net/firebase-hosting-multisite/">Firebaseで複数のサイトをHostingする方法</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></content:encoded>
					
					<wfw:commentRss>https://mintaku-blog.net/firebase-hosting-multisite/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1437</post-id>	</item>
		<item>
		<title>【GCP】GAEでRailsのステージング環境と本番環境を構築する方法</title>
		<link>https://mintaku-blog.net/gae-rails-env/</link>
					<comments>https://mintaku-blog.net/gae-rails-env/#respond</comments>
		
		<dc:creator><![CDATA[みんたく]]></dc:creator>
		<pubDate>Mon, 20 Apr 2020 14:08:00 +0000</pubDate>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[GCP]]></category>
		<guid isPermaLink="false">https://mintaku-blog.net/?p=1426</guid>

					<description><![CDATA[<p>Google App EngineでRailsのステージング環境と本番環境を構築したので、その方法をメモしておきます。 database.ymlの編集 da …</p>
The post <a href="https://mintaku-blog.net/gae-rails-env/">【GCP】GAEでRailsのステージング環境と本番環境を構築する方法</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></description>
										<content:encoded><![CDATA[<p>Google App EngineでRailsのステージング環境と本番環境を構築したので、その方法をメモしておきます。</p>
<h2>database.ymlの編集</h2>
<p>database.ymlにステージング環境用と本番環境用のDB情報をそれぞれ追加します。</p>
<p>・database.yml</p><pre class="crayon-plain-tag">...

staging:
  adapter: mysql2
  encoding: utf8
  pool: 5
  timeout: 5000
  username: sample_stg
  password: sample_stg_pass
  database: sample_stg
  socket: /cloudsql/sample_stg:asia-northeast1:sample_stg

production:
  adapter: mysql2
  encoding: utf8
  pool: 5
  timeout: 5000
  username: sample_prod
  password: sample_prod_pass
  database: sample_prod
  socket: /cloudsql/sample_prod:asia-northeast1:sample_prod

...</pre><p>&nbsp;</p>
<h2>app.yamlの編集</h2>
<p>GAEにデプロイするステージング環境と本番環境のapp.yamlファイルを作成します。</p>
<p>今回はGAEのスタンダード環境で構築しています。「RAILS_ENV=」で環境を指定します。</p>
<p>また、env_variablesで環境変数を指定することもできます。</p>
<p>・app-staging.yaml</p><pre class="crayon-plain-tag">service: api--staging
runtime: ruby25
entrypoint: RAILS_ENV=staging bundle exec rails s -e staging
env_variables:
  SAMPLE_API_KEY: 'SAMPLE_STAGING_API_KEY'</pre><p>&nbsp;</p>
<p>・app-production.yaml</p><pre class="crayon-plain-tag">service: api--production
runtime: ruby25
entrypoint: RAILS_ENV=production bundle exec rails s -e production
env_variables:
  SAMPLE_API_KEY: 'SAMPLE_PRODUCTION_API_KEY'</pre><p>&nbsp;</p>
<h2>dispatch.yamlの作成</h2>
<p>dispatch.yamlを作成し、ドメインとサービスを紐づけます。これでGAEのサービスにデプロイした際に、指定したURLに割り当てることができます。</p>
<p>・dispatch.yaml</p><pre class="crayon-plain-tag">dispatch:
- url: "*stg.sample.com/*"
service: api--staging
- url: "*sample.com/*"
service: api--production</pre><p>dispatch.yamlが作成できたら、以下のコマンドでデプロイします。</p><pre class="crayon-plain-tag">$ gcloud app deploy dispatch.yaml</pre><p>&nbsp;</p>
<h2>Railsプロジェクトをステージング環境と本番環境にそれぞれデプロイ</h2>
<p>ここまで準備が完了したら、実際にRailsプロジェクトをそれぞれの環境にデプロイします。</p>
<h3>■ステージング環境</h3>
<p>デプロイする前にRailsアセットをコンパイルします。</p><pre class="crayon-plain-tag">$ RAILS_ENV=staging bundle exec rails assets:precompile</pre><p>app-staging.yamlを指定してデプロイします。</p><pre class="crayon-plain-tag">$ gcloud app deploy app-staging.yaml</pre><p>&nbsp;</p>
<p>■本番環境</p>
<p>ステージング環境と同様、デプロイする前にコンパイルします。</p><pre class="crayon-plain-tag">$ RAILS_ENV=production bundle exec rails assets:precompile</pre><p>app-production.yamlを指定してデプロイします。</p><pre class="crayon-plain-tag">$ gcloud app deploy app-production.yaml</pre><p>デプロイする際に、target serviceがそれぞれの環境が選択できているか確認しておきましょう。</p><pre class="crayon-plain-tag">target service: [api--staging]</pre><p>&nbsp;</p>
<h2>マイグレーション・シードの実行</h2>
<p>マイグレーションとシードもそれぞれの環境に合わせて行いますappengineを使ってマイグレーションを実行します。</p>
<p>シード処理は時間がかかることがあるので、デフォルトの10分を30分まで伸ばしています。</p>
<h3>■ステージング環境</h3>
<p>マイグレーション処理</p><pre class="crayon-plain-tag">$ bundle exec rake appengine:exec GAE_SERVICE=api--staging -- bundle exec rails db:migrate RAILS_ENV=staging</pre><p>シード処理</p><pre class="crayon-plain-tag">$ bundle exec rake appengine:exec GAE_SERVICE=api--staging GAE_TIMEOUT=30m -- bundle exec rails db:seed RAILS_ENV=staging</pre><p>&nbsp;</p>
<h3>■本番環境</h3>
<p>マイグレーション処理</p><pre class="crayon-plain-tag">$ bundle exec rake appengine:exec GAE_SERVICE=api--production -- bundle exec rails db:migrate RAILS_ENV=production</pre><p>シード処理</p><pre class="crayon-plain-tag">$ bundle exec rake appengine:exec GAE_SERVICE=api--production GAE_TIMEOUT=30m -- bundle exec rails db:seed RAILS_ENV=production</pre><p>&nbsp;</p>
<h2>① ハマりポイント「Errno::EROFS: Read-only file system @ rb_sysopen &#8211; /srv/db/schema.rb」</h2>
<p>追加のマイグレーションファイルを作成し、実行するときにエラー発生。schema.rbが読み取り専用のため(スタンダード環境だから？)、実行できずにハマる。。</p><pre class="crayon-plain-tag">$ bundle exec rake appengine:exec GAE_SERVICE=api--staging -- bundle exec rails db:migrate</pre><p></p><pre class="crayon-plain-tag">[STDERR] rails aborted!
[STDERR] Errno::EROFS: Read-only file system @ rb_sysopen - /srv/db/schema.rb</pre><p>&nbsp;</p>
<p>解決策として、作成したマイグレーションファイルのバージョンを指定することで実行できました。</p><pre class="crayon-plain-tag">$ bundle exec rake appengine:exec GAE_SERVICE=api--staging -- bundle exec rails db:migrate:up VERSION=20200401000000</pre><p></p><pre class="crayon-plain-tag">[STDOUT] == 20200401000000 AddColumnTests: migrating ===================
[STDOUT] -- add_column(:tests, :test_id, :string, {:null=&gt;true, :after=&gt;:sample_id})
[STDOUT] -&gt; 0.0461s
[STDOUT] == 20200401000000 AddColumnTests: migrated (0.0462s) ==========
[STDOUT]

EXIT STATUS: 0</pre><p>&nbsp;</p>
<h2>②ハマりポイント「Cannot run migrations because another migration process is currently running.」</h2>
<p>マイグレーション対象のDBに接続した状態で、実行するとエラー発生。</p><pre class="crayon-plain-tag">[STDERR] rails aborted!
[STDERR] ActiveRecord::ConcurrentMigrationError:
[STDERR]
[STDERR] Cannot run migrations because another migration process is currently running.</pre><p>&nbsp;</p>
<p>DBにログインし、以下のコマンドで処理中のプロセスの一覧を表示し、該当のプロセスを終了させて再度実行すれば通ります。</p><pre class="crayon-plain-tag">$ SHOW PROCESSLIST</pre><p>&nbsp;</p>
<p>以上、GAEでRailsのステージング環境と本番環境を構築する方法を紹介しました。</p>The post <a href="https://mintaku-blog.net/gae-rails-env/">【GCP】GAEでRailsのステージング環境と本番環境を構築する方法</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></content:encoded>
					
					<wfw:commentRss>https://mintaku-blog.net/gae-rails-env/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1426</post-id>	</item>
		<item>
		<title>Cloud SQLをローカルのDBeaver(クライアントツール)にプロキシを使用して接続する方法</title>
		<link>https://mintaku-blog.net/cloudsql-dbeaver/</link>
					<comments>https://mintaku-blog.net/cloudsql-dbeaver/#respond</comments>
		
		<dc:creator><![CDATA[みんたく]]></dc:creator>
		<pubDate>Wed, 25 Mar 2020 14:07:19 +0000</pubDate>
				<category><![CDATA[GCP]]></category>
		<category><![CDATA[環境構築]]></category>
		<guid isPermaLink="false">https://mintaku-blog.net/?p=1394</guid>

					<description><![CDATA[<p>Cloud SQLをローカルのDBeaver(クライアントツール)に接続する方法を紹介します。今回はクライアントツールとしてDBeaverを選択していますが …</p>
The post <a href="https://mintaku-blog.net/cloudsql-dbeaver/">Cloud SQLをローカルのDBeaver(クライアントツール)にプロキシを使用して接続する方法</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></description>
										<content:encoded><![CDATA[<p>Cloud SQLをローカルのDBeaver(クライアントツール)に接続する方法を紹介します。今回はクライアントツールとしてDBeaverを選択していますが、他のツールでも問題ありません。</p>
<p><span style="font-size: 8px;">参考：<a href="https://cloud.google.com/sql/docs/mysql/connect-external-app?hl=ja" target="_blank" rel="noopener noreferrer">外部アプリケーションから Cloud SQL に接続する | Cloud SQL for MySQL</a></span></p>
<p>&nbsp;</p>
<h2>前提条件</h2>
<p>Cloud SQLをローカルのクライアントツールに接続する前提として以下が当てはまっていることが条件です。</p>
<ul>
<li>Cloud SQL AdminAPIが有効化されていること</li>
<li>Cloud SQLのインスタンスが作成されていること</li>
<li>Cloud SQLにDB・ユーザが作成されていること</li>
</ul>
<p>&nbsp;</p>
<h2>プロキシクライアントのインストール</h2>
<p>ローカルから認証に必要なプロキシクライアントをインストールします。</p>
<p>Macの場合は以下のコマンドでダウンロードします。他のOSからのコマンドは以下の公式を参考にしてください。</p>
<p><span style="font-size: 8px;">参考：<a href="https://cloud.google.com/sql/docs/mysql/connect-external-app?hl=ja#install" target="_blank" rel="noopener noreferrer">ローカルマシンにプロキシ クライアントをインストールする</a></span></p><pre class="crayon-plain-tag">$ curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.amd64</pre><p>&nbsp;</p>
<p>プロキシの実行権限を付与します。</p><pre class="crayon-plain-tag">$ chmod +x cloud_sql_proxy</pre><p>&nbsp;</p>
<h2>サービスアカウントの作成</h2>
<p>次にローカルからCloud SQLに接続する際に、認証で必要となるサービスアカウントを作成します。</p>
<p>GCPの「IAMと管理」からサービスアカウントを選択します。「サービスアカウントを作成」を押下します。</p>
<p><img data-attachment-id="1395" data-permalink="https://mintaku-blog.net/cloudsql-dbeaver/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2020-03-10-19-52-38/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/734873cdf67bcd86aacb79ea1a3b1098.png?fit=1532%2C92&amp;ssl=1" data-orig-size="1532,92" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="スクリーンショット 2020-03-10 19.52.38" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/734873cdf67bcd86aacb79ea1a3b1098.png?fit=300%2C18&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/734873cdf67bcd86aacb79ea1a3b1098.png?fit=800%2C48&amp;ssl=1" loading="lazy" class="aligncenter size-large wp-image-1395" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/734873cdf67bcd86aacb79ea1a3b1098.png?resize=800%2C48&#038;ssl=1" alt="" width="800" height="48" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/734873cdf67bcd86aacb79ea1a3b1098.png?resize=1024%2C61&amp;ssl=1 1024w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/734873cdf67bcd86aacb79ea1a3b1098.png?resize=300%2C18&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/734873cdf67bcd86aacb79ea1a3b1098.png?resize=768%2C46&amp;ssl=1 768w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/734873cdf67bcd86aacb79ea1a3b1098.png?w=1532&amp;ssl=1 1532w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>&nbsp;</p>
<p>以下の項目を入力し、作成を押下します。</p>
<ul>
<li>サービスアカウント名</li>
<li>サービスアカウントID</li>
<li>サービスアカウントの説明</li>
</ul>
<p><img data-attachment-id="1396" data-permalink="https://mintaku-blog.net/cloudsql-dbeaver/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2020-03-10-19-54-17/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/4f48f633c12fdb892d6c9b1a73515dc5.png?fit=1756%2C1052&amp;ssl=1" data-orig-size="1756,1052" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="スクリーンショット 2020-03-10 19.54.17" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/4f48f633c12fdb892d6c9b1a73515dc5.png?fit=300%2C180&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/4f48f633c12fdb892d6c9b1a73515dc5.png?fit=800%2C479&amp;ssl=1" loading="lazy" class="aligncenter size-large wp-image-1396" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/4f48f633c12fdb892d6c9b1a73515dc5.png?resize=800%2C479&#038;ssl=1" alt="" width="800" height="479" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/4f48f633c12fdb892d6c9b1a73515dc5.png?resize=1024%2C613&amp;ssl=1 1024w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/4f48f633c12fdb892d6c9b1a73515dc5.png?resize=300%2C180&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/4f48f633c12fdb892d6c9b1a73515dc5.png?resize=768%2C460&amp;ssl=1 768w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/4f48f633c12fdb892d6c9b1a73515dc5.png?resize=1536%2C920&amp;ssl=1 1536w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/4f48f633c12fdb892d6c9b1a73515dc5.png?w=1756&amp;ssl=1 1756w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/4f48f633c12fdb892d6c9b1a73515dc5.png?w=1600&amp;ssl=1 1600w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>&nbsp;</p>
<p>役割は「Cloud SQL クライアント」を選択し、続行を押下します。</p>
<p><img data-attachment-id="1397" data-permalink="https://mintaku-blog.net/cloudsql-dbeaver/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2020-03-10-19-54-42/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/9f5a434a808c1bf5a515505103e138f3.png?fit=1696%2C922&amp;ssl=1" data-orig-size="1696,922" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="スクリーンショット 2020-03-10 19.54.42" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/9f5a434a808c1bf5a515505103e138f3.png?fit=300%2C163&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/9f5a434a808c1bf5a515505103e138f3.png?fit=800%2C435&amp;ssl=1" loading="lazy" class="aligncenter size-large wp-image-1397" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/9f5a434a808c1bf5a515505103e138f3.png?resize=800%2C435&#038;ssl=1" alt="" width="800" height="435" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/9f5a434a808c1bf5a515505103e138f3.png?resize=1024%2C557&amp;ssl=1 1024w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/9f5a434a808c1bf5a515505103e138f3.png?resize=300%2C163&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/9f5a434a808c1bf5a515505103e138f3.png?resize=768%2C418&amp;ssl=1 768w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/9f5a434a808c1bf5a515505103e138f3.png?resize=1536%2C835&amp;ssl=1 1536w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/9f5a434a808c1bf5a515505103e138f3.png?w=1696&amp;ssl=1 1696w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/9f5a434a808c1bf5a515505103e138f3.png?w=1600&amp;ssl=1 1600w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>&nbsp;</p>
<p>「キーを作成」を押下します。</p>
<p><img data-attachment-id="1398" data-permalink="https://mintaku-blog.net/cloudsql-dbeaver/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2020-03-10-19-55-14/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/3d00140db364f1bbab62c362bea75143.png?fit=1582%2C1310&amp;ssl=1" data-orig-size="1582,1310" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="スクリーンショット 2020-03-10 19.55.14" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/3d00140db364f1bbab62c362bea75143.png?fit=300%2C248&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/3d00140db364f1bbab62c362bea75143.png?fit=800%2C663&amp;ssl=1" loading="lazy" class="aligncenter size-large wp-image-1398" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/3d00140db364f1bbab62c362bea75143.png?resize=800%2C663&#038;ssl=1" alt="" width="800" height="663" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/3d00140db364f1bbab62c362bea75143.png?resize=1024%2C848&amp;ssl=1 1024w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/3d00140db364f1bbab62c362bea75143.png?resize=300%2C248&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/3d00140db364f1bbab62c362bea75143.png?resize=768%2C636&amp;ssl=1 768w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/3d00140db364f1bbab62c362bea75143.png?resize=1536%2C1272&amp;ssl=1 1536w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/3d00140db364f1bbab62c362bea75143.png?w=1582&amp;ssl=1 1582w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>&nbsp;</p>
<p>キーのタイプは「JSON」を選択し、作成を押下します。すると認証ファイルがダウンロードされるので、保存します。今回は、sample-key.jsonというファイル名で保存します。</p>
<p><img data-attachment-id="1399" data-permalink="https://mintaku-blog.net/cloudsql-dbeaver/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2020-03-10-20-12-47/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/3c708e8a2efe41ecd9f2bc5da417f915.png?fit=1030%2C642&amp;ssl=1" data-orig-size="1030,642" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="スクリーンショット 2020-03-10 20.12.47" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/3c708e8a2efe41ecd9f2bc5da417f915.png?fit=300%2C187&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/3c708e8a2efe41ecd9f2bc5da417f915.png?fit=800%2C498&amp;ssl=1" loading="lazy" class="aligncenter size-large wp-image-1399" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/3c708e8a2efe41ecd9f2bc5da417f915.png?resize=800%2C498&#038;ssl=1" alt="" width="800" height="498" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/3c708e8a2efe41ecd9f2bc5da417f915.png?resize=1024%2C638&amp;ssl=1 1024w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/3c708e8a2efe41ecd9f2bc5da417f915.png?resize=300%2C187&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/3c708e8a2efe41ecd9f2bc5da417f915.png?resize=768%2C479&amp;ssl=1 768w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/3c708e8a2efe41ecd9f2bc5da417f915.png?w=1030&amp;ssl=1 1030w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>&nbsp;</p>
<h2>プロキシの起動</h2>
<p>先ほどインストールしたプロキシを起動します。</p>
<ul>
<li>instances : インスタンス接続名</li>
<li>tcp : 13306</li>
<li>credential_file : 先ほど保存した認証ファイル</li>
</ul>
<p></p><pre class="crayon-plain-tag">$ ./cloud_sql_proxy -instances=&lt;インスタンス接続名&gt;=tcp:13306 -credential_file=sample-key.json</pre><p>&nbsp;</p>
<p>起動し以下のように「Ready for new connections」が表示され、正常に起動できていることを確認します。</p><pre class="crayon-plain-tag">2020/03/10 19:56:57 using credential file for authentication; email=sample@&lt;project_id&gt;.iam.gserviceaccount.com
2020/03/10 19:56:58 Listening on 127.0.0.1:13306 for &lt;インスタンス接続名&gt;
2020/03/10 19:56:58 Ready for new connections</pre><p>&nbsp;</p>
<h2>DBeaverに接続</h2>
<p>いよいよDBeaver(クライアントツール)に接続します。</p>
<p>以下を入力して接続完了です。</p>
<ul>
<li>Server Host : ローカルループバックアドレス</li>
<li>Port : 先ほど指定したポート</li>
<li>Database : Cloud SQLで作成したDB名</li>
<li>User name : Cloud SQLで作成したユーザ名</li>
<li>Password : Cloud SQLで作成したユーザのパスワード</li>
</ul>
<p><img data-attachment-id="1400" data-permalink="https://mintaku-blog.net/cloudsql-dbeaver/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2020-03-10-20-14-22/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/104de0c7056387e6997c6e26bc250439.png?fit=2110%2C1354&amp;ssl=1" data-orig-size="2110,1354" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="スクリーンショット 2020-03-10 20.14.22" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/104de0c7056387e6997c6e26bc250439.png?fit=300%2C193&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/104de0c7056387e6997c6e26bc250439.png?fit=800%2C513&amp;ssl=1" loading="lazy" class="aligncenter size-large wp-image-1400" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/104de0c7056387e6997c6e26bc250439.png?resize=800%2C513&#038;ssl=1" alt="" width="800" height="513" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/104de0c7056387e6997c6e26bc250439.png?resize=1024%2C657&amp;ssl=1 1024w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/104de0c7056387e6997c6e26bc250439.png?resize=300%2C193&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/104de0c7056387e6997c6e26bc250439.png?resize=768%2C493&amp;ssl=1 768w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/104de0c7056387e6997c6e26bc250439.png?resize=1536%2C986&amp;ssl=1 1536w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/104de0c7056387e6997c6e26bc250439.png?resize=2048%2C1314&amp;ssl=1 2048w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2020/03/104de0c7056387e6997c6e26bc250439.png?w=1600&amp;ssl=1 1600w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>&nbsp;</p>
<h2>接続時に「Communications link failure」エラー</h2>
<p>最後のクライアントからの接続時に以下のエラーでハマりました。</p><pre class="crayon-plain-tag">Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.</pre><p>&nbsp;</p>
<p>ログを確認すると以下のエラーが表示されていました。調べてみるとどうやら接続の問題のようですが、特に問題なさそう。</p><pre class="crayon-plain-tag">[Note] Aborted connection xxx to db: 'sample' user: 'sample' host: 'cloudsqlproxy~xxxxx' (Got an error reading communication packets)</pre><p>&nbsp;</p>
<p>タイムアウトやbuffer_sizeを増やしたり、あれこれ設定を変更するが解決できず。。</p>
<p>結局、原因は会社で使用しているWiFiでした。試しにWiFiをオフにして、テザリングを使ってみると、問題なく接続できました。</p>The post <a href="https://mintaku-blog.net/cloudsql-dbeaver/">Cloud SQLをローカルのDBeaver(クライアントツール)にプロキシを使用して接続する方法</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></content:encoded>
					
					<wfw:commentRss>https://mintaku-blog.net/cloudsql-dbeaver/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1394</post-id>	</item>
		<item>
		<title>Google App EngineのRuby 2.5 StandardでRails環境構築</title>
		<link>https://mintaku-blog.net/gae-rails/</link>
					<comments>https://mintaku-blog.net/gae-rails/#respond</comments>
		
		<dc:creator><![CDATA[みんたく]]></dc:creator>
		<pubDate>Wed, 19 Feb 2020 13:08:38 +0000</pubDate>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[GCP]]></category>
		<category><![CDATA[環境構築]]></category>
		<guid isPermaLink="false">https://mintaku-blog.net/?p=1338</guid>

					<description><![CDATA[<p>Google App EngineのRuby 2.5 StandardでRails環境構築する方法とCloud SQLのMySQLとの接続方法について紹介し …</p>
The post <a href="https://mintaku-blog.net/gae-rails/">Google App EngineのRuby 2.5 StandardでRails環境構築</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></description>
										<content:encoded><![CDATA[<p>Google App EngineのRuby 2.5 StandardでRails環境構築する方法とCloud SQLのMySQLとの接続方法について紹介します。</p>
<p>基本的には以下の公式を参考に環境構築しています。</p>
<ul>
<li><a href="https://cloud.google.com/ruby/rails/appengine?hl=ja" target="_blank" rel="noopener noreferrer">Running Rails 5 on App Engine flexible environment | Ruby</a></li>
<li><a href="https://cloud.google.com/ruby/rails/using-cloudsql-mysql?hl=ja" target="_blank" rel="noopener noreferrer">Using Cloud SQL for MySQL with Rails 5 | Ruby</a></li>
</ul>
<h2>前提条件</h2>
<p>デプロイするRailsプロジェクトが以下に当てはまっていることが前提条件です。</p>
<ul>
<li>Ruby バージョン2.3.4以降をインストール</li>
<li>Rails 5 gem をインストール</li>
<li>Bundler gem をインストール</li>
</ul>
<p>&nbsp;</p>
<h2>必要なAPIを有効化</h2>
<p>データストア、Pub / Sub、Cloud Storage JSON、Stackdriver Logging、およびGoogle+必要なAPIを有効にします。</p>

<div class="ys-blog-card">
	<div class="ys-blog-card__container">
				<div class="ys-blog-card__text">
			<p class="ys-blog-card__title">
				<a class="ys-blog-card__link" href="https://console.cloud.google.com/flows/enableapi?apiid=datastore.googleapis.com,pubsub,storage_api,logging,plus&_ga=2.48516846.936357722.1581502708-977931022.1573203289">Google Cloud Platform</a>
			</p>
										<div class="ys-blog-card__domain">console.cloud.google.com</div>
					</div>
	</div>
</div>

<p>&nbsp;</p>
<h2>app.yamlの作成</h2>
<p>GAEにデプロイするRailsアプリのディレクトリ直下にapp.yamlを作成します。</p>
<p>今回はスタンダード環境なので「env: flex」はコメントアウトしておきます。またapp.yamlに環境変数を書くことでGAEに環境変数を渡せます。</p>
<p>secret keyは以下のコマンドで確認できます。</p><pre class="crayon-plain-tag">$ bundle exec rails secret</pre><p>・app.yaml</p><pre class="crayon-plain-tag">entrypoint: bundle exec rackup --port $PORT
runtime: ruby25
# env: flex
env_variables:
    SECRET_KEY_BASE: &lt; Your secret key&gt;</pre><p>GAEにデプロイしたアプリはDocker上で動くためDockerfileがプロジェクト直下にあるとruntime rubyでデプロイができません。</p>
<p>runtime rubyでデプロイする場合は、DockerfileをDockerfile-devなどに置き換えておきましょう。</p>
<p>&nbsp;</p>
<h2>.gcloudignoreの作成</h2>
<p>デプロイしないファイルを指定するために.gcloudignoreファイルを作成します。</p>
<p>・.gcloudignore</p><pre class="crayon-plain-tag">.gcloudignore
#!include:.gitignore
.git
.gitignore

!/public/assets</pre><p>&nbsp;</p>
<h2>MySQL用Cloud SQLをセットアップ</h2>
<p>RailsアプリでCloud SQLを使用するために、mysql2とappenginegemをGemfileファイルに追加します</p><pre class="crayon-plain-tag">$ bundle add mysql2
$ bundle add appengine</pre><p>以下のコマンドでインスタンス接続名を取得できます。<br />
gcloud sql instances describe &lt; インスタンス名 &gt;</p>
<p>・database.yml</p><pre class="crayon-plain-tag">production:
    adapter: mysql2
    encoding: utf8
    pool: 5
    timeout: 5000
    username: &lt; username &gt;
    password: &lt; password &gt;
    database: &lt; database &gt;
    socket: /cloudsql/&lt; インスタンス接続名 &gt;</pre><p>&nbsp;</p>
<h2>GAEにデプロイ</h2>
<p>以下のコマンドで、GAEアプリを作成します。</p><pre class="crayon-plain-tag">$ gcloud app create</pre><p>デプロイする前に、Railsアセットをプリコンパイルします。</p><pre class="crayon-plain-tag">$ bundle exec bin/rails assets:precompile</pre><p>アセットのコンパイルが完了したらGAEにデプロイします。</p><pre class="crayon-plain-tag">$ gcloud app deploy</pre><p>&nbsp;</p>
<h2>マイグレーションでテーブル作成</h2>
<p>以下のコマンドでプロジェクトを一覧表示できます。アプリのデプロイに使用するプロジェクトを見つけ、プロジェクト番号をコピーします。</p><pre class="crayon-plain-tag">$ gcloud projects list</pre><p>roles/editorデータベース移行を実行するロールのプロジェクトIAMポリシーに新しいメンバーを追加します。</p><pre class="crayon-plain-tag">$ gcloud projects add-iam-policy-binding &lt; YOUR-PROJECT-ID &gt; --member=serviceAccount: &lt; PROJECT_NUMBER &gt; @cloudbuild.gserviceaccount.com --role=roles/editor</pre><p>先ほど追加したappengineを使用して、Cloud SQL上でのマイグレーションを実行します。</p><pre class="crayon-plain-tag">$ bundle exec rake appengine:exec -- bundle exec rake db:migrate</pre><p>Cloud SQL画面の「Cloud Shellを使用して接続」から以下のコマンドで接続し、実際にテーブルが作成されたか確認してみましょう。</p><pre class="crayon-plain-tag">$ gcloud sql connect &lt; インスタンス名 &gt; --user=&lt; username &gt; --quiet</pre><p>&nbsp;</p>
<h2>以降のデプロイ</h2>
<p>以降、ソースを更新して再度デプロイする場合は以下のコマンドで実行する流れになります。</p><pre class="crayon-plain-tag">$ bundle exec bin/rails assets:precompile
$ gcloud app deploy
$ bundle exec rake appengine:exec -- bundle exec rake db:migrate</pre><p>&nbsp;</p>
<h2>ハマりポイント</h2>
<h3>① コンパイル時にエラー</h3>
<p>コンパイル時に以下のエラーが発生。</p><pre class="crayon-plain-tag">Note: Google::Cloud::Logging is disabled because it failed to authorize with the service.
Note: Google::Cloud::Debugger is disabled because it failed to authorize with the service.
Note: Google::Cloud::ErrorReporting is disabled because it failed to authorize with the service.
Note: Google::Cloud::Trace is disabled because it failed to authorize with the service.</pre><p>develop環境では使用しないようfalseにすることで解決しました。</p>
<p>・development.rb</p><pre class="crayon-plain-tag">config.google_cloud.use_logging = false
config.google_cloud.use_debugger = false
config.google_cloud.use_error_reporting = false
config.google_cloud.use_trace = false</pre><p>&nbsp;</p>
<h3>② MySQLに接続できない</h3>
<p>以下のエラーによりCloud SQLのMySQLに接続できずハマり。。</p><pre class="crayon-plain-tag">[STDERR] rake aborted!
[STDERR] Mysql2::Error::ConnectionError: Unknown MySQL server host '/cloudsql/&lt; インスタンス接続名 &gt;' (2)</pre><p>公式ではdatabase.yamlの「/cloudsql/&lt; インスタンス接続名 &gt;」の箇所がhostとなっていたため、hostで書いていたのですが、socketに変更することで解決しました。。</p>
<p>参考：</p>

<div class="ys-blog-card">
	<div class="ys-blog-card__container">
					<figure class="ys-blog-card__image">
				<img src="https://opengraph.githubassets.com/124e3ac85ab876ecb3ee9a13f260488c6765a97302a572b589bb25a41b6144ed/GoogleCloudPlatform/ruby-docs-samples" alt="">			</figure>
				<div class="ys-blog-card__text">
			<p class="ys-blog-card__title">
				<a class="ys-blog-card__link" href="https://github.com/GoogleCloudPlatform/ruby-docs-samples/blob/0a6e898a1acd140ca04c63c7b68da1468acb4082/appengine/rails-cloudsql-postgres/config/database.yml">ruby-docs-samples/appengine/rails-cloudsql-postgres/config/database.yml at 0a6e898a1acd140ca04c63c7b68da1468acb4082 · GoogleCloudPlatform/ruby-docs-samples · GitHub</a>
			</p>
							<div class="ys-blog-card__dscr">
					Ruby samples for Google Cloud Platform p&hellip;				</div>
										<div class="ys-blog-card__domain">github.com</div>
					</div>
	</div>
</div>

<p>・修正前</p><pre class="crayon-plain-tag">production:
    adapter: mysql2
    encoding: utf8
    pool: 5
    timeout: 5000
    username: &lt; username &gt;
    password: &lt; password &gt;
    database: &lt; database &gt;
    host: /cloudsql/&lt; インスタンス接続名 &gt;</pre><p>・修正後</p><pre class="crayon-plain-tag">production:
    adapter: mysql2
    encoding: utf8
    pool: 5
    timeout: 5000
    username: &lt; username &gt;
    password: &lt; password &gt;
    database: &lt; database &gt;
    socket: /cloudsql/&lt; インスタンス接続名 &gt;</pre><p>&nbsp;</p>
<h3>③ GAEのデフォルトTime Outが10分なためSeedが完了しない</h3>
<p>GAEのデフォルトタイムアウトが10mのため、Seedが完了せず途中で終了してしまう。。</p><pre class="crayon-plain-tag">TIMEOUT: 10m</pre><p>GAE_TIMEOUTオプションでタイムアウトを伸ばすことができました。1h23m45sの形式で指定できます。</p><pre class="crayon-plain-tag">bundle exec rake appengine:exec GAE_TIMEOUT=30m -- bundle exec rake db:seed</pre><p>参考：</p>

<div class="ys-blog-card">
	<div class="ys-blog-card__container">
					<figure class="ys-blog-card__image">
				<img src="https://opengraph.githubassets.com/52b5158113b4bc826f0dc7f99a3c78803f2eb2dc31ffe6537b7bd59dcc946bd6/GoogleCloudPlatform/appengine-ruby/issues/26" alt="">			</figure>
				<div class="ys-blog-card__text">
			<p class="ys-blog-card__title">
				<a class="ys-blog-card__link" href="https://github.com/GoogleCloudPlatform/appengine-ruby/issues/26">How to set the value of timeout? · Issue #26 · GoogleCloudPlatform/appengine-ruby · GitHub</a>
			</p>
							<div class="ys-blog-card__dscr">
					Could not find this documented anywhere &hellip;				</div>
										<div class="ys-blog-card__domain">github.com</div>
					</div>
	</div>
</div>

<p>以上、Google App EngineのRuby 2.5 StandardでRails環境構築する方法とCloud SQLのMySQLとの接続方法でした。</p>The post <a href="https://mintaku-blog.net/gae-rails/">Google App EngineのRuby 2.5 StandardでRails環境構築</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></content:encoded>
					
					<wfw:commentRss>https://mintaku-blog.net/gae-rails/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1338</post-id>	</item>
	</channel>
</rss>
