20220108のdockerに関する記事は14件です。

Winodws10のubuntuにてDockerでReactNative

教材 ありがとうございます。とても参考になりました。 準備 Winsows10 Ubuntu インストール済み 手順 ほぼ教材にさせていただきました参考サイト通りです。 一点だけ yarn global add create-react-app が何故か通らなかったので代わりに npm install -g create-react-app を実行しました。 yarn yarn start で無事ローカルのブラウザでReactの画面を確認できました。 Dockerメモ sudo service docker start 起動 sudo docker info 起動確認 sudo docker ps 確認 コンテナから抜けるとき Winodws上のDockerからSTOPする またはexitする 終わりに 勉強のためにguthubにpushしました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerでSORACOM Arcを使う (Ubuntu 20.04)

任意の IP ネットワークからSORACOMプラットフォームへ接続できるSORACOM Arc。 Dockerで動かすときに少し詰まったので共有です。 環境 Windows 11 WSL2 (Ubuntu 20.04) CPU Architecture: x86_64 Docker 20.10.11 Dockerイメージを取得 今回はUbuntu 20.04を使用しました。 $ docker pull ubuntu:20.04 公式ドキュメントによると、サポート対象は次の通りです。 以下のプラットフォームをサポートします。 Linux amd64 Ubuntu 20.04.2 LTS Linux arm (Raspberry Pi 32-bit) Raspberry Pi OS 2021-05-07 Ubuntu 20.04.2 LTS また、テストと開発用途として以下のプラットフォームで動作します。サポートはありません。 macOS Big Sur 以降 コンテナの作成&起動 $ docker run --cap-add NET_ADMIN -it ubuntu:20.04 --cap-add とはデフォルトで無効化されている capability を有効化するためのオプションです。 SORACOM Arcのトンネルを作成するにはNET_ADMINの権限が必要です(参考)。 capabilityとは? Linuxにはこのような場合に使える,rootが持っている絶対的な権限を細かく分け,必要な権限だけを与える仕組みが存在します。これがケーパビリティ(capability)です。 引用元:第42回 Linuxカーネルのケーパビリティ[1]LXCで学ぶコンテナ入門 -軽量仮想化環境を実現する技術  パッケージのインストール 取得したDockerイメージはのちに使うパッケージがいくつかインストールされていないので、インストールしておきましょう。 $ apt update && apt install -y wget iputils-ping net-tools /dev/net/tunの作成 $ mkdir -p /dev/net $ mknod /dev/net/tun c 10 200 $ chmod 666 /dev/net/tun soratun によるバーチャル SIM/Subscriber のブートストラップ 公式ドキュメントの通りにやるとうまくいきました。 ただし、ステップ4の soratun --config /path/to/arc.json up を実行するとセッションが開始されます。これは生かしておく必要があるので、別のターミナルで $ docker exec -it YOUR_CONTAINER_ID /bin/bash をして $ ping -c 3 pong.soracom.io をすることで疎通確認ができます。 Dockerfile いずれ書きます そんなに複雑じゃないはず。 後記 soratunって名前かわいいな、と思ったら sora-com tun-nelのことなんですね。 参考サイト soratun で SORACOM API の認証キーを使用してバーチャル SIM/Subscriber をブートストラップする SORACOM ArcとDockerで作る仮想デバイス Docker内でTUN/TAPを使うときのメモ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

(Nuxt.js)共通部分をcomponent化して使い回す

はじめに Nuxt.js Rails Dockerでプロジェクト進めてる時に 共通部分をcomponents化してメンテ性、可読性の向上を行なったのでその備忘録 共通部分をcomponent化するメリット 第一にまずコード量が減る 変更箇所が統一されメンテ性が向上する 使い回しができる ゴール 今回はわかりやすくログインフォームで実装します 先生用のフォームと生徒用のフォームでわかれていると仮定します (生徒用のフォーム) (先生用のフォーム) Propsでページごとに変更する箇所 【タイトル】 生徒ログイン ⇆ 先生ログイン 【リンク名前】 先生はこちら ⇆ 生徒はこちら 【リンクURL】 '/teacher' ⇆ '/student' 【ログインURL】 'api/v1/teacher/sign_in' ⇆ 'api/v1/student/sign_in' 今回はこの4つの項目を親ページからcomponentへ送って表示を変更させます ログインフォーム実装 Nuxt.js components/LoginFrom.vue <template> <v-main> <v-container> <v-row justify="center" align="center"> <v-col cols="10"> <v-card> <v-card-title> {{ title }} </v-card-title> <v-card-text> <v-form> <v-text-field v-model="login_info.email" prepend-icon="mdi-account-circle" label="メールアドレス" /> <v-text-field v-model="login_info.password" :type="showPassword ? 'text' : 'password'" :append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'" prepend-icon="mdi-lock" label="パスワード" @click:append="showPassword = !showPassword" /> </v-form> <v-card-actions> <v-btn block color="info" > ログイン </v-btn> </v-card-actions> <v-card-actions> <router-link :to="link"> {{ linkTitle }} </router-link> </v-card-actions> </v-card-text> </v-card> </v-col> </v-row> </v-container> </v-main> </template> <script> export default { props: { title: { type: String, required: true }, linkTitle: { type: String, required: true }, link: { type: String, required: true }, loginUrl: { type: String, required: true } }, data () { return { showPassword: false, login_info: { email: '', password: '' } } } } </script> pages/teacher_login.vue <template> <LoginForm :title="title" :link-title="link_title" :link="link" :login-url="login_url" /> </template> <script> import LoginForm from '~/components/LoginForm.vue' export default { components: { LoginForm }, data () { return { title: '先生ログイン', link_title: '生徒はこちら', link: '/student_login', login_url: '/api/v1/teacher/sign_in' } } } </script> pages/teacher_login.vue <template> <LoginForm :title="title" :link-title="link_title" :link="link" :login-url="login_url" /> </template> <script> import LoginForm from '~/components/LoginForm.vue' export default { components: { LoginForm }, data () { return { title: '生徒ログイン', link_title: '先生はこちら', link: '/teacher_login', login_url: '/api/v1/student/sign_in' } } } </script> おまけ componentsへデータを送る時は teacher_login.vue(抜粋) :link-title=link_tile といったようにケバブケースとスネイクケースで書いている 又、受け取る時は LoginForm.vue(抜粋) linkTitle: { type: String, required: true }, とキャメルケースで受け取りを行っている JavaScriptでは【キャメルケース】 HTMLでは【ケバブケース】など 表記表現に違いがある為このような書き方になっている ESLintなど入れとけば警告で教えてくれるからいれるべき ではお疲れ様でした
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

sidekicq使って定期的なメール配信(rails/Docker/Heroku/circleCI)

やりたいこと 自作の「家計簿アプリ」の中で、 定期的(今回は毎週月曜の午前9時)に「支出のまとめ」をメールで配信する。 ※完成イメージはgithubのrepositoryを参照してください。 環境 ruby 2.7.4 rails 6.1.4 アプリケーションは、Docker,circleCIを使って、Herokuにデプロイ済み。 docker-compose.yml version: '3' services: db: image: mysql:8.0 command: --default-authentication-plugin=mysql_native_password volumes: - mysql_data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: password web: build: . command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - ./src:/app - gem_data:/usr/local/bundle environment: WEBPACKER_DEV_SERVER_HOST: webpacker ports: - "3000:3000" depends_on: - db tty: true stdin_open: true Dockerfile FROM ruby:2.7.4 ENV RAILS_ENV=production RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \ && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \ && apt-get update -qq \ && apt-get install -y nodejs yarn build-essential default-mysql-client \ && apt-get install -y cron WORKDIR /app COPY ./src /app RUN bundle config --local set path 'vendor/bundle' \ && bundle install COPY start.sh /start.sh RUN chmod 744 /start.sh CMD [ "sh", "/start.sh" ] start.sh #! /bin/sh if [ "${RAILS_ENV}" = "production" ] then bundle exec rails assets:precompile fi bundle exec rails s -p ${PORT:-3000} -b 0.0.0.0 .circleci/config.yml version: 2.1 orbs: ruby: circleci/ruby@1.1.2 # config.ymlのruby向け記法を導入 node: circleci/node@2 heroku: circleci/heroku@1.2.3 jobs: build: docker: - image: circleci/ruby:2.7.4-node working_directory: ~/kyodokoza/src steps: - checkout: path: ~/kyodokoza - ruby/install-deps test: docker: - image: circleci/ruby:2.7.4-node - image: circleci/mysql:5.5 environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: app_test MYSQL_USER: root environment: BUNDLE_JOBS: "3" BUNDLE_RETRY: "3" BUNDLE_PATH: vendor/bundle APP_DATABASE_HOST: "127.0.0.1" RAILS_ENV: test working_directory: ~/kyodokoza/src steps: - checkout: path: ~/kyodokoza - ruby/install-deps - run: name: Database setup command: bundle exec rake db:create - run: name: yarn install command: yarn install - run: name: Database migrate command: bundle exec rake db:migrate RAILS_ENV=test - run: name: RSpec command: bundle exec rspec deploy: docker: - image: circleci/ruby:2.7.4 steps: - checkout - setup_remote_docker: version: 19.03.13 - heroku/install - run: name: heroku login command: heroku container:login - run: name: push docker image command: heroku container:push web -a $HEROKU_APP_NAME - run: name: release docker image command: heroku container:release web -a $HEROKU_APP_NAME - run: name: database setup command: heroku run bundle exec rake db:migrate RAILS_ENV=production -a $HEROKU_APP_NAME workflows: version: 2 build_test_deploy: jobs: - build - test: requires: - build - deploy: requires: - test filters: branches: only: main 実装開始の前に 今回は、「ActiveJob」の「キューイングライブラリ」として「sidekicq」を使用。 「ActiveJob」って何? Railsガイドから引用。 ActiveJobの目的は以下の通り。 Active Jobは、ジョブを宣言し、 それによってバックエンドでさまざまな方法によるキュー操作を実行するためのフレームワークです。 ジョブには、定期的なクリーンアップを始めとして、請求書発行やメール配信など、あらゆる処理がジョブになります。 これらのジョブをより細かな作業単位に分割して並列実行することもできます。 「バックグラウンドjob実行のための共通化インターフェース」ということのようです。 「sidekiq」とか「キューイングライブラリ」って何? Railsガイドから引用。 production環境でのジョブのキュー登録と実行では、キューイングのバックエンドを用意しておく必要があります。具体的には、Railsで使うべきサードパーティのキューイングライブラリを決める必要があります。 Rails自身が提供するのは、ジョブをメモリに保持するインプロセスのキューイングシステムだけです。 プロセスがクラッシュしたりコンピュータをリセットしたりすると、デフォルトの非同期バックエンドの振る舞いによって主要なジョブが失われてしまいます。アプリケーションが小規模な場合やミッションクリティカルでないジョブであればこれでも構いませんが、多くのproductionでは永続的なバックエンドを選ぶ必要があります。 そもそもActiveJobには、 定期実行や重たい処理等の「非同期な処理(=Jobの登録から実行まで時間的な隔たりがある処理)」を登録します。 その時間的隔たりの間に、プロセスクラッシュ等により、Jobが失われる可能性があります。 そうならないためにも、Jobを保管する場所を用意したい。 それがキューイングライブラリ。例えばsidekicq。 他には、ResqueやDelayedJobなどもあるらしいです。 sidekiqは公式githubのwikiが詳しいので、まずはざっと目を通すといいと思います。 https://github.com/mperham/sidekiq/wiki 実装(開発環境) 実装の流れ(開発環境) gemの導入(sidekiq, sidekiq-scheduler) docker-composeにredis用・sidekiq用のコンテナを導入 ActiveJob、sidekiqの設定 テスト用のジョブの設定、コンソール上で実行 sidekiq-schedulerの設定 テスト用のメール定期配信ジョブの設定、コンソール上で実行 sidekiqの導入~コンソール上で動作確認 gemの導入 gemdileに追加してbundle install gemfile gem 'sidekiq' gem 'sidekiq-scheduler' # 後々使うので、先に入れておく。 docker-composeにredis用・sidekiq用のコンテナを導入 Dockerも修正。redisサーバーをコンテナで立ち上げる。 Dokcer-compose.yml # 以下追加 redis: image: "redis:latest" ports: - "6379:6379" volumes: - "./data/redis:/data" sidekiq: build: . command: bundle exec sidekiq volumes: - ./src:/app - gem_data:/usr/local/bundle environment: REDIS_URL: redis://redis:6379 depends_on: - db - redis ActiveJob、sidekiqの設定 ActiveJobのキューインライブラリとしてsidekiqを設定 config/application.rb module App class Application < Rails::Application # 以下追加 config.active_job.queue_adapter = :sidekiq end end sidekiqのredisとの通信を設定。 docker-compose.ymlで環境変数を定義した、REDIS_URLを使用。 config/initializer/sidekiq.rb Sidekiq.configure_server do |config| config.redis = { url: ENV["REDIS_URL"] } end Sidekiq.configure_client do |config| config.redis = { url: ENV["REDIS_URL"] } end テスト用のジョブの設定、コンソール上で実行 docker-compose up でコンテナ立ち上げした後、 動作確認用にsamplejobクラスを定義して、コンソール上で実行してみる。 console docker-compose exec web bundle exec rails g job SampleJob app/jobs/sample_job.rb class SampleJob < ApplicationJob queue_as :default def perform(*args) # テスト用の処理を記述 puts "=====サンプルジョブです======" end end sidekiqのコンソールでSampleJobの実行 docker-compose exec sidekiq rails c irb [1] pry(main)> SampleJob.perform_later Enqueued SampleJob (Job ID: 541558a6-e161-4688-bdac-af87749c0ef6) to Sidekiq(default) => #<SampleJob:0x0000563727fb5fb8 @arguments=[], @exception_executions={}, @executions=0, @job_id="541558a6-e161-4688-bdac-af87749c0ef6", @priority=nil, @provider_job_id="8dc90dd89d58f0348c963338", @queue_name="default", @timezone="Asia/Tokyo"> sidekiqのlog 2022-01-03T00:56:14.908Z pid=1 tid=gup class=SampleJob jid=8f1e338731e0576cd6376cd4 INFO: start 2022-01-03T00:56:15.857Z pid=1 tid=gup class=SampleJob jid=8f1e338731e0576cd6376cd4 INFO: Performing SampleJob (Job ID: bfccddd8-2cc8-4cd9-9c78-f7a0b628edea) from Sidekiq(default) enqueued at 2022-01-03T00:56:14Z =====サンプルジョブです====== 2022-01-03T00:56:15.859Z pid=1 tid=gup class=SampleJob jid=8f1e338731e0576cd6376cd4 INFO: Performed SampleJob (Job ID: bfccddd8-2cc8-4cd9-9c78-f7a0b628edea) from Sidekiq(default) in 0.23ms 2022-01-03T00:56:15.862Z pid=1 tid=gup class=SampleJob jid=8f1e338731e0576cd6376cd4 elapsed=0.954 INFO: done コンソール上の動作確認ができました。 因みに、perform_laterの他に、以下のようなメソッドも使うことができます。 SampleJob.perform_async SampleJob.perform_in(5.minutes) SampleJob.perform_at(5.minutes.from_now) 参照: https://github.com/mperham/sidekiq/wiki/Getting-Started sidekiq-schedulerの導入~コンソール上で動作確認 単独でsidekiqのジョブ実行の確認ができました。 次に、定期実行のためにsidekiq-schedulerを導入、テストしていきます。 sidekiq-schedulerの設定 Sidekiq-schedulerのGemは前節で導入済みのはず。 sidekiq.ymlを追加して、cron likeなジョブスケジューリングを設定。 config/sidekiq.yml :schedule: sample_job: cron: '0 * * * * *' # Runs once per minute class: SampleJob うまくいけば、sidekiqのログにsample_jobの実行結果が表示される。 log sidekiq_1 | 2022-01-03T01:13:00.259Z pid=1 tid=gnh INFO: queueing SampleJob (SampleJob) sidekiq_1 | 2022-01-03T01:13:00.261Z pid=1 tid=gp5 class=SampleJob jid=b452e81949a58ad40be54307 INFO: start sidekiq_1 | 2022-01-03T01:13:00.375Z pid=1 tid=gnh INFO: Enqueued SampleJob (Job ID: 0df2f507-3e67-4fc9-a3ee-5e768d554877) to Sidekiq(default) sidekiq_1 | 2022-01-03T01:13:06.562Z pid=1 tid=gp5 class=SampleJob jid=b452e81949a58ad40be54307 INFO: Performing SampleJob (Job ID: 0df2f507-3e67-4fc9-a3ee-5e768d554877) from Sidekiq(default) enqueued at 2022-01-03T01:13:00Z sidekiq_1 | =====サンプルジョブです====== sidekiq_1 | 2022-01-03T01:13:17.173Z pid=1 tid=gp5 class=SampleJob jid=b452e81949a58ad40be54307 INFO: Performed SampleJob (Job ID: 0df2f507-3e67-4fc9-a3ee-5e768d554877) from Sidekiq(default) in 10595.9ms sidekiq_1 | 2022-01-03T01:13:17.181Z pid=1 tid=gp5 class=SampleJob jid=b452e81949a58ad40be54307 elapsed=16.92 INFO: done sidekiq_1 | 2022-01-03T01:14:00.220Z pid=1 tid=gnh INFO: queueing SampleJob (SampleJob) sidekiq_1 | 2022-01-03T01:14:00.222Z pid=1 tid=gwd class=SampleJob jid=fd5771e57a45b22f2d98da82 INFO: start sidekiq_1 | 2022-01-03T01:14:00.223Z pid=1 tid=gnh INFO: Enqueued SampleJob (Job ID: b712844c-1ba6-4774-b31d-53e857caaf95) to Sidekiq(default) sidekiq_1 | 2022-01-03T01:14:01.788Z pid=1 tid=gwd class=SampleJob jid=fd5771e57a45b22f2d98da82 INFO: Performing SampleJob (Job ID: b712844c-1ba6-4774-b31d-53e857caaf95) from Sidekiq(default) enqueued at 2022-01-03T01:14:00Z sidekiq_1 | =====サンプルジョブです====== sidekiq_1 | 2022-01-03T01:14:01.791Z pid=1 tid=gwd class=SampleJob jid=fd5771e57a45b22f2d98da82 INFO: Performed SampleJob (Job ID: b712844c-1ba6-4774-b31d-53e857caaf95) from Sidekiq(default) in 0.22ms sidekiq_1 | 2022-01-03T01:14:01.793Z pid=1 tid=gwd class=SampleJob jid=fd5771e57a45b22f2d98da82 elapsed=1.571 INFO: done 参照: https://kerubito.net/technology/3315 https://github.com/moove-it/sidekiq-scheduler テスト用のメール定期配信ジョブの設定、コンソール上で実行 まずは通常通り、メイラーのメソッド・ビューの記述。 app/mailers/user_mailer.rb class UserMailer < ApplicationMailer def weekly_notification user = User.first mail to: user, subject: "test mail" end end app/views/user_maier/weekly_notifications.html.erb <p>これはテスト用メールです<p> Jobの作成 console docker-compose run web bundle exec rails g job WeeklyMailJob app/jobs/weekly_mail_job.rb class WeeklyMailJob < ApplicationJob queue_as :default def perform(*args) UserMailer.weekly_notification.deliver_now puts "==== send WeeklyMail!! ====" end end docker-compose upで確認。 letter_opener_webのgemを使えばメール配信されていることを確認できると思います。今回は割愛。 実装(本番環境) ここからはredis,sidekiqをHerokuで使えるようにしていきます。 実装の流れ(本番環境) heroku redisの導入 circleci.yml, Dockerfile, docker-compose.ymlの記述 デプロイ、ログ・メール受信の確認 参考: Worker dyno、バックグラウンドジョブ、キューイング(Heroku公式) https://devcenter.heroku.com/ja/articles/background-jobs-queueing heroku redisの導入 heroku redisの導入 まずはheroku redisのadd-onを自分のアプリに導入。 コンソールからでも、ダッシュボードからでもOKです。 ダッシュボードからはこちらから↓。 https://elements.heroku.com/addons/heroku-redis ※デフォルトではredisのversionは6.2が設定される。 (https://devcenter.heroku.com/articles/heroku-redis#version-support-and-legacy-infrastructure) ※Heroku上でインスタンスを生成すると、REDIS_URL環境変数は自動で上書き設定される。 If you’ve manually created a REDIS_URL config var on your app, it is overwritten when you add your first heroku-redis add-on. 参照: https://devcenter.heroku.com/articles/heroku-redis#create-an-instance worker dynoを導入 RailsのWEBアプリをHeroku上で動かす場合、 自動でWEBプロセス(web dyno)を作り、その中で動作している (Herokuのdyno ≒ AWSのEC2インスタンス)。 Heoku上でsidekiqを動作させるには、web dynoと並列で、 worker dynoが必要です。 プロセスモデルについて詳細は以下を参照。 https://devcenter.heroku.com/ja/articles/process-model ここでは、webプロセス(Railsアプリケーションのフロントエンド)とworkerプロセス(sidekiq)を用意して、 1,webプロセスがクライアントからのリクエストを受信 2,webプロセスがタスクをジョブキュー(Redis)に追加 3,workerプロセスがキューに溜まったタスクを検知し、取り出して実行 という処理を実装します。 つまり構成のイメージを図にすると、以下の通りです。 ===== web dyno(rails app) ↓ redis ↑ worker dyno(sidekiq) ===== また、Dockerを使わずにデプロイする場合は プロジェクトのルートに以下を記載したProcfileを用意して Sidekiq用のworkerのプロセスタイプを定義し、herokuにpushすればOKです。 (参考:https://madogiwa0124.hatenablog.com/entry/2021/03/28/161255) 今回は、Dockerおよびherokuコンテナレジストリの仕組みを使ってデプロイするので、 Dockerfile,CircleCIのymlファイルを修正して、 web dyno, worker dynoを作ります。 circleci.yml, Dockerfile, docker-compose.ymlの記述 実装方針 デプロイの設定(circleci/config.ymlの記述)は以下の通り。 sidekiq導入前) rails app <= Dockerfile heroku container:push web app_name 導入後) rails app <= Dockerfile.web sidekiq <= Dockerfile.worker heroku container:push --recursive app_name 参照: https://devcenter.heroku.com/ja/articles/container-registry-and-runtime https://qiita.com/sho7650/items/9654377a8fc2d4db236d 実際に、各種設定ファイルを修正します。 Dockerfile.web ファイル名変更 Dockerfile => Dockerfile.web Dockerfile.worker Dockerfile.webと最後のCMD以外同じ内容です。 (本当はうまく共通化したいが、今のところ後回し。。) (うまいやり方あれば、教えていただけますと幸いです。。) Dockerfile.worker FROM ruby:2.7.4 ENV RAILS_ENV=production RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \ && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \ && apt-get update -qq \ && apt-get install -y nodejs yarn build-essential default-mysql-client WORKDIR /app COPY ./src /app RUN bundle config --local set path 'vendor/bundle' \ && bundle install COPY start_worker.sh /start_worker.sh RUN chmod 744 /start_worker.sh CMD [ "sh", "/start_worker.sh" ] こちらも追加。 start_worker.sh #! /bin/sh if [ "${RAILS_ENV}" = "production" ] then bundle exec rails assets:precompile fi bundle exec sidekiq docker-compose.yml 以下、変更点のみ記載。 dokcer-compose.yml # 変更前 web: &app build: .  (中略) sidekiq: build: context: . dockerfile: Dockerfile.worker command: bundle exec sidekiq # 変更後 web: &app build: context: . dockerfile: Dockerfile.web  (中略) sidekiq: build: context: . dockerfile: Dockerfile.worker .circleci/config.yml 以下、変更点のみ記載。 .circleci/config.yml # 変更前 deploy: steps: - run: name: push docker image command: heroku container:push web -a $HEROKU_APP_NAME - run: name: release docker image command: heroku container:release web -a $HEROKU_APP_NAME # 変更後 deploy: steps: - run: name: push docker image command: heroku container:push web worker --recursive -a $HEROKU_APP_NAME - run: name: release docker image command: heroku container:release web worker -a $HEROKU_APP_NAME 本番環境で毎分メールはさすがにしんどいので、 確認用として、「5分ごとにメール設定」に変更します。 sidekiq.yml :schedule: weekly_mail: cron: '0 */5 * * * *' class: WeeklyMailJob デプロイ、ログ・メール受信の確認 デプロイし、本番環境で立ち上げ確認。 コンソールで「worker dynoが起動していること」と「SampleJobが実行できること」を確認。 console # worker dynoが起動していることを確認 $ heroku ps -a kyodokoza === web (Free): sh /start.sh (1) web.1: up 2022/01/08 16:56:49 +0900 (~ 8m ago) === worker (Free): sh /start_worker.sh (1) worker.1: up 2022/01/08 16:54:42 +0900 (~ 10m ago) # SampleJobが実行できることを確認 $ heroku config -a app_name irb(main):001:0> SampleJob.perform_later herokuのlog 2022-01-08T07:33:14.282983+00:00 app[worker.1]: =====サンプルジョブです====== また、ログを見れば、 自動で5分ごとにweekly_mailのjobが実行されていることも確認できます。 herokuのlog 2022-01-08T07:35:01.151945+00:00 app[worker.1]: ==== send WeeklyMail!! ==== (中略) 2022-01-08T07:40:00.839061+00:00 app[worker.1]: ==== send WeeklyMail!! ==== (中略) 2022-01-08T07:45:00.570713+00:00 app[worker.1]: ==== send WeeklyMail!! ==== 問題なし! あとは自分の好みにスケジュールを修正しましょう。 今回は毎週月曜の朝9時に送信されるように設定します。 sidekiq.yml :schedule: weekly_mail: cron: '0 0 9 * * 1' # Runs at 9:00 every Monday class: WeeklyMailJob これでOK!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Next.js の Product Build を docker-compose で動かしたい

どうしてやりたかったか? Next.js + typescript + Prisma2 + PostgreSQL でアプリケーションを作っていて、PostgreSQL は Docker で動かしていたので、合わせて docker-compose したかった。で、Deploy も docker で動かしたかった。 Production の PostgreSQL は、Docker 使わないけど、staging サーバ等では、Docker でも構わなかったので、docker-compose で、そのまま行くことにした。 ネットで調べたところ、開発環境用のものはいくつか見つかったが、Product Build 用のものは見当たらなかった。みんな vercel なの?? 検証環境 OS: MacOS Catalina Version 10.15.7(19H1615) node: v16.13.1 yarn: 1.22.15 docker: Docker version 20.10.11, build dea9396 docker-compose: Docker Compose version v2.2.1 公式ドキュメントによると Deployment - Docker Image with-docker の example を clone して build/run しろとある。気持ちは分かるけど、そうじゃない。 example は、github で見れるので、Dockerfile だけ拝借することにする。 Dockerfile は、こうなっている # Install dependencies only when needed FROM node:16-alpine AS deps # Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. RUN apk add --no-cache libc6-compat WORKDIR /app COPY package.json yarn.lock ./ RUN yarn install --frozen-lockfile # Rebuild the source code only when needed FROM node:16-alpine AS builder WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . RUN yarn build # Production image, copy all the files and run next FROM node:16-alpine AS runner WORKDIR /app ENV NODE_ENV production RUN addgroup -g 1001 -S nodejs RUN adduser -S nextjs -u 1001 # You only need to copy next.config.js if you are NOT using the default configuration # COPY --from=builder /app/next.config.js ./ COPY --from=builder /app/public ./public COPY --from=builder /app/package.json ./package.json # Automatically leverage output traces to reduce image size # https://nextjs.org/docs/advanced-features/output-file-tracing COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static USER nextjs EXPOSE 3000 ENV PORT 3000 # Next.js collects completely anonymous telemetry data about general usage. # Learn more here: https://nextjs.org/telemetry # Uncomment the following line in case you want to disable telemetry. # ENV NEXT_TELEMETRY_DISABLED 1 CMD ["node", "server.js"] yarn install する build する 必要なものだけコピーして node server.js する シンプル。特別なことはやってなさそう。 準備 まずは適当な Next.js アプリを作って、それで検証する。 $ yarn create next-app app --typescript yarn dev, yarn build, yarn start 全部 OK。 ひとまず、Dockerfile で動かしてみたいので、先程の Dockerfile を置く。node_modules とかはコピーする必要がない(コピーしても無駄な上時間がかかる)ので、.dockerignore に。 Dockerfile .dockerignore node_modules README.md .next とりあえず実行、そして失敗 "/app/.next/standalone" not found: not found と言われてしまう。なんでやねん。 yarn build したときに出来た .next の中に standalone がないらしい。 手元で build したときに出来た .next の中にも確かにない。 対応、だがしかし standalone は、experimental feature のようなので、next.config.js に追加すれば良い。Product Build でだけ experimental feature 使うの?という気もするけど。 next.config.js /** @type {import('next').NextConfig} */ module.exports = { reactStrictMode: true, experimental: { outputStandalone: true, }, } 再度 docker build すると、成功する。そして、docker run もできる。Welcome to Next.js! も表示される。でも、エラーが出る。 $ docker run -p 3000:3000 nextjs-docker Listening on port 3000 Error: Cannot find module './image-optimizer' Require stack: - /app/node_modules/next/dist/server/next-server.js - /app/server.js at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15) at Function.Module._load (node:internal/modules/cjs/loader:778:27) at Module.require (node:internal/modules/cjs/loader:1005:19) at require (node:internal/modules/cjs/helpers:94:18) at Object.fn (/app/node_modules/next/dist/server/next-server.js:609:49) at Router.execute (/app/node_modules/next/dist/server/router.js:222:48) at processTicksAndRejections (node:internal/process/task_queues:96:5) at async Server.run (/app/node_modules/next/dist/server/next-server.js:1135:29) at async Server.handleRequest (/app/node_modules/next/dist/server/next-server.js:325:20) at async Server.<anonymous> (/app/server.js:18:5) { code: 'MODULE_NOT_FOUND', requireStack: [ '/app/node_modules/next/dist/server/next-server.js', '/app/server.js' ] } image-optimizer がないとのこと。最終的に実行されているのは、.next/standalone の node_modules なので、手元で .next/standalone/node_modules/next/dist/server を確認してみるも、確かに image-optimizer.js はない。 なんでー。 バグだった Using component with-docker results in missing image-optimizer #32513 v12.0.8-canary.7 以上で対応済みとのこと。 現在の stable version は、 12.0.7 なので、しばし待て。ということか。 修正内容を見ると image-optimizer.js とそれを正しく動かすための sharp を含めれば良さそうだが、sharp なんてものはインストールされていないし、そう単純でもなさそうな気配がする。 対応方針 image-optimizer.js は、next/image API を利用する際に呼び出される。 考えられる方針は、以下3つくらい? v12.0.8-canary.7 以上を使う(本日時点の最新は、v12.0.8-canary.19) next/image API の利用をやめる image-optimizer.js の dependencies をひたすらコピーする 3つ目は、後で Dockerfile を編集するの嫌だし、途中まで試みたけど、切りがないのでやめる。 v12.0.8-canary.7 以上を使う マイナーバージョンアップの canary だし、別に良っか。という方針。next/image API を利用している場合は、こっち。v12.0.8 が出たら忘れずに直すこと。 package.json { ... "dependencies": { "next": "12.0.8-canary.19", ... }, ... } next/image API の利用をやめる 潜在的エラーなので、微妙だけど、next/image 使わないよって場合は、こっち。今回の例では、app/pages/index.tsx 内で使っているので、そこを消してしまう。 app/pages/index.tsx import type { NextPage } from 'next' import Head from 'next/head' //import Image from 'next/image' import styles from '../styles/Home.module.css' const Home: NextPage = () => { return ( <div className={styles.container}> ... <footer className={styles.footer}> <a href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app" target="_blank" rel="noopener noreferrer" > Powered by{' '} {/*<span className={styles.logo}> <Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} /> </span>*/} </a> </footer> </div> ) } export default Home docker-compose に組み込む Next.js のアプリの中に、Dockerfile を置いておくのは個人的に気持ち悪いので、以下のような配置とする。Dockerfile は他でも書くかも知れないので、名前を app に変更。.dockerignore は…ま、いっか。 . ├── Dockerfiles │   └── app ├── app (Next.js アプリ) ├── README.md └── docker-compose.yml docker-compose.yml version: '3.8' services: app: build: context: ./app dockerfile: ../Dockerfiles/app ports: - "3000:3000" $ docker-compose build $ docker-compose up -d OK! まとめ 本日時点で Next.js の Product Build を docker-compose で動かす手順をまとめると、 いくつか微妙な点はあるが(experimental feature 使ったり、canary 使ったり) with-docker example の Dockerfile を拝借 next.config.js に standalone を追加 next.js のバージョンを v12.0.8-canary.8 以上にするか、next/image API の使用をやめる docker-compose に組み込む となる。Next.js のバージョンも変更できないし、next/image API も使ってる!という場合は、build して yarn start するような Dockerfile に書き換えれば良いんじゃないかと。 おしまい。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MQTTの動作確認

Pub/Subモデルのmqttプロトコルの動作確認 イメージ ※Publisherがbrokerにデータを登録し、接続されているSubscriberにデータを流す。 ブローカのDockerfile Dockerfile-broker FROM ubuntu:20.04 RUN apt-get update RUN apt-get install -y mosquitto # ブローカの起動 CMD ["mosquitto", "-c", "/etc/mosquitto/mosquitto.conf"] 各クライアントのDockerfile Dockerfile-client FROM ubuntu:18.04 RUN apt-get update RUN apt-get install -y mosquitto-clients docker-compose docker-compose.yml version: "3.7" services: # ブローカ broker: build: context: . dockerfile: Dockerfile-broker # publisher pub: build: context: . dockerfile: Dockerfile-client tty: true # subscriber1 sub1: build: context: . dockerfile: Dockerfile-client tty: true # subscriber2 sub2: build: context: . dockerfile: Dockerfile-client tty: true 起動 docker-compose up 下記コマンドを実行してコンテナに入る ※上からpub、sub1、sub2 subscriber側で要求をする mosquitto_sub -h broker -t sample-topics publisher側でデータ送信 mosquitto_pub -h broker -t sample-topics -m "send to subscriber" subscriber側でデータを受信できているのを確認 github
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[golang error] go: gopkg.in/yaml.v2@v2.2.2: unknown revision v2.2.2

状況 Dockerでgolangとmysqlの環境構築 エラー内容 go: gopkg.in/yaml.v2@v2.2.2: unknown revision v2.2.2 go: error loading module requirements さきに結論 version (1.17)にupdateしましょう 上記をすでに試した場合 より詳しく 結論の繰り返しになりますが versionを更新することで解決できます 参考にしたissueはこちら 解決できてない方は自分と同じ場合かもしれないので 先にお進みください 自分の場合 Dockerfile FROM golang:1.17 WORKDIR /go/src/github.com/mahiro72/todo_api_pra COPY . . ENV GO111MODULE=on そもそもversionが本当に更新されているか コンテナ内で確認してみてください コンテナが動いてる場合 ログインしてgo versionで調べられます コンテナがbuild時に失敗し強制終了している場合 Dockerflieまたはcomposeのcmd で go versionを調べてみてください example: Dokcerfileの場合 CMD ["go","version"] 解決 自分の場合はレアケース(?)でversion指定してても buildするとversion:1.11.4になってました 上のDockerfileにあるENV GO111MODULE=onを コメント化することでversionを1.17にできました
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

multipass + docker on Mac

Mac でのDocker環境構築 いよいよ DockerDesktopの猶予期限がくるので、移行しました。 下記どちらでコマンドをうっているのか分かりづらいので セクションタイトルに Macで実行する場合は "on Mac"、 仮想環境のUbuntuで実行する場合は "on Ubuntu"と入れる multipass (ubuntu の仮想起動環境)インストール on Mac https://multipass.run/ 1. 上記からmac用binaryをDownload 2. installer を起動 multipass でubuntu:latest(20.04) 起動 on Mac あとからmemory, disk sizeを変更するのがとても大変なので最初から必要な分指定する。目的としてkubernetesのローカルデバッグをkindを使用して動かすので以下のようにmemory 10G, disk 20G, cpu core 4 程度は最低必要。 % multipass launch --name ryujidev -m 10G -d 20G -c 4 Launched: ryujidev % multipass ls Name State IPv4 Image ryujidev Running 192.168.64.3 Ubuntu 20.04 LTS % multipass info ryujidev Name: ryujidev State: Running IPv4: 192.168.64.3 172.17.0.1 172.18.0.1 Release: Ubuntu 20.04.3 LTS Image hash: 8fbc4e8c6e33 (Ubuntu 20.04 LTS) Load: 0.98 0.89 1.09 Disk usage: 12.3G out of 19.2G Memory usage: 2.3G out of 9.7G Mounts: -- あとから cpu, memoryを変更する方法 最初に指定していたほうがよいのですが、kubernetesでpodを起動しようとして、 podのstatusがpendingのままで進まないということがよくあります。 kubectrl describe pods をするとCPUやメモリが足りていないというのがわかります。 $kubectl describe pods -n istio-system ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 27m (x1 over 28m) default-scheduler 0/1 nodes are available: 1 Insufficient cpu. Warning FailedScheduling 15m (x1 over 16m) default-scheduler 0/1 nodes are available: 1 Insufficient cpu. Warning FailedScheduling 14h (x365 over 20h) default-scheduler 0/1 nodes are available: 1 Insufficient cpu. こんなときはしょうがないので以下の手順でmultipassが割り当てる cpu, memoryを変更できます https://github.com/canonical/multipass/issues/1158#issuecomment-548073024 # stop multipassd sudo launchctl unload /Library/LaunchDaemons/com.canonical.multipassd.plist # edit /var/root/Library/Application Support/multipassd/multipassd-vm-instances.json # you'll need sudo for that # start multipassd again sudo launchctl load /Library/LaunchDaemons/com.canonical.multipassd.plist 以下が編集したあとのmultipassd-vm-instances.jsonの例です { "ryujidev": { "deleted": false, "disk_space": "21474836480", "extra_interfaces": [ ], "mac_addr": "52:54:00:e1:9d:18", "mem_size": "10737418240", "metadata": { }, "mounts": [ ], "num_cores": 4, "ssh_username": "ubuntu", "state": 4 } } 参考:あとからDiskSizeを変更する方法 下記に説明があるので、やってみたのですが 2回ともmultipassでstartし直そうとすると disk imageが壊れてしまったようでした。 深くおっていないですがdisk sizeは変えなくて良いように最初に多めに割り当てておくのが無難です。 ubuntu に local directory をmount, login on Mac mountするかどうかは任意 (base) ~ % multipass mount ~/git ryujidev:/home/ubuntu/git (base) ~ % multipass shell ryujidev Welcome to Ubuntu 20.04.3 LTS (GNU/Linux 5.4.0-92-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage System information as of Sat Jan 8 09:05:44 JST 2022 System load: 0.13 Usage of /: 28.0% of 4.67GB Memory usage: 2% Swap usage: 0% Processes: 119 Users logged in: 0 IPv4 address for enp0s2: 192.168.64.3 IPv6 address for enp0s2: fd76:3e59:29b1:1bdf:4449:33ff:fe91:8c20 1 update can be applied immediately. To see these additional updates run: apt list --upgradable Last login: Sat Jan 8 09:04:25 2022 from 192.168.64.1 ubuntu@ryujidev:~$ ls git snap docker Install on Ubuntu https://docs.docker.com/engine/install/ubuntu/ 上記を直接参照したほうがよいですが何度も再実行するときのメモ用に下記にコマンドを抜き出しておきます。 sudo apt-get remove docker docker-engine docker.io ubuntu@ryujidev:~/git$ sudo apt-get update sudo apt-get install ca-certificates curl gnupg lsb-release curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io sudo docker run hello-world sudo なしでdocker実行するためのGroup追加 on Ubuntu sudo gpasswd -a $USER docker # logout & login, then enabled. Go package and make install on Ubuntu sudo add-apt-repository ppa:longsleep/golang-backports sudo apt update sudo apt install golang-go sudo apt install make remote debbug on Mac まず下記のように multipass 内で生成されたssh 公開鍵をコピーしておく sudo install -m 600 -o $USER -g $(id -g) /var/root/Library/Application\ Support/multipassd/ssh-keys/id_rsa ~/.ssh/multipass.id_rsa ~/.ssh/config に下記の設定を追記しておく(HostNameはmultipassで起動したubuntuのLocalIPに合わせる) Host ryujidev User ubuntu HostName 192.168.64.3 IdentityFile ~/.ssh/multipass.id_rsa これでmultipass shell だけでなく、 ssh ryujidev でubuntuにアクセスできるようになりました。 あとは下記を参考に vscodeのremote debug で ubuntuに接続し、src code本体は、仮想環境ubuntuにgitで取得して、UIは mac 上の vscodeで編集できます。 https://code.visualstudio.com/docs/remote/ssh#_connect-to-a-remote-host container のポートフォワード(WebServerのデバッグ等) https://code.visualstudio.com/docs/remote/ssh#_forwarding-a-port-creating-ssh-tunnel docker, k8s の動作確認 以下のように上記vscode remote debugで 仮想 ubuntuにつなぎ、vscodeのターミナルで、kind, k8s をたちあげてistioctl で kialiを開いてみます。(istioctlについての参考:https://qiita.com/kozayupapa/items/dfbabe1bd6eb40f4ddf9) 上記で実行するとvscode ポートタブに移動すると port forward設定が自動で追加しれてくれています!(便利!!かゆいところにてがとどいているさすがMicrosoft) MacのBrowserで localhost:20001 にアクセスするとちゃんと開いて確認できました。 これで無事 DockerDesktopを卒業できました。 今後また container CI/CDで利用することになったら再度Dockerファミリにお世話になろうと思います。 しばらくは AzureのContainerRepositoryを利用する予定なのでmultipassで十分かなと思いました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

「@blueskyarea Docker ホスト-コンテナ間でのユーザー/グループの分離をしたい」おまけ

docker Advent Calendar 2021 10日目の記事の紹介です。 ご投稿ありがとうございます。 @blueskyarea Docker ホスト-コンテナ間でのユーザー/グループの分離をしたい Linux上でdocker上のLinuxを動かす場合の、利用者(user)管理によるファイル管理を試されています。 現在、macOSで作業をしており、追試はできていません。ごめんなさい。 自分が興味を持ったとこだけ、おまけとして記録させてください。 記事の一番肝心な技術については、何かの機会に試させてください。 macOSのuser、Winoowsのuserとの関係の調査はいつかしてみようと思いました。 記事に関連して dockerを使っている時に、よくやる操作誤りは、どちら側で操作しているかを忘れてしまうことです。 この記事のように、コマンドプロンプトが違うから、そんなに間違えないよという方もおみえでしょう。 私はしょっ中やらかします。 今は、macOSで操作しているから apt ってやっても動かないのでいいのですが、 ubuntu にbrewを入れてしまったら、やらかすかもしれません。 記事には、どちら側の操作かを示していただいているので安心です。 user 補足1に書かれていることの関連事項です。 Linuxの利用者(user)管理ではいろいろ痛い目にあっています。 コマンドによる利用者の追加と、設定ファイルの同期をうまく取らないと、zombie(活動死体)かghost(幽霊)になるかもしれない。 ある配布(distribution)のある版(version)では、複数のコマンドが存在しており、振る舞いが少し違うことがあったりした。 その配布のその版で、一番お勧めな方法以外は取らないようにしている。 現在のdocker上のubuntuでコマンドを見た。 bash # useradd Usage: useradd [options] LOGIN useradd -D useradd -D [options] Options: --badnames do not check for bad names -b, --base-dir BASE_DIR base directory for the home directory of the new account --btrfs-subvolume-home use BTRFS subvolume for home directory -c, --comment COMMENT GECOS field of the new account -d, --home-dir HOME_DIR home directory of the new account -D, --defaults print or change default useradd configuration -e, --expiredate EXPIRE_DATE expiration date of the new account -f, --inactive INACTIVE password inactivity period of the new account -g, --gid GROUP name or ID of the primary group of the new account -G, --groups GROUPS list of supplementary groups of the new account -h, --help display this help message and exit -k, --skel SKEL_DIR use this alternative skeleton directory -K, --key KEY=VALUE override /etc/login.defs defaults -l, --no-log-init do not add the user to the lastlog and faillog databases -m, --create-home create the user's home directory -M, --no-create-home do not create the user's home directory -N, --no-user-group do not create a group with the same name as the user -o, --non-unique allow to create users with duplicate (non-unique) UID -p, --password PASSWORD encrypted password of the new account -r, --system create a system account -R, --root CHROOT_DIR directory to chroot into -P, --prefix PREFIX_DIR prefix directory where are located the /etc/* files -s, --shell SHELL login shell of the new account -u, --uid UID user ID of the new account -U, --user-group create a group with the same name as the user -Z, --selinux-user SEUSER use a specific SEUSER for the SELinux user mapping --extrausers Use the extra users database # adduser -h adduser [--home DIR] [--shell SHELL] [--no-create-home] [--uid ID] [--firstuid ID] [--lastuid ID] [--gecos GECOS] [--ingroup GROUP | --gid ID] [--disabled-password] [--disabled-login] [--add_extra_groups] [--encrypt-home] USER Add a normal user adduser --system [--home DIR] [--shell SHELL] [--no-create-home] [--uid ID] [--gecos GECOS] [--group | --ingroup GROUP | --gid ID] [--disabled-password] [--disabled-login] [--add_extra_groups] USER Add a system user adduser --group [--gid ID] GROUP addgroup [--gid ID] GROUP Add a user group addgroup --system [--gid ID] GROUP Add a system group adduser USER GROUP Add an existing user to an existing group general options: --quiet | -q don't give process information to stdout --force-badname allow usernames which do not match the NAME_REGEX[_SYSTEM] configuration variable --extrausers uses extra users as the database --help | -h usage message --version | -v version number and copyright --conf | -c FILE use FILE as configuration file did docker 内でdockerを起動する方法を探しました。 docker コマンドは導入できますが、dockerコマンドが見当たりません。 結果として、やってみたいことのやり方は見つかりませんでした。 docker上でPOSIXのTestSuiteの実行をしていないことに気がつきました。 別記事で立てようと思いました。 bash # docker run -it ubuntu /bin/bash bash # apt update; apt -y upgrade # apt -y install docker Reading package lists... Done Building dependency tree Reading state information... Done The following additional packages will be installed: libbsd0 libglib2.0-0 libglib2.0-data libicu66 libx11-6 libx11-data libxau6 libxcb1 libxdmcp6 libxml2 shared-mime-info tzdata wmdocker xdg-user-dirs The following NEW packages will be installed: docker libbsd0 libglib2.0-0 libglib2.0-data libicu66 libx11-6 libx11-data libxau6 libxcb1 libxdmcp6 libxml2 shared-mime-info tzdata wmdocker xdg-user-dirs 0 upgraded, 15 newly installed, 0 to remove and 0 not upgraded. Need to get 12.0 MB of archives. After this operation, 50.5 MB of additional disk space will be used. Get:1 http://archive.ubuntu.com/ubuntu focal/main amd64 libbsd0 amd64 0.10.0-1 [45.4 kB] Get:2 http://archive.ubuntu.com/ubuntu focal-updates/main amd64 libglib2.0-0 amd64 2.64.6-1~ubuntu20.04.4 [1287 kB] Get:3 http://archive.ubuntu.com/ubuntu focal-updates/main amd64 libglib2.0-data all 2.64.6-1~ubuntu20.04.4 [6052 B] Get:4 http://archive.ubuntu.com/ubuntu focal-updates/main amd64 tzdata all 2021e-0ubuntu0.20.04 [295 kB] Get:5 http://archive.ubuntu.com/ubuntu focal-updates/main amd64 libicu66 amd64 66.1-2ubuntu2.1 [8515 kB] Get:6 http://archive.ubuntu.com/ubuntu focal-updates/main amd64 libxml2 amd64 2.9.10+dfsg-5ubuntu0.20.04.1 [640 kB] Get:7 http://archive.ubuntu.com/ubuntu focal/main amd64 shared-mime-info amd64 1.15-1 [430 kB] Get:8 http://archive.ubuntu.com/ubuntu focal/main amd64 xdg-user-dirs amd64 0.17-2ubuntu1 [48.3 kB] Get:9 http://archive.ubuntu.com/ubuntu focal/main amd64 libxau6 amd64 1:1.0.9-0ubuntu1 [7488 B] Get:10 http://archive.ubuntu.com/ubuntu focal/main amd64 libxdmcp6 amd64 1:1.1.3-0ubuntu1 [10.6 kB] Get:11 http://archive.ubuntu.com/ubuntu focal/main amd64 libxcb1 amd64 1.14-2 [44.7 kB] Get:12 http://archive.ubuntu.com/ubuntu focal-updates/main amd64 libx11-data all 2:1.6.9-2ubuntu1.2 [113 kB] Get:13 http://archive.ubuntu.com/ubuntu focal-updates/main amd64 libx11-6 amd64 2:1.6.9-2ubuntu1.2 [575 kB] Get:14 http://archive.ubuntu.com/ubuntu focal/universe amd64 wmdocker amd64 1.5-2 [13.0 kB] Get:15 http://archive.ubuntu.com/ubuntu focal/universe amd64 docker all 1.5-2 [1316 B] Fetched 12.0 MB in 5s (2219 kB/s) debconf: delaying package configuration, since apt-utils is not installed Selecting previously unselected package libbsd0:amd64. (Reading database ... 4127 files and directories currently installed.) Preparing to unpack .../00-libbsd0_0.10.0-1_amd64.deb ... Unpacking libbsd0:amd64 (0.10.0-1) ... Selecting previously unselected package libglib2.0-0:amd64. Preparing to unpack .../01-libglib2.0-0_2.64.6-1~ubuntu20.04.4_amd64.deb ... Unpacking libglib2.0-0:amd64 (2.64.6-1~ubuntu20.04.4) ... Selecting previously unselected package libglib2.0-data. Preparing to unpack .../02-libglib2.0-data_2.64.6-1~ubuntu20.04.4_all.deb ... Unpacking libglib2.0-data (2.64.6-1~ubuntu20.04.4) ... Selecting previously unselected package tzdata. Preparing to unpack .../03-tzdata_2021e-0ubuntu0.20.04_all.deb ... Unpacking tzdata (2021e-0ubuntu0.20.04) ... Selecting previously unselected package libicu66:amd64. Preparing to unpack .../04-libicu66_66.1-2ubuntu2.1_amd64.deb ... Unpacking libicu66:amd64 (66.1-2ubuntu2.1) ... Selecting previously unselected package libxml2:amd64. Preparing to unpack .../05-libxml2_2.9.10+dfsg-5ubuntu0.20.04.1_amd64.deb ... Unpacking libxml2:amd64 (2.9.10+dfsg-5ubuntu0.20.04.1) ... Selecting previously unselected package shared-mime-info. Preparing to unpack .../06-shared-mime-info_1.15-1_amd64.deb ... Unpacking shared-mime-info (1.15-1) ... Selecting previously unselected package xdg-user-dirs. Preparing to unpack .../07-xdg-user-dirs_0.17-2ubuntu1_amd64.deb ... Unpacking xdg-user-dirs (0.17-2ubuntu1) ... Selecting previously unselected package libxau6:amd64. Preparing to unpack .../08-libxau6_1%3a1.0.9-0ubuntu1_amd64.deb ... Unpacking libxau6:amd64 (1:1.0.9-0ubuntu1) ... Selecting previously unselected package libxdmcp6:amd64. Preparing to unpack .../09-libxdmcp6_1%3a1.1.3-0ubuntu1_amd64.deb ... Unpacking libxdmcp6:amd64 (1:1.1.3-0ubuntu1) ... Selecting previously unselected package libxcb1:amd64. Preparing to unpack .../10-libxcb1_1.14-2_amd64.deb ... Unpacking libxcb1:amd64 (1.14-2) ... Selecting previously unselected package libx11-data. Preparing to unpack .../11-libx11-data_2%3a1.6.9-2ubuntu1.2_all.deb ... Unpacking libx11-data (2:1.6.9-2ubuntu1.2) ... Selecting previously unselected package libx11-6:amd64. Preparing to unpack .../12-libx11-6_2%3a1.6.9-2ubuntu1.2_amd64.deb ... Unpacking libx11-6:amd64 (2:1.6.9-2ubuntu1.2) ... Selecting previously unselected package wmdocker. Preparing to unpack .../13-wmdocker_1.5-2_amd64.deb ... Unpacking wmdocker (1.5-2) ... Selecting previously unselected package docker. Preparing to unpack .../14-docker_1.5-2_all.deb ... Unpacking docker (1.5-2) ... Setting up libxau6:amd64 (1:1.0.9-0ubuntu1) ... Setting up xdg-user-dirs (0.17-2ubuntu1) ... Setting up libglib2.0-0:amd64 (2.64.6-1~ubuntu20.04.4) ... No schema files found: doing nothing. Setting up tzdata (2021e-0ubuntu0.20.04) ... debconf: unable to initialize frontend: Dialog debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 76.) debconf: falling back to frontend: Readline debconf: unable to initialize frontend: Readline debconf: (Can't locate Term/ReadLine.pm in @INC (you may need to install the Term::ReadLine module) (@INC contains: /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.30.0 /usr/local/share/perl/5.30.0 /usr/lib/x86_64-linux-gnu/perl5/5.30 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl/5.30 /usr/share/perl/5.30 /usr/local/lib/site_perl /usr/lib/x86_64-linux-gnu/perl-base) at /usr/share/perl5/Debconf/FrontEnd/Readline.pm line 7.) debconf: falling back to frontend: Teletype Configuring tzdata ------------------ Please select the geographic area in which you live. Subsequent configuration questions will narrow this down by presenting a list of cities, representing the time zones in which they are located. 1. Africa 3. Antarctica 5. Arctic 7. Atlantic 9. Indian 11. SystemV 13. Etc 2. America 4. Australia 6. Asia 8. Europe 10. Pacific 12. US Geographic area: 6 Please select the city or region corresponding to your time zone. 1. Aden 13. Barnaul 25. Dushanbe 37. Jerusalem 49. Macau 61. Pyongyang 73. Taipei 85. Vientiane 2. Almaty 14. Beirut 26. Famagusta 38. Kabul 50. Magadan 62. Qatar 74. Tashkent 86. Vladivostok 3. Amman 15. Bishkek 27. Gaza 39. Kamchatka 51. Makassar 63. Qostanay 75. Tbilisi 87. Yakutsk 4. Anadyr 16. Brunei 28. Harbin 40. Karachi 52. Manila 64. Qyzylorda 76. Tehran 88. Yangon 5. Aqtau 17. Chita 29. Hebron 41. Kashgar 53. Muscat 65. Rangoon 77. Tel_Aviv 89. Yekaterinburg 6. Aqtobe 18. Choibalsan 30. Ho_Chi_Minh 42. Kathmandu 54. Nicosia 66. Riyadh 78. Thimphu 90. Yerevan 7. Ashgabat 19. Chongqing 31. Hong_Kong 43. Khandyga 55. Novokuznetsk 67. Sakhalin 79. Tokyo 8. Atyrau 20. Colombo 32. Hovd 44. Kolkata 56. Novosibirsk 68. Samarkand 80. Tomsk 9. Baghdad 21. Damascus 33. Irkutsk 45. Krasnoyarsk 57. Omsk 69. Seoul 81. Ujung_Pandang 10. Bahrain 22. Dhaka 34. Istanbul 46. Kuala_Lumpur 58. Oral 70. Shanghai 82. Ulaanbaatar 11. Baku 23. Dili 35. Jakarta 47. Kuching 59. Phnom_Penh 71. Singapore 83. Urumqi 12. Bangkok 24. Dubai 36. Jayapura 48. Kuwait 60. Pontianak 72. Srednekolymsk 84. Ust-Nera Time zone: 79 Current default time zone: 'Asia/Tokyo' Local time is now: Sat Jan 8 11:27:04 JST 2022. Universal Time is now: Sat Jan 8 02:27:04 UTC 2022. Run 'dpkg-reconfigure tzdata' if you wish to change it. Setting up libglib2.0-data (2.64.6-1~ubuntu20.04.4) ... Setting up libx11-data (2:1.6.9-2ubuntu1.2) ... Setting up libbsd0:amd64 (0.10.0-1) ... Setting up libxdmcp6:amd64 (1:1.1.3-0ubuntu1) ... Setting up libxcb1:amd64 (1.14-2) ... Setting up libicu66:amd64 (66.1-2ubuntu2.1) ... Setting up libx11-6:amd64 (2:1.6.9-2ubuntu1.2) ... Setting up libxml2:amd64 (2.9.10+dfsg-5ubuntu0.20.04.1) ... Setting up wmdocker (1.5-2) ... Setting up shared-mime-info (1.15-1) ... Setting up docker (1.5-2) ... Processing triggers for libc-bin (2.31-0ubuntu9.2) ... root@1957b5c49435:/# docker run -it ubuntu /bin/bash bash: docker: command not found root@1957b5c49435:/# /bin/docker bash: /bin/docker: No such file or directory root@1957b5c49435:/# /sbin/docker bash: /sbin/docker: No such file or directory root@1957b5c49435:/# find / -name docker -print /usr/share/doc/docker did 参考資料 Docker in Docker のベタープラクティス Dockerコンテナ内からDockerを使うことについて docker in docker(dind)を使ってみる 参考資料 Linuxbrew のススメ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby 2.5.0コンテナでRails6の開発環境を作るときのトラブルシューティング

こちらのハンズオンをやっていたところ、いくつかの問題に遭遇したので備忘録。 Rails アプリケーションをコンテナで開発しよう ! 第 1 回 - まずは Rails アプリケーション作りから Rails7のインストールに失敗する 記事では Ruby2.5 & Rails6 を使用しているが、現時点(2022/1)での最新版は 7.0.1。 エラーメッセージにもあるように7.0.1 ではRuby2.7以上が必要であるため gem install railsに失敗する。 root@810c33297af8:/work# gem install rails Fetching: concurrent-ruby-1.1.9.gem (100%) Successfully installed concurrent-ruby-1.1.9 Fetching: i18n-1.8.11.gem (100%) Successfully installed i18n-1.8.11 Fetching: tzinfo-2.0.4.gem (100%) Successfully installed tzinfo-2.0.4 Fetching: activesupport-7.0.1.gem (100%) ERROR: Error installing rails: There are no versions of activesupport (= 7.0.1) compatible with your Ruby & RubyGems. Maybe try installing an older version of the gem you're looking for? activesupport requires Ruby version >= 2.7.0. The current ruby version is 2.5.0. gem install のオプションでRailsのバージョンを指定してインストールすることとした。 root@810c33297af8:/work# gem install -v 6.0.3.2 rails Nokogiriのインストールに失敗する さて、Railのバージョン指定をして改めてgem installを実施したところ、 root@810c33297af8:/work# gem install -v 6.0.3.2 rails ... Fetching: activesupport-6.0.3.2.gem (100%) Successfully installed activesupport-6.0.3.2 ERROR: While executing gem ... (Gem::RemoteFetcher::FetchError) bad response Forbidden 403 (https://api.rubygems.org/quick/Marshal.4.8/nokogiri-1.13.0-x64-unknown.gemspec.rz) Nokogiri 1.13.0のインストールに失敗している。 403なのでライブラリが不足している的なやつではないみたい。 rubygems.org でNokogiriの過去バージョンを調べて 1.12.5 を予めインストールすることで解決。 root@810c33297af8:/work# gem install nokogiri -v 1.12.5 Fetching: nokogiri-1.12.5-x86_64-linux.gem (100%) Successfully installed nokogiri-1.12.5-x86_64-linux 1 gem installed root@810c33297af8:/work# gem install -v 6.0.3.2 rails Fetching: loofah-2.13.0.gem (100%) Successfully installed loofah-2.13.0 Fetching: rails-html-sanitizer-1.4.2.gem (100%) Successfully installed rails-html-sanitizer-1.4.2 Fetching: rails-dom-testing-2.0.3.gem (100%) Successfully installed rails-dom-testing-2.0.3 Fetching: builder-3.2.4.gem (100%) Successfully installed builder-3.2.4 Fetching: erubi-1.10.0.gem (100%) Successfully installed erubi-1.10.0 Fetching: actionview-6.0.3.2.gem (100%) Successfully installed actionview-6.0.3.2 Fetching: actionpack-6.0.3.2.gem (100%) Successfully installed actionpack-6.0.3.2 Fetching: activemodel-6.0.3.2.gem (100%) Successfully installed activemodel-6.0.3.2 Fetching: activerecord-6.0.3.2.gem (100%) Successfully installed activerecord-6.0.3.2 Fetching: globalid-1.0.0.gem (100%) Successfully installed globalid-1.0.0 Fetching: activejob-6.0.3.2.gem (100%) Successfully installed activejob-6.0.3.2 Fetching: mini_mime-1.1.2.gem (100%) Successfully installed mini_mime-1.1.2 Fetching: mail-2.7.1.gem (100%) Successfully installed mail-2.7.1 Fetching: actionmailer-6.0.3.2.gem (100%) Successfully installed actionmailer-6.0.3.2 Fetching: nio4r-2.5.8.gem (100%) Building native extensions. This could take a while... Successfully installed nio4r-2.5.8 Fetching: websocket-extensions-0.1.5.gem (100%) Successfully installed websocket-extensions-0.1.5 Fetching: websocket-driver-0.7.5.gem (100%) Building native extensions. This could take a while... Successfully installed websocket-driver-0.7.5 Fetching: actioncable-6.0.3.2.gem (100%) Successfully installed actioncable-6.0.3.2 Fetching: mimemagic-0.3.10.gem (100%) Building native extensions. This could take a while... Successfully installed mimemagic-0.3.10 Fetching: marcel-0.3.3.gem (100%) Successfully installed marcel-0.3.3 Fetching: activestorage-6.0.3.2.gem (100%) Successfully installed activestorage-6.0.3.2 Fetching: actionmailbox-6.0.3.2.gem (100%) Successfully installed actionmailbox-6.0.3.2 Fetching: actiontext-6.0.3.2.gem (100%) Successfully installed actiontext-6.0.3.2 Fetching: thor-1.2.1.gem (100%) Successfully installed thor-1.2.1 Fetching: method_source-1.0.0.gem (100%) Successfully installed method_source-1.0.0 Fetching: railties-6.0.3.2.gem (100%) Successfully installed railties-6.0.3.2 Fetching: sprockets-4.0.2.gem (100%) Successfully installed sprockets-4.0.2 Fetching: sprockets-rails-3.4.2.gem (100%) Successfully installed sprockets-rails-3.4.2 Fetching: rails-6.0.3.2.gem (100%) Successfully installed rails-6.0.3.2 29 gems installed
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LinuxにDockerをインストールする方法

UbuntuでDockerをインストールする方法について説明します 手順 - リポジトリを設定 - Docker Engineをインストール - hello-worldイメージの実行 リポジトリを設定 Dockerのインストール前にaptパッケージインデックスを更新し、パッケージをインストールして、aptがHTTPS経由でリポジトリを使用できるようにします。 以下コマンドをターミナルにコピペして実行してください。 terminal sudo apt-get update sudo apt-get install \ ca-certificates \ curl \ gnupg \ lsb-release それぞれのコマンド実行の様子 terminal $sudo apt-get update Get:1 http://security.ubuntu.com/ubuntu focal-security InRelease [114 kB] Hit:2 http://archive.ubuntu.com/ubuntu focal InRelease Get:3 http://archive.ubuntu.com/ubuntu focal-updates InRelease [114 kB] Get:4 http://archive.ubuntu.com/ubuntu focal-backports InRelease [108 kB] Get:5 http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages [1445 kB] Get:6 http://archive.ubuntu.com/ubuntu focal-updates/universe amd64 Packages [892 kB] Fetched 2672 kB in 4s (676 kB/s) Reading package lists... Done terminal $sudo apt-get install \ > ca-certificates \ > curl \ > gnupg \ > lsb-release Reading package lists... Done Building dependency tree Reading state information... Done lsb-release is already the newest version (11.1.0ubuntu2). lsb-release set to manually installed. ca-certificates is already the newest version (20210119~20.04.2). ca-certificates set to manually installed. curl is already the newest version (7.68.0-1ubuntu2.7). curl set to manually installed. gnupg is already the newest version (2.2.19-3ubuntu2.1). gnupg set to manually installed. 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. 続いて、Dockerの公式GPGキーを追加します。(実行後は特に何も表示されません) terminal curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg 次に安定板のリポジトリをセットアップします。(実行後は特に何も表示されません) terminal echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null Docker Engineをインストールします。 terminal sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io それぞれのコマンド実行後の様子 sudo apt-get updateは再度実行します。 terminal $sudo apt-get update Get:1 https://download.docker.com/linux/ubuntu focal InRelease [57.7 kB] Get:2 https://download.docker.com/linux/ubuntu focal/stable amd64 Packages [13.5 kB] Get:3 http://security.ubuntu.com/ubuntu focal-security InRelease [114 kB] Hit:4 http://archive.ubuntu.com/ubuntu focal InRelease Hit:5 http://archive.ubuntu.com/ubuntu focal-updates InRelease Get:6 http://archive.ubuntu.com/ubuntu focal-backports InRelease [108 kB] Fetched 293 kB in 2s (130 kB/s) Reading package lists... Done terminal $sudo apt-get install docker-ce docker-ce-cli containerd.io Reading package lists... Done Building dependency tree Reading state information... Done The following additional packages will be installed: docker-ce-rootless-extras docker-scan-plugin pigz slirp4netns Suggested packages: . (途中省略) . Do you want to continue? [Y/n] Y Get:1 https://download.docker.com/linux/ubuntu focal/stable amd64 containerd.io amd64 1.4.12-1 [23.7 MB] Get:2 http://archive.ubuntu.com/ubuntu focal/universe amd64 pigz amd64 2.4-1 [57.4 kB] Get:3 http://archive.ubuntu.com/ubuntu focal/universe amd64 slirp4netns amd64 0.4.3-1 [74.3 kB] Get:4 https://download.docker.com/linux/ubuntu focal/stable amd64 docker-ce-cli amd64 5:20.10.12~3-0~ubuntu-focal [40.7 MB] Get:5 https://download.docker.com/linux/ubuntu focal/stable amd64 docker-ce amd64 5:20.10.12~3-0~ubuntu-focal [21.2 MB] 65% [5 docker-ce 32.3 kB/21.2 MB 0%] (以下省略) これでDockerがインストールされたので、Dockerを起動します。 terminal $ sudo service docker start * Docker is running Dockerが正常に起動したことを確認できたら、 hello-worldイメージを実行して、DockerEngineが正しくインストールされていることを確認します。 terminal $sudo docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 2db29710123e: Pull complete Digest: sha256:2498fce14358aa50ead0cc6c19990fc6ff866ce72aeb5546e1d59caac3d0d60f Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/ これでDockerのインストールは完了です。 <参考記事> Install Docker Engine on Ubuntu WSL上でDockerを動かす際に躓いたこと
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

NestJS + Docker + Jest でE2Eテストを実行する備忘録

概要 以下の参考記事をもとに業務で導入した方法を備忘録として残します。 やり方 E2Eテスト用DockerFileを作成 Dockerfile.test # FROM ベースイメージを指定する # as build-stage ビルド用のイメージと実行用のイメージを分ける # -alpine 軽量イメージ FROM node:14.16.1-alpine as build-stage # 作業ディレクトリを作成 WORKDIR /work COPY . /work/ RUN npm install # コマンドを実行する CMD ["npm","run","test:e2e"] dev環境をmigration用DockerFileを作成 Dockerfile.migrate FROM node:14.16.1-alpine WORKDIR /work COPY ./src/databases /work/src/databases COPY ./package.json ./package-lock.json ./ormconfig.ts ./tsconfig.json /work/ RUN npm install CMD ["npm", "run", "typeorm", "migration:run"] E2Eテスト用のdocker-composehuxairu unit-test.yml # docker-composeで使用するバージョン version: '3' # アプリケーションを動かすための各要素 services: # コンテナ名 app: # ComposeFileを実行し、ビルドされるときのpath build: # docker buildコマンドを実行した場所 context: "." # Dockerfileのある場所 dockerfile: "Dockerfile.test" # image ID image: hoge-test # コンテナ名 container_name: hoge-test # ポート番号 ports: - '3000:3000' # 環境変数 environment: PORT: xxx TZ: 'Asia/Tokyo' DB_HOST: 'xx' DB_PORT: 'xxxx' DB_USERNAME: 'xxxx' DB_PASSWORD: 'xxxx' DB_NAME: 'hoge' REDIS_HOST: 'xx' REDIS_PORT: 'xx' # サービス間の依存関係 depends_on: - db - redis redis: image: redis:5.0 container_name: redis_container-test ports: - "xxxx:xxxx" db: image: mysql:8.0 command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci container_name: db_container_test ports: - xxxx:xxxx environment: TZ: 'Asia/Tokyo' MYSQL_ROOT_PASSWORD: xxxx MYSQL_DATABASE: xxxx MYSQL_USER: xxxx MYSQL_PASSWORD: xxxx テスト環境用TypeOrm設定ファイルの作成 同期-アプリケーションの起動ごとにデータベーススキーマを自動作成する必要があるかどうかを示します。このオプションには注意してください。本番環境では使用しないでください。本番環境のデータが失われる可能性があります。このオプションは、デバッグおよび開発中に役立ちます。その代わりに、CLIを使用してschema:syncコマンドを実行できます。 ormconfig.test.ts module.exports = { type: 'mysql', host: process.env.DB_HOST || 'localhost', port: process.env.DB_PORT || 'xxxx', username: process.env.DB_USERNAME || 'xxxx', password: process.env.DB_PASSWORD || 'xxxx', database: process.env.DB_NAME || 'xxxx', // アプリケーション実行時にEntityをデータベースに同期する synchronize: true, // 実行されるSQLをログとして吐く logging: true, entities: ['src/domain/entities/*.ts'], migrations: ['src/databases/migrations/*.ts'], seeds: ['src/test/databases/seeders/*.seed.{js,ts}'], subscribers: ['src/subscribers/**/*.ts'], cli: { migrationsDir: 'src/databases/migrations', entitiesDir: 'src/domain/entities', seedersDir: 'src/databases/seeders', subscribersDir: 'src/subscribers', }, } テスト実行 # E2Eテストコンテナ立ち上げ docker-compose -f unit-test.yml build # E2Eテストコンテナ起動 テスト終わったらコンテナ落とす docker-compose -f unit-test.yml up --abort-on-container-exit Recreating redis_container ... done Recreating db_container ... done Recreating xxx-api-test ... done Attaching to redis_container-test, db_container_test, xxx-api-test xxx-api-test | xxx-api-test | > sample@0.0.1 test:e2e /work xxx-api-test | > jest --config ./src/test/e2e/jest-e2e.json xxx-api-test | xxx-api-test | PASS src/test/e2e/contractor-reps.e2e-spec.ts (92.288 s) xxx-api-test 契約担当者(E2E) xxx-api-test ログインしていない場合は401が返ります xxx-api-test ✓ OK /contractor-reps (GET) (1471 ms) xxx-api-test 契約担当者一覧テスト_サービス・システム管理 xxx-api-test ✓ OK /contractor-reps (GET) (1195 ms) // 省略 xxx-api-test Test Suites: 1 passed, 1 total xxx-api-test Tests: 38 passed, 38 total xxx-api-test Snapshots: 0 total xxx-api-test Time: 92.428 s xxx-api-test Ran all test suites. xxxx-api-test exited with code 0 最後に 読んでいただきありがとうございます。 今回の記事はいかがでしたか? ・こういう記事が読みたい ・こういうところが良かった ・こうした方が良いのではないか などなど、率直なご意見を募集しております。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel8.x】Laravel + Ngram + Observerを利用した全文検索機能の実装ハンズオン

はじめに 本記事は以下の続編になります。 https://qiita.com/naoki-haba/items/ace7a5d1e0d9d72ed040 続編記事を書くことにした経緯 シンプルなテーブル構成の場合は以下の通りにすれば全文検索の準備は整います DB::statement("ALTER TABLE shops ADD free_word TEXT as (concat(IFNULL(age, ''), ' ',IFNULL(name, ''), ' ',(case gender_id when 1 then '男性' when 2 then '女性' else '' end), ' ')) STORED"); しかし、複雑な要因(複数テーブルとの外部結合が必要な場合etc)の場合に、上記の記述をすることに苦労したので、今回は対処方法の選択肢の1つとしてご紹介させていただきます。 記事の流れ 1.既存のDDLからfree_wordカラムを削除する 2.ダミーデータを投入する 3.free_wordカラムを追加する 4.登録・更新イベントをディスパッチする処理を追加する 5.Artisanコマンドを作成する 6.作成したArtisanコマンドを実行。  free_wordカラムにデータを投入する 事前準備 docker-compose up -d docker-compose exec app bash composer install composer update cp .env.example .env php artisan key:generate php artisan storage:link chmod -R 777 storage bootstrap/cache Laravel + Ngram + Observerを利用した全文検索機能の実装ハンズオン 1.既存のDDLからfree_wordカラムを削除する 変更用のmigrationファイルを生成します php artisan make:migration change_free_word_to_shops --table=shops migrationを定義 backend/database/migrations/2022_01_06_185439_change_free_word_to_shops.php class ChangeFreeWordToShops extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::table('shops', function (Blueprint $table) { $table->dropColumn('free_word'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::table('shops', function (Blueprint $table) { DB::statement("ALTER TABLE shops ADD free_word TEXT as (concat(IFNULL(age, ''), ' ',IFNULL(name, ''), ' ',(case gender_id when 1 then '男性' when 2 then '女性' else '' end), ' ')) STORED"); }); } migrationを実行する php artisan migrate DDLを確認し,shopsテーブルにfree_wordカラムがなければOKです ngram-docker-laravel docker-compose exec db bash mysql -u root -p Enter password: password mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | laravel_local | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.01 sec) mysql> use laravel_local; mysql> show tables; +-------------------------+ | Tables_in_laravel_local | +-------------------------+ | failed_jobs | | migrations | | password_resets | | personal_access_tokens | | shops | | users | +-------------------------+ 6 rows in set (0.00 sec) DESC shops; +------------+-----------------+------+-----+-------------------+-----------------------------------------------+ | Field | Type | Null | Key | Default | Extra | +------------+-----------------+------+-----+-------------------+-----------------------------------------------+ | id | bigint unsigned | NO | PRI | NULL | auto_increment | | name | varchar(255) | NO | | NULL | | | age | int unsigned | NO | | NULL | | | gender_id | smallint | NO | | NULL | | | created_at | timestamp | NO | | CURRENT_TIMESTAMP | DEFAULT_GENERATED | | updated_at | timestamp | NO | | CURRENT_TIMESTAMP | DEFAULT_GENERATED on update CURRENT_TIMESTAMP | +------------+-----------------+------+-----+-------------------+-----------------------------------------------+ 6 rows in set (0.01 sec) 2.ダミーデータを投入する 実行するSeedファイル backend/database/seeders/DummyShopsSeeder.php <?php namespace Database\Seeders; use App\Models\Shop; use Illuminate\Database\Seeder; class DummyShopsSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { $data = [ [ 'name' => 'サンプル太郎', 'age' => 25, 'gender_id' => 1 ], [ 'name' => 'サンプル花子', 'age' => 30, 'gender_id' => 2 ], [ 'name' => 'サンプル二郎', 'age' => 20, 'gender_id' => 1 ], ]; (new Shop())->query()->insert($data); } } Seedファイルを実行 php artisan db:seed --class=DummyShopsSeeder Seed結果を確認し登録できていれば成功です mysql> select * from shops; +----+--------------------+-----+-----------+---------------------+---------------------+ | id | name | age | gender_id | created_at | updated_at | +----+--------------------+-----+-----------+---------------------+---------------------+ | 1 | サンプル太郎 | 25 | 1 | 2022-01-07 04:19:43 | 2022-01-07 04:19:43 | | 2 | サンプル花子 | 30 | 2 | 2022-01-07 04:19:43 | 2022-01-07 04:19:43 | | 3 | サンプル二郎 | 20 | 1 | 2022-01-07 04:19:43 | 2022-01-07 04:19:43 | +----+--------------------+-----+-----------+---------------------+---------------------+ 3 rows in set (0.01 sec) 3.free_wordカラムを追加する 再度free_wordカラムを追加するmigrationを作成します php artisan make:migration add_free_word_column_to_shops --table=shops migrationファイルを定義します backend/database/migrations/2022_01_07_162519_add_free_word_column_to_shops.php class AddFreeWordColumnToShops extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::table('shops', function (Blueprint $table) { DB::statement("ALTER TABLE shops ADD free_word TEXT"); DB::statement("ALTER TABLE shops ADD FULLTEXT index ftx_free_word (free_word) with parser ngram"); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::table('shops', function (Blueprint $table) { $table->dropColumn('free_word'); }); } } migrationを実行する php artisan migrate DDLを確認しshopsテーブルにfree_wordカラムが追加されていればOKです ngram-docker-laravel docker-compose exec db bash mysql -u root -p Enter password: password mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | laravel_local | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.01 sec) mysql> use laravel_local; mysql> show tables; +-------------------------+ | Tables_in_laravel_local | +-------------------------+ | failed_jobs | | migrations | | password_resets | | personal_access_tokens | | shops | | users | +-------------------------+ 6 rows in set (0.00 sec) mysql> select * from shops; +----+--------------------+-----+-----------+---------------------+---------------------+-----------+ | id | name | age | gender_id | created_at | updated_at | free_word | +----+--------------------+-----+-----------+---------------------+---------------------+-----------+ | 1 | サンプル太郎 | 25 | 1 | 2022-01-08 01:54:17 | 2022-01-08 01:54:17 | NULL | | 2 | サンプル花子 | 30 | 2 | 2022-01-08 01:54:17 | 2022-01-08 01:54:17 | NULL | | 3 | サンプル二郎 | 20 | 1 | 2022-01-08 01:54:17 | 2022-01-08 01:54:17 | NULL | +----+--------------------+-----+-----------+---------------------+---------------------+-----------+ 4.登録・更新イベントをディスパッチする処理を追加する さて,ここまでで全文検索用のカラムの作成が完了しました。 ですが見ての通りfree_wordカラムはNULLなのでこれでは全文検索ができません。 そこで、登録・更新イベントをディスパッチして自動的にfree_wordカラムに追加する値を生成していきます オブザーバーを作成します php artisan make:observer ShopObserver --model=Shop オブサーバーを定義 <?php namespace App\Observers; use App\Models\Shop; class ShopObserver { /** * save()イベントを検知する * @param Shop $shop * @return void */ public function saved(Shop $shop) { $collect = collect($shop); $id = $collect->get('id'); $name = $collect->get('name'); $age = $collect->get('age'); $genderId = $collect->get('gender_id'); if (!is_null($genderId)) { $gender = (int)$genderId === 1 ? '男性' : '女性'; } else { $gender = null; } $freeWord = $age . ' ' . $id . ' ' . $name . ' ' . $gender; $data = [ 'id' => $id, 'name' => $name, 'age' => $age, 'gender_id' => $genderId, 'free_word' => $freeWord, ]; (Shop::query()->where('id', $id))->update($data); } } オブサーバーを登録 backend/app/Providers/EventServiceProvider.php class EventServiceProvider extends ServiceProvider { /** * The event listener mappings for the application. * * @var array<class-string, array<int, class-string>> */ protected $listen = [ Registered::class => [ SendEmailVerificationNotification::class, ], ]; /** * Register any events for your application. * * @return void */ public function boot() { Shop::observe(ShopObserver::class); } } 5.Artisanコマンドを作成する コマンド生成 php artisan make:command UpdateFreeWordByShop コマンド定義 class UpdateFreeWordByShop extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'update:free-word-by-shop'; /** * The console command description. * * @var string */ protected $description = 'shopsテーブルのfree_wordを登録するコマンド'; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return void */ public function handle() { $updateTarget = Shop::query()->pluck('id'); foreach ($updateTarget as $id) { $target = Shop::find($id); $result = $target->save(); if (!$result) { echo "店ID:{$id}の登録中にエラーが発生しました。終了します\n"; exit(); } echo "{$id}完了\n"; } echo "処理完了。終了します。\n"; exit(); } } 6.作成したArtisanコマンドを実行してfree_wordカラムにデータを投入する 作成したコマンドが登録されていることを確認 php artisan update update:free-word-by-shop shopsテーブルのfree_wordを登録するコマンド コマンドを実行する php artisan update:free-word-by-shop 1完了 2完了 3完了 処理完了。終了します。 free_wordにデータが登録されているかを確認 free_wordに値が登録されていれば成功です! mysql> select * from shops; +----+--------------------+-----+-----------+---------------------+---------------------+--------------------------------+ | id | name | age | gender_id | created_at | updated_at | free_word | +----+--------------------+-----+-----------+---------------------+---------------------+--------------------------------+ | 1 | サンプル太郎 | 25 | 1 | 2022-01-08 01:54:17 | 2022-01-07 19:25:39 | 25 1 サンプル太郎 男性 | | 2 | サンプル花子 | 30 | 2 | 2022-01-08 01:54:17 | 2022-01-07 19:25:39 | 30 2 サンプル花子 女性 | | 3 | サンプル二郎 | 20 | 1 | 2022-01-08 01:54:17 | 2022-01-07 19:25:39 | 20 3 サンプル二郎 男性 | +----+--------------------+-----+-----------+---------------------+---------------------+--------------------------------+ 3 rows in set (0.00 sec) おわりに 読んでいただきありがとうございます。 今回の記事はいかがでしたか? ・こういう記事が読みたい ・こういうところが良かった ・こうした方が良いのではないか などなど、率直なご意見を募集しております。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

make コマンドで環境ごとに Google Cloud Run をデプロイする (docker build に引数を渡す)

以下の例は、環境をプロジェクトで別けていて、develop / production といったサフィックスを持っているという想定です。 環境の変数名は適当に PROJECT_ENV にしてます。 まず、Dockerfile に以下を追記します。 Dockerfile # ...略... # PROJECT_ENV という引数を受け取れるようにする ARG PROJECT_ENV # 環境変数 PROJECT_ENV に 引数で受け取った値を横流しする # 環境変数として使う必要がなければ不要 ENV PROJECT_ENV $PROJECT_ENV # ...略... cloudbuild.yaml を用意します。 gcloud builds submit コマンドで完結させたかったんですが、どうやらできないようです。 cloudbuild.yaml steps: - name: 'gcr.io/cloud-builders/docker' args: [ 'build', '--build-arg', 'PROJECT_ENV=$_PROJECT_ENV', # substitutions に指定されている変数を `docker build` に横流しする '-t', 'gcr.io/your-project-${_PROJECT_ENV}/your-service-name', '.' ] substitutions: _PROJECT_ENV: develop # 変数のデフォルトの値を指定 images: ['gcr.io/your-project-${_PROJECT_ENV}/your-service-name'] ビルド関連の準備が整ったので、Makefile を書きます。 Makefile # 環境変数のデフォルトの値を指定 PROJECT_ENV=develop pre: # e という arg を受け取っていたらその文字列を代入 # - 実際に運用するときは develop / production など、 # 特定の文字列しか受け取れないようにする処理とかを入れたほうがいいかも ifdef e PROJECT_ENV=${e} endif deploy-setup: pre gcloud config set project your-project-${PROJECT_ENV} ; deploy: pre @make deploy-setup ;\ cd ./path/to/your-app ;\ gcloud builds submit --config=cloudbuild.yaml \ # 用意しておいた yaml を使って build する --substitutions=_PROJECT_ENV="${PROJECT_ENV}" ;\ # substitutions の _PROJECT_ENV に値を横流しする gcloud run deploy your-service-name \ --image gcr.io/your-project-${PROJECT_ENV}/your-service-name \ --platform managed \ --region asia-northeast1 ; # region はテキトー これで、 $ make deploy で develop 環境へのデプロイ、 $ make deploy -e=production で production 環境へのデプロイが可能になります。   終 制作・著作 ━━━━━  ⓁⓈⓅ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む