- 投稿日:2021-01-29T23:52:31+09:00
【独学・未経験】Nuxt.js, Rails, Docker, AWS ECS(Fargate), TerraformなSPAポートフォリオを作成しました。
はじめに
プログラミング歴半年(独学)の実務未経験者がSPAなポートフォリオを制作しましたので紹介していきたいと思います!
今後もアップデートしていくのでフィードバックなど頂けますと嬉しいです。
記事の最後には、お世話になったWebサイトや教材をまとめておきましたので参考になれば幸いです。作者のスペック
年齢は27歳で今までにプログラミング経験は全くなし。
サーバーサイドエンジニアを目指してプログラミング学習中の初学者です。
本記事を執筆している時点でプログラミング学習期間は半年。(2021/1/29時点)
ポートフォリオに関わる技術のキャッチアップをしながら約4ヶ月程かけて完成させました。ポートフォリオ制作に着手した時点では、ProgateとRailsチュートリアルを終えた程度の実力。
至る所に詰みポイントがありひたすらググりまくって問題解決してました。(Google先生は神)アプリの概要
制作したアプリケーションがこちら。
『ガジェコミ!』はガジェット好きが集まれるSNS型のWebアプリケーションです。
簡単に言ってしまえば『Twitterクローン』に近いものなので、SNSに必要な機能を重点的に実装済み。
スマホ利用を想定しているのでモバイルからも気軽にお試し下さい!(ゲストログイン有ります)
トップページ
レスポンシブ対応
スマホ利用も想定したUI設計。
Ajax処理
ネストした要素でもAjaxに動作します。
例) 『コメントアイコンをタップ → コメント欄を表示 → 既にあるコメントに返信』
ポートフォリオに使用した技術
各バージョン
- Ruby 2.7.1
- Rails 6.0.3.4
- nuxt 2.14.6
- @nuxtjs/vuetify 1.11.2
- Docker 19.03.13
- docker-compose 1.27.4
- Terraform 0.14.3
フロントエンド
名称 説明 Nuxt.js (SSR mode) フロントエンドフレームワーク Vuetify UIコンポーネント Firebase Authentication JWTを用いたログイン・ログアウト
Vuetifyコンポーネントを導入することで、スマホ利用を想定したレスポンシブデザインを実現。
Vuexストアでステート管理。
個人情報(メールアドレス・パスワード)は、外部API(Firebase Authentication)に保存する仕組みで、外部APIで発行されるJWTをSession Storageに保存してログイン・ログアウト機能を実装しました。
未ログイン状態でアクセスして欲しくないページ( /users/editなど )へのアクセス対策には、Nuxt.jsのmiddlewareを活用することで自動的にリダイレクトするようにしました。
ログイン状態でアクセスして欲しくないページ (ログインページ, 新規作成ページ) へのアクセスも同じくリダイレクトします。
バックエンド
名称 説明 Rails (API mode) APIサーバーとして利用 PostgreSQL データベース
RailsはAPIサーバーとして利用しており、フロントエンドコンテナからのリクエストに対してJSONデータを返しています。
画像データはActiveStorage経由でS3バケットに保存。
その他のデータはRDSに保存。
個人情報(メールアドレス・パスワード)は外部API(Firebase Authentication)に保存しているので、バックエンド側にセンシティブな情報を保存しない仕組みです。
テストコード
名称 説明 Jest フロントエンドテスト, Vuexストアの動作を少しだけ RSpec バックエンドテスト, バリデーションとアソシエーションのテストのみ
- CodePipelineのTestステージで実行するテストコードです。
インフラ
名称 説明 ECS Fargate サーバーレスな本番環境, オートスケール CodePipeline CI/CD環境 RDS 本番用DB(PostgreSQL) Docker, Docker-compose コンテナ環境 Github バージョン管理 Terraform 本番用インフラをコード管理
ローカル開発環境からデプロイまで一貫してDockerを使用。
ALBを通すことで常時SSL通信化。
CodePipelineは、 『Sourceステージ => Testステージ => Buildステージ => Deployステージ』の順で実行され、Testステージで問題が発生した場合は当該ソースでのDeployは実行されません。
本番環境の環境変数については SSM で管理。『システム環境変数 => Terraform => SSM => 各AWSサービス』というフローで環境変数を受け渡しています。
インフラ構成図
インフラの全体像をまとめたものがこちら。
RDSにはPostgreSQLを採用し、画像を除いたデータを保管。
画像データはS3に保管しています。ER図
一貫性のあるテーブル名称を意識しました。
アプリの機能紹介
0. 機能一覧
機能名 説明 ユーザー機能 新規登録、登録内容変更、アバター登録、ログイン、ログアウト、フォロー つぶやき機能 投稿、編集、削除、画像複数枚登録 つぶやきコメント機能 つぶやきに対してコメント投稿、コメントへのリプライ投稿、削除、画像複数枚登録 つぶやきいいね機能 つぶやきをいいねできる、マイページのいいねタブにいいねしたつぶやきを一覧表示 掲示板機能 質問掲示板、雑談掲示板の作成、編集、削除、画像複数枚登録 掲示板コメント機能 掲示板に対してコメント投稿、コメントへのリプライ投稿、削除、画像複数枚登録 私物ガジェット機能 登録、編集、削除、画像複数枚登録 フィード機能 つぶやき新着表示、タイムライン表示、タグフィード表示 タグ管理機能 つぶやき・掲示板・私物ガジェットにはタグを登録可能、タグをタップしてタグ詳細ページを表示、タグ詳細ページではタグを含むコンテンツを表示 検索機能 各コンテンツを検索可能 通知機能 つぶやきにいいね・コメント、掲示板にコメント、他ユーザーからフォローされると通知を表示 管理者モード Godmode のトグルスイッチをONにすると、一時的に管理者権限が有効化、各コンテンツの削除メニューが表示される 1. ユーザー機能
登録・編集・削除
メールアドレスとパスワードを入力するだけでアカウント作成できます。
メールアドレス確認機能は未実装。VeeValidateを使用してフォームにバリデーションを設定しています。
詳細設定ページで登録情報を編集できます。
ユーザーにはアバターを設定できます。
アバター画像は各コンテンツで表示されます。
2. つぶやき機能
投稿・編集・削除
つぶやき編集は即時反映されます。
つぶやき削除は即時反映されます。
タグ付け
つぶやきにはタグを複数登録できます。
コメント
つぶやきにはコメントすることができます。
コメントに返信できます。
コメントは削除のみ可能です。編集機能はありません。
親コメントを削除すると子コメントも削除されます。いいね
つぶやきにいいねできます。
3. 掲示板機能
作成・編集・削除
掲示板作成は即時反映されます。
掲示板編集は即時反映されます。
掲示板削除は即時反映されます。
タグ付け
掲示板にはタグを複数登録できます。
掲示板タイプ
『雑談』『質問』を選択できます。
コメント
掲示板にはコメントすることができます。
コメントに返信できます。
コメントは削除のみ可能です。編集機能はありません。
親コメントを削除すると子コメントも削除されます。4. 私物ガジェット機能
登録・編集・削除
自分の私物ガジェットやお気に入りアイテムを登録できます。
登録したガジェットは一覧ページでは『みんなのガジェット』として新着表示されます。ガジェット編集は即時反映されます。
ガジェット削除は即時反映されます。
タグ付け
私物ガジェットにはタグを複数登録できます。
5. フィード機能
つぶやきを一覧表示します。
無限スクロールで順次読み込みます。<タブによって表示する内容が異なります>
- 新着順 => 全てのつぶやきを新着順で表示
- タイムライン => フォロー済みユーザーのつぶやきのみ新着順で表示
- タグフィード => フォロー済みタグを含むつぶやきのみ新着順で表示
6. タグ管理機能
タグをフォローすることができます。
タグフィードに表示したいタグをフォローします。つぶやき・掲示板・私物ガジェットはタグ付けすることができます。
タグをタップするとタグ詳細ページに遷移し、タグを含むつぶやき・掲示板・私物ガジェット・フォローしているユーザーの一覧を表示します。7. 検索機能
検索ページでは、検索フォームに入力した内容に合わせて結果がリアルタイムに表示される機能を実装しております。
8. 通知機能
つぶやき・掲示板・ユーザーフォローにおいて、イベントが発生すると通知が表示されます。
新着通知
新しい通知が発生すると、ヘッダー内のベルアイコンにバッジが表示されます。
タップすると新しい通知がリスト表示され、通知をタップするとイベント発生元へ画面遷移します。通知一覧
通知一覧をタップすると一覧ページへ画面遷移します。
通知一覧ページでは、今まで受け取った全ての通知を表示します。9. ゲストユーザー機能
ユーザー専用機能を簡単に利用できるように、ゲストユーザーログイン機能を実装しています。
『ゲストユーザーとしてログイン』をタップするだけです。
未ログイン状態でユーザー専用機能にアクセスすると、ゲストユーザーログインを促すダイアログを表示するようにしております。
10. God mode
一時的に管理者権限を有効にするモードです。(管理者という概念が存在することを確認して頂くためのモードです。)
DB内 の Userモデルの adminカラム の true/false で 各ユーザーの管理者権限を管理しておりますが、God modeではVuexストアの値を一時的に変更して管理者権限を有効化しています。(DB上には保存されないのでブラウザ再読み込みでfalseに戻ります。)
つぶやき・掲示板・私物ガジェットにはそれぞれ『管理メニュー』が設定されており、作成者本人にのみ表示される仕組みです。
God mode を有効化にすると他のユーザーが作成したコンテンツでも『管理メニュー』を表示するようになり、『削除のみ』実行可能となります。
制作を終えてみて
ポートフォリオのアップデートは今後も行いますが、いったん区切りがついたのでホッとしています。
制作中に苦労したポイントをまとめてみると以下の内容で、主に初期学習のタイミングで壁が何度も現れました。
壁 内容 フロントエンドとバックエンドを分離した開発環境の構築 仮想コンテナの基礎知識やポートフォワーディングでつまりました。初めからdocker-composeを使うことをオススメします。 環境変数の受け渡し ローカル環境、本番環境のインフラ構成に合わせて環境変数の渡し方に工夫が必要でした。 Vuetifyモジュールの導入 Nuxt.jsの初期セットアップでVuetifyを選択するとエラー発生。VuetifyなしでNuxt.jsをセットアップ + 後からVuetifyを導入 + おまじないが必要で詰みました。 SSRモードで動作するNuxt.jsのライフサイクル SSRでSPA用コードを実行するとライフサイクルが一部違うので正常に動作しません。 AxiosモジュールのSSRモードでの挙動 SPAとSSRではAxiosのエンドポイントの設定に違いがあり詰みました。 Firebase Authenticationの導入 SSRモードでの解説記事が少なく、動作させるまでに苦労しました。 SSRモードでは動作しないプラグイン ポートフォリオで利用した『@johmun/vue-tags-input』がSSRモードでは動作しなかったので、特別なおまじないが必要でした。 親コンポーネントと子コンポーネントのデータ受け渡し props, emitの概念の理解に苦戦しました。 Vuexストアの扱い方 断片的な解説記事が多くて理解するのに時間が掛かりました。 終わらないN+1対策 アソシエーションの絡んだデータ取得をするたびに苦労しました。 ECS Fargateでのインフラ構築 FargateはSSHできないのでエラーログの取得やトラブルシュートに手間取りました。CloudWatchなどを利用して確実にログを取れる環境を作らないと、どこに問題があってコンテナが動いていないのか判断できなくて詰みます。 特に厳しかったのがECSデプロイでして、途中何度も諦めそうになりましたが何とかやり終えることができました...。(インフラ難しい)
何とか形になったものの、書いているコードは実務レベルから比べると『その場しのぎ』程度だと思いますし、
プログラミングにおける基礎知識が抜けていると思い知らされる場面も多々ありました。(特に学習初期の理解力)正直なところ、Nuxt.js や Rails という『ツール』を何となく使えている、というのが現時点での実力だと思います。
今後について
ポートフォリオが完成したので就活を始めるために準備を進めています!
就活以外では、課題である基礎力を伸ばすために基本情報技術者やJavaSliverなどの取得を目指して資格勉強も進めていくつもりです。(オススメ教材などあれば教えて欲しいです)
ただのポートフォリオ紹介記事ですが、最後までお付き合い頂きましてありがとうございました!
Twitterもやってますので是非フォローもよろしくお願いします!
関連リンク
お世話になった書籍や教材
ポートフォリオ制作中に何度もお世話になった資料一覧です。
これがなければ完成できていなかったので本当に感謝しています。ありがとうございました!
媒体 資料名 学習内容 Web Progate Ruby, Rails, HTML, CSS, JavaScript...などの基礎を学習 Web Railsチュートリアル いわずもがな、Railsの基礎、Herokuデプロイ、AWS S3、GitHubの扱いなどを学習 Web JavaScript Primer DOM操作以外のJavaScriptの基礎を学習 Web Rails + Nuxt.js + Docker なアプリを作ってみよう 神記事です。めちゃめちゃ参考になりました。ただしSPAモードなのでSSRモードで制作する場合は工夫が必要。 Web 独学プログラマ (Docker+Rails6+Nuxt.js+PostgreSQL)=>Heroku 環境構築~デプロイまでの手順書 神記事です。特に環境構築の手法がめちゃめちゃ参考になります。 Web Pikawaka Railsの基礎はここ見れば大体全部載ってます。マジでわかりやすくて助かりました。 Web SSRモードのNuxtでのFirebase認証 この記事とGitHubリポジトリがなければ実装するの諦めてました。本当にありがとうございます。 書籍 たのしいRuby Rubyの基礎を学習 書籍 Ruby on Rails速習実践ガイド Railsでよく使うコマンドやRailsの基礎を学習 書籍 プロを目指す人のためのRuby入門 実践的なRubyについて学習 書籍 Rubyによるクローラー開発技法 Rubyだけでスクレイピングアプリを作れます。学んだ基礎知識をアウトプットするために使用しました。 書籍 Nuxt.jsビギナーズガイド Nuxt.jsの基礎学習。Vue.jsの経験がないと難しいかも。 書籍 速習Vue.js3 Vue.jsの基礎学習。単一コンポーネント形式のサンプルが少ないので、これだけでは不十分かも。 書籍 実践Terraform AWSにおけるシステム設計とベストプラクティス 神本。これがなければECSデプロイできませんでした。感謝しています。 書籍 はじめての人のためのTerraform for AWS Terraformを全く触ったことない人向けの書籍。サンプルコードがちゃんと動作するので感じを掴むのに最適。 書籍 CircleCI実践入門 CI/CDってなに?って状態で感じを掴むために使用。結局CodePipelineで実装したけど自動テストの雰囲気が掴めて良かった。 書籍 Amazon Web Services 基礎からのネットワーク&サーバー構築 AWSの基礎学習にぴったり。EC2での解説なのでECSについては別途学習する必要あり。 書籍 Docker/Kubernetes実践コンテナ開発入門 Dockerの基礎学習。初心者向けの章節まで読めば十分でした。 書籍 達人に学ぶSQL徹底至難書 実践的なSQLを学習。 書籍 Webを支える技術 ネットワークの概念がイマイチ理解できてないときに使用。 書籍 GitHub実践入門 GitHubの基礎学習
- 投稿日:2021-01-29T23:52:31+09:00
【独学・未経験】Nuxt.js, Rails, Docker, AWS ECS(Fargate), Terraformな完全SPAポートフォリオを制作しました!
概要
プログラミング歴半年(独学)の実務未経験者が完全SPAなポートフォリオを制作しましたので紹介していきたいと思います!
記事の最後には初学者が詰まるであろうポイントもまとめておきましたので、参考になれば幸いです。作者のスペック
年齢は27歳(今年で28歳)で今までにプログラミング経験はありませんでした。
今現在はエンジニアを目指して独学で学習中でして、本記事を執筆している時点でプログラミング学習期間は半年間です。
ポートフォリオに関わる技術のキャッチアップをしながら約4ヶ月程かけてポートフォリオを完成させました。ポートフォリオ制作に着手した時点では、ProgateとRailsチュートリアルを終えた程度の実力。
至る所に詰みポイントがありひたすらググりまくって問題解決してました。(Google先生は神)ポートフォリオ紹介
『ガジェコミ!』はガジェット好きが集まれるSNS型のWebアプリケーションです。
Nuxt.js x Rails という組み合わせて制作した完全SPAアプリケーションなので、同じような構成で制作される方の参考になれば幸いです!
ガジェコミ!
ポートフォリオに使用した技術
フロントエンド
- Nuxt.js(SSR mode) => フロントエンドフレームワーク
- Vuetify => UIコンポーネント
- Firebase Authentication => JWTを用いたログイン・ログアウト
バックエンド
- Rails(API mode) => APIサーバーとして実行
- PostgreSQL => データベース
テストコード
- フロントエンド => Jest(Vuexストアの動作を少しだけ)
- バックエンド => RSpec(バリデーションとアソシエーションのテストのみ)
インフラ
- AWS ECS Fargate => サーバーレスな本番環境、オートスケール
- AWS CodePipeline => CI/CD環境
- AWS RDS => 本番用DB(PostgreSQL)
- AWS S3 => 本番環境の画像データ保存用 x 1, CodePipelineのアーティファクト保存用 x 1
- AWS Route53 => ドメイン取得
- AWS ACM => SSL証明書の発行
- AWS ALB => ロードバランサー
- AWS ECR => 本番用Dockerイメージ管理
- AWS SSM => 本番用環境変数の一括管理
- Docker, Docker-compose => コンテナ環境
- Github => バージョン管理
- Terraform => 本番用インフラをコード管理
インフラ構成図
ER図
技術を選定した理由
- 採用担当者の目に留まるようなポートフォリオを制作するため
- 自分自身がプログラミングが好きかどうかを推し量るために、あえて高難度な技術を選定した
- 主流となりつつある『フロントエンドとバックエンドを切り離したWebアプリケーション』を制作してみたかったから
- 完全SPAアプリケーションの制作を経験してみたかったから
- 未経験な技術のキャッチアップを独学でどのように進めるか身を以て経験したおきたかったから
技術面での詳解
フロントエンド
Nuxt.js を採用し、フロントエンドとバックエンドを分離した完全SPAアプリケーションを実現しております。
Nuxt.jsは、SEO面で有効とされるSSRモード(サーバーサイドレンダリング)で実行しております。
Vuetifyコンポーネントを導入することで、スマホ利用を想定したレスポンシブデザインを実現しています。
Vuexストアでステート管理をしており、ほぼ全ての動作をAjax化しました。(一部未完)
個人情報(メールアドレス・パスワード)の安全性については、外部API(Firebase Authentication)に任せることで確保しています。
Firebase Authentication で発行されるJWTをブラウザのSession Storageに保管することで、ログイン・ログアウトができる仕組みです。
未ログイン状態でアクセスして欲しくないページ( /users/editなど )へのアクセス対策には、Nuxt.jsのmiddlewareを活用することで自動的にリダイレクトするようにしました。
ログイン状態でアクセスして欲しくないページ (ログインページ, 新規作成ページ) へのアクセスも同じくリダイレクトします。
バックエンド
Rails(APIモード)で実行しており、フロントエンドコンテナからのリクエストに対してJSONデータを返しています。
個人情報(メールアドレス・パスワード)は外部API(Firebase Authentication)に保存しているので、バックエンド側にセンシティブな情報を保存しない仕組みです。
『N+1問題』への対策を施しているため、アソシエーションがネストしているコンテンツへアクセスしてもレスポンスが遅れません。
一貫性のあるテーブル名称を意識しました。
インフラ
ローカル開発環境から一貫してDockerを使用しており、ECSデプロイまでを想定した開発フローを実践しました。
AWS ECS(Fargate)で本番環境をサーバーレスで運用しております。
ALBを通すことで常時SSL通信を実現しました。
AWS CodePipelineを使用したCI/CDパイプラインを構築しております。
CodePipelineは、 『Sourceステージ => Testステージ => Buildステージ => Deployステージ』の順で実行され、Testステージで問題が発生した場合は当該ソースでのDeployは実行されません。
Terraformを用いて AWSの本番環境は全てコードで管理しています。
本番環境の環境変数については AWS SSM で管理しており、『システム環境変数 => Terraform => SSM => 各AWSサービス』というフローで環境変数を受け渡しています。
アプリの機能紹介
一般的なSNS型アプリケーションを意識して制作しているので、複雑なビジネスロジックが絡むような機能は残念ながら実装できておりません...。
とはいえレスポンシブ対応やAjax化に力を入れているので、実際に使ってみてください!
1. ユーザー機能
登録・編集・削除
メールアドレスとパスワードを入力するだけでアカウント作成できます。
メールアドレス確認機能は未実装。VeeValidateを使用してフォームにバリデーションを設定しています。
詳細設定ページで登録情報を編集できます。
ユーザーにはアバターを設定できます。
アバター画像は各コンテンツで表示されます。
2. つぶやき機能
投稿・編集・削除
つぶやき編集は即時反映されます。
つぶやき削除は即時反映されます。
タグ付け
つぶやきにはタグを複数登録できます。
コメント
つぶやきにはコメントすることができます。
コメントに返信できます。
コメントは削除のみ可能です。編集機能はありません。
親コメントを削除すると子コメントも削除されます。いいね
つぶやきにいいねできます。
3. 掲示板機能
作成・編集・削除
掲示板作成は即時反映されます。
掲示板編集は即時反映されます。
掲示板削除は即時反映されます。
タグ付け
掲示板にはタグを複数登録できます。
掲示板タイプ
『雑談』『質問』を選択できます。
コメント
掲示板にはコメントすることができます。
コメントに返信できます。
コメントは削除のみ可能です。編集機能はありません。
親コメントを削除すると子コメントも削除されます。4. 私物ガジェット機能
登録・編集・削除
自分の私物ガジェットやお気に入りアイテムを登録できます。
登録したガジェットは一覧ページでは『みんなのガジェット』として新着表示されます。ガジェット編集は即時反映されます。
ガジェット削除は即時反映されます。
タグ付け
私物ガジェットにはタグを複数登録できます。
5. フィード機能
つぶやきを一覧表示します。
無限スクロールで順次読み込みます。<タブによって表示する内容が異なります>
- 新着順 => 全てのつぶやきを新着順で表示
- タイムライン => フォロー済みユーザーのつぶやきのみ新着順で表示
- タグフィード => フォロー済みタグを含むつぶやきのみ新着順で表示
6. タグ管理機能
タグをフォローすることができます。
タグフィードに表示したいタグをフォローします。つぶやき・掲示板・私物ガジェットはタグ付けすることができます。
タグをタップするとタグ詳細ページに遷移し、タグを含むつぶやき・掲示板・私物ガジェット・フォローしているユーザーの一覧を表示します。7. 検索機能
検索ページでは、検索フォームに入力した内容に合わせて結果がリアルタイムに表示される機能を実装しております。
8. 通知機能
つぶやき・掲示板・ユーザーフォローにおいて、イベントが発生すると通知が表示されます。
新着通知
新しい通知が発生すると、ヘッダー内のベルアイコンにバッジが表示されます。
タップすると新しい通知がリスト表示され、通知をタップするとイベント発生元へ画面遷移します。通知一覧
通知一覧をタップすると一覧ページへ画面遷移します。
通知一覧ページでは、今まで受け取った全ての通知を表示します。9. ゲストユーザー機能
ユーザー専用機能を簡単に利用できるように、ゲストユーザーログイン機能を実装しています。
『ゲストユーザーとしてログイン』をタップするだけです。
未ログイン状態でユーザー専用機能にアクセスすると、ゲストユーザーログインを促すダイアログを表示するようにしております。
10. God mode
一時的に管理者権限を有効にするモードです。(管理者という概念が存在することを確認して頂くためのモードです。)
DB内 の Userモデルの adminカラム の true/false で 各ユーザーの管理者権限を管理しておりますが、God modeではVuexストアの値を一時的に変更して管理者権限を有効化しています。(DB上には保存されないのでブラウザ再読み込みでfalseに戻ります。)
つぶやき・掲示板・私物ガジェットにはそれぞれ『管理メニュー』が設定されており、作成者本人にのみ表示される仕組みです。
God mode を有効化にすると他のユーザーが作成したコンテンツでも『管理メニュー』を表示するようになり、『削除のみ』実行可能となります。
11. レスポンシブデザイン
Vuetifyを活用したレスポンシブデザインで、スマホでも扱いやすいUI/UXを意識しました。
サブメニューとタブメニューを組み合わせることで、画面遷移ゼロで複数のコンテンツにアクセスできます。
つまったポイント
フロントエンドとバックエンドを分離した開発環境の構築
=> 仮想コンテナの基礎知識やポートフォワーディングでつまりました。
=> 初めからdocker-composeを使うことをオススメします。環境変数の受け渡し
=> 渡せているはずなのに!という場面が何度もありました。各ソフトの仕様を把握していないと詰みます。SSRモードで動作するNuxt.jsのライフサイクル
=> SSRでSPA用コードを実行するとライフサイクルが一部違うので正常に動作しません。SSRモードでは動作しないプラグイン
=> ポートフォリオで利用した『@johmun/vue-tags-input』がSSRモードでは動作しなかったので、特別なおまじないが必要でした。Vuexストアの扱い方
=> 断片的な解説記事が多くて理解するのに時間が掛かりました。親コンポーネントと子コンポーネントのデータ受け渡し
=> Vue.jsの経験がある方であれば問題ないかと思います。Vuetifyモジュールの導入
=> Nuxt.jsの初期セットアップでVuetifyを選択するとエラー発生
=> VuetifyなしでNuxt.jsをセットアップ + 後からVuetifyを導入 + おまじないが必要で詰みました。AxiosモジュールのSSRモードでの挙動
=> SPAとSSRではAxiosのエンドポイントの設定に違いがあり詰みました。ECS Fargateでのインフラ構築
=> FargateはSSHできないのでエラーログの取得やトラブルシュートに手間取りました。
=> CloudWatchなどを利用して確実にログを取れる環境を作らないと、どこに問題があってコンテナが動いていないのか判断できなくて詰みます。制作を終えてみて
ポートフォリオのアップデートは今後も行いますが、いったん区切りがついたのでホッとしています。
特に厳しかったのがECSデプロイでして、途中何度も諦めそうになりましたが何とかやり終えることができました...。(インフラ難しい)
苦労した分だけ喜びも大きくなると言われますが、自作アプリにアクセスできた瞬間は嬉しかったですね!
ただし、書いているコードは実務レベルから比べると『その場しのぎ』程度だと思いますし、
プログラミングにおける基礎知識が抜けていると思い知らされる場面も多々ありました。(特に学習初期の理解力)正直なところ、Nuxt.js や Rails という『ツール』を何となく使えている、というのが現時点での実力だと思います。
今後について
ポートフォリオが完成したので就活を始めていきます。
課題である基礎力を伸ばすために、就活と同時に基本情報技術者やJavaSliverなどの取得を目指して資格勉強も進めていくつもりです。
コロナ渦で未経験からエンジニアになることが難しいと言われてますし、引き続き気合を入れて頑張っていきたいと思います。
ただのポートフォリオ紹介記事ですが、最後までお付き合い頂きましてありがとうございました!
Twitterもやってますので是非フォローもよろしくお願いします!
関連リンク
使用した教材
Progate
ドットインストール
Railsチュートリアル
書籍
Google先生
Githubのソースコード(チュートリアル用アプリケーションのソースを読んでました。)
バージョン
Ruby 2.7.1
Rails 6.0.3.4
nuxt 2.14.6
@nuxtjs/vuetify 1.11.2
Docker 19.03.13
docker-compose 1.27.4
Terraform 0.14.3
- 投稿日:2021-01-29T21:58:38+09:00
ActionView::Template::Error (Webpacker can't find application.css)で沼にハマった時の解決方法
動作環境
- Ruby 2.6.6
- Rails 6.1.0
- Docker 20.10.2
- Heroku
経緯
Railsでアプリを作っており、Herokuにデプロイしたが、その際にHerokuでエラーが発生してしまった。
エラー内容
rails_12factorを追加して、herokuでもrailsのログが見れるようにしている。
ActionView::Template::Error (Webpacker can't find application.css in /myapp/public/packs/manifest.json. Possible causes: 1. You want to set webpacker.yml value of compile to true for your environment 2021-01-25T01:15:35.492764+00:00 app[web.1]: unless you are using the `webpack -w` or the webpack-dev-server. 2021-01-25T01:15:35.492765+00:00 app[web.1]: 2. webpack has not yet re-run to reflect updates. 2021-01-25T01:15:35.492765+00:00 app[web.1]: 3. You have misconfigured Webpacker's config/webpacker.yml file. 2021-01-25T01:15:35.492766+00:00 app[web.1]: 4. Your webpack configuration is not creating a manifest.解決方法
これはapplication.cssをwebpackerで管理できてないことが原因で発生したエラーであった。
試しにエラーが出ていたviewファイルを確認してみる。
application.html.erb<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>そういえばtailwindを導入した際に、記事の内容に従ってstylesheet_linkからpackに書き換えたような、、、
application.html.erb<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>中身を書き換えたら無事に本番環境でデプロイできました!
どうやらstylesheet_pack_tagをつかうと、webpackerからスタイルシートを呼び出すみたいでした。
自分の場合はcssをsprocketsで管理していたので、stylesheet_link_tagを使う必要があったようでした。エラー文のPossible causes以降の文章が答えだと思って、ずっと頭を悩ませていましたが全く別のところに原因が存在していました。
まずはじめに、「webpackerでapplication.cssが見つからない」というところに注目して取り組んでいたらもっと苦労せずに解決できていたと思います。最後に
今回のエラーを経て、
エラー文の怪しいところに注目して解決をするだけではなく、しっかりとエラーの本質を理解して解決に当たるということが重要であると感じました。しかし、ローカル環境では何の問題もなかったのになぜ本番環境のみでエラーが発生したんだろう、、、?
- 投稿日:2021-01-29T21:56:55+09:00
Laravel SailでM1 MacBookのDocker開発環境構築
前置き
ご購入検討中のエンジニアさん
結論、“まだ”M1のMacはおすすめできません。
VagrantやVirtualBox、何を入れるにも一苦労。
導入できたとしても仮想環境は起動しない・・・。
(ARM対応してないものが多い)私はかれこれ2週間近く試してやっとLaravelが動く方法を見つけました。
PHP + MySQL(mariaDB)使いたい方は参考になると思います。
私が実際に試して導入できた方法をご案内します。LaravelSail導入
Laravel公式のDocker 開発環境構築ツール使います。
ターミナルからコマンドを実行。curl -s https://laravel.build/sample-app | bash[sample-app]の部分はお好みで。
起動します
cd sample-app ./vendor/bin/sail upうまく行かない・・・ので
docker-compose.ymlの1箇所修正
image: 'mysql:8.0'の部分を↓
image: 'mariadb'再トライで、無事に起動
./vendor/bin/sail up以上です。
まとめ
今まではHomestead使っていたので、
M1 MacではVirtualBoxとVagrantが動かないのがわかったとき、めっちゃ焦りました。いろいろ調べてLaravelSailというのを見つけて、初めて導入しました。
かなりいいです。Laravel開発のスタンダードになりそうな予感。よし、開発すすめるぞー
開発中のツーリングアプリ
https://touringbook.com/
- 投稿日:2021-01-29T21:32:21+09:00
vscodeでxdebug3のdocker環境を作る
はじめに
2020年11月25日にxdebug 3.0.0がリリースされました。
それを知らずにdockerでxdebugの環境を作って、「ブレイクポイントで止まってくれない、なんでやねん」ってなったのでまとめます。フォルダ構成
xdebug2からxdebug3に移行のために、編集するのはphp.iniだけですがDockerfilやvscodeのlaunch.jsonの解説もします。
docker-composeは省略。php ├── Dockerfile └── php.iniphp.ini
xdebug3ではxdebug2と記述方法が異なるようです。
xdebug2のphp.iniのxdebugの設定
xdebug.remote_host = docker.host.internal xdebug.remote_autostart = 1 xdebug.remote_connect_back = 0 xdebug.remote_enable = 1 xdebug.remote_handler = "dbgp" xdebug.remote_port = 9000xdebug3のphp.iniiのxdebugの設定
xdebug.client_host = docker.host.internal xdebug.mode = debug xdebug.start_with_request = yes xdebug.discover_client_host = 0 xdebug.remote_handler = "dbgp" xdebug.client_port = 9000
xdebug2 xdebug3の変更点 xdebug.remote_host xdebug.client_host に置き換え xdebug.remote_autostart xdebug.mode=debug と xdebug.start_with_request=yes で設定 xdebug.remote_enable xdebug.mode=debugで設定 xdebug.remote_connect_back xdebug.discover_client_host に置き換え xdebug.remote_handler 変更無し xdebug.remote_port xdebug.client_port に置き換え これら以外にも変更点があるので、詳しくはこちらを参照
https://xdebug.org/docs/upgrade_guideDockerfile
FROM php:7.4-fpm SHELL ["/bin/bash","-c"] COPY ./php.ini /usr/local/etc/php/php.ini RUN apt-get update && \ apt-get -y install git unzip libzip-dev libicu-dev libonig-dev && \ pecl install xdebug && \ #xdebugのインストール docker-php-ext-enable xdebug # WORKDIR /workポイントは
pecl install xdebug
とdocker-php-ext-enable xdebug
2021年1月29日、現在では
pecl install xdebug
を行うとxdebug3がインストールされます。xdebugを使うにはイントールされた、xdebug.soのパスをphp.iniに
zend_extension = パス
を追記して、登録しなければなりません。docker-php-ext-enable xdebug
のコマンドを叩くと自動でこの作業を行ってくれます。launch.json
vscode側の設定になります。
"configurations":[ { "name": "XDebug on docker", "type": "php", "request": "launch", "port": 9000,//php.iniで設定したポート番号 "pathMappings": { // {docker上のdocument root}:{ローカルのdocument root} "/work":"${workspaceRoot}/src" } } ]これをlaungh.jsonの中に追記します。
これでxdebugを動かすための環境ができました。
参考にさせて頂いた記事
Dockerで構築したPHP環境をxdebugでデバッグ(vscode)
Xdebug3.0.0がリリースされたので、ver2からの雑な設定コンバート最後に
"port:9000"
のポート番号はvscodeが開いてるんですね。
xdebugが開いているものと思ってました。
- 投稿日:2021-01-29T21:05:59+09:00
Dockerコンテナを作成してコンテナ内をうろうろして削除する
TL;DR
- 記事内で書いていること
- dockerでコンテナ作って壊すコマンド
- container内での操作
- docker networkのつなぎ方
- 記事内で触れてない事
- docker compose
- Kubernetes
起動〜削除
- 起動中のコンテナの情報を表示する
docker ps
❯ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1248ef1b72c5 ubuntu "/bin/bash" 4 seconds ago Up 2 seconds test
コンテナ作成(既存ベースから名前をつけて)
docker run -itd --name 名前 ベースイメージ
# `test`という名前のubuntuベースのコンテナを作る ❯ docker run -itd --name test ubuntu 1248ef1b72c53ba0ab0ff80d68a8787a52076b93e33da2727da1ec31c3a6bc5e ~/applications/docker_practice_qiita/getting-started/app master* ❯ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1248ef1b72c5 ubuntu "/bin/bash" 4 seconds ago Up 2 seconds test 15e29811168f node:12-alpine "docker-entrypoint.s…" 3 hours ago Up 3 hours 0.0.0.0:3000->3000/tcp app_app_1コンテナ作成(dockerfileから作成)
docker build -t コンテナ名 .
-t
= コンテナに名前をつけるコンテナ起動
docker run -dp 3000:3000 コンテナ名 .
-d
= デタッチモード(裏で起動)
-p 3000:3000
= ポート3000番にマッピングする
-e MYSQL_ROOT_PASSWORD=secret
= 環境変数をコンテナに渡す、環境変数名:MYSQL_ROOT_PASSWORD
、値:secret
コンテナ停止&削除
docker rm -f <the-container-id>
未使用のイメージ、コンテナ、ボリューム、ネットワークの全削除
docker system prune -af
イメージ操作
- 未使用のdocker imgaeを削除する
docker image prune -af
コンテナ操作
- ログを確認する
docker logs -f コンテナ名
- コンテナに入る
docker attach コンテナ名
- コンテナ内でbashを立ち上げる
docker exec -it コンテナ名 bash
- コンテナ内で直接コマンドを実行する
docker exec -it コンテナ名 /bin/echo "hi" > hi実行できるコマンドの調べ方 ``` ❯ ls /bin [ cp dd expr launchctl mkdir pwd sleep test bash csh df hostname link mv rm stty unlink cat dash echo kill ln pax rmdir sync wait4path chmod date ed ksh ls ps sh tcsh zsh ```
コンテナのポート転送確認
docker containter port コンテナ名
コンテナのリネーム
docker container rename 古い名前 新しい名前
コンテナ内のファイルコピー
docker container cp コンテナ名:ファイルパス(コピー元) ホストのパス(コピー先)
e.g.aggregatorのファイルをローカルにもってくる
docker container cp test_container:/var/app/foobar ~/Desktop/copied
dockerネットワーク
dockerコンテナ同士が通信するときはDockerネットワークを用いている
- ネットワークの一覧表示
docker network ls
docker networkは指定しない場合、bridge
に接続される
コンテナのネットワーク確認
docker container inspect コンテナ名
ネットワークの作成
docker network create ネットワーク名
ネットワークへの接続(後付け)
docker network connct ネットワーク名 コンテナ名
コンテナ名の指定はIPアドレス、コンテナIDでもOK
inspectするとNetworksに追加されている事がわかる❯ docker container inspect test "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, ========中略======== "DriverOpts": null } }❯ docker network connect todo-app test ❯ docker container inspect test "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, ========中略======== "DriverOpts": null }, "todo-app": { "IPAMConfig": {}, "Links": null, "Aliases": [ "1248ef1b72c5" ], ========中略======== "DriverOpts": {} } ```
ネットワークへの接続(作成時に設定)
docker run -itd --name=名前 --net=ネットワーク名 ベースイメージ
ネットワークからの切断
docker network disconnect ネットワーク名 コンテナ名
ネットワークの詳細確認
docker network inspect ネットワーク名
ネットワークのIPなどが確認できるネットワークからの削除
docker network rm ネットワーク名
参考にさせて頂いた動画
Udemy様の動画を参考に学ばせて頂きました。
所感ですが、初めて学ぶものは書籍より動画とハンズオンで手を動かしていくほうが良いですね。
ゼロからはじめる Dockerによるアプリケーション実行環境構築
- 投稿日:2021-01-29T19:35:24+09:00
Dockerのローカル環境をAWSに載せてみる
はい!こんにちは!
1月中にこの記事を出そうと思ってましたが、なかなかうまくいかないものですね。
2/1に、第3者チェックを通してから2月頭に公開になりそうだ!!!! 現在 1/26 定時ちょい過ぎ今日はdockerについてAWSとの連携のイメージを簡単にご紹介しようと思います。
はじめに
今やもうコンテナって言葉を知らない人はいないと思います!
知らない人はちょこっと調べて、ローカルで実装してみて、動いたタイミングで
「AWSサーバに乗っけたい!」って思ったら参考程度に読んでみてください〜いつぞやのDockerfile(ちょっと復習)
Dockerfile# 基盤のimageファイル選択 FROM php:7.3-fpm # コンテナを立ち上げるときにライブラリ・パッケージのアップデートとインストール RUN apt-get update && apt-get install -y \ ... >>> 省略ローカルでDockerfileやdocker-compose.ymlで
コンテナの設計書書いて構築もできて開発してまーす!この状態でコンテナ化が完了したと思っているそこのあなた!
どうやってサービス展開するの?リリースするの?って疑問が出てくると思います。サービス展開するなら本番環境の構築なども必要ですよね?
以下AWSの複数サービスを使って、ローカルコンテナ環境をクラウドに移行する1手法をご紹介します!
全体のイメージ(自己流)
ごちゃごちゃしていますが、これはどうしてもこうなる部分なんです、、あしからず、、、
使うAWSのサービス
- ECR(コンテナイメージの保存)
- EC2(ECSを乗っけるサーバー) ※本記事では触れませんがALBの設定なども必要です。
- ECS(クラスター 、サービス、タスク)
メインで関係してくるのはこの3つのサービスです!
- CodeCommit
- CodeBuild(CodeDeploy)
さらにCodeCommitとCodeDeployを使えば、CodeCommitへのPUSHを検知して、
コードのビルドができる仕組みも作ることができます。私は挫折しましたが、、、今は運用の中で、ソースコードについては一部コンテナに直接SSH接続して、pullする方法を取っていますが、
AWS側でもdocker-composeファイルを導入して複数コンテナの操作を1ファイルで行ったりすることができるそうですソースをコンテナに乗っける方法
私が今回行った方法は以下です。
- CodeCommitでソース管理をする
- CodeDeployのラインでCodeBuildの部分をいい感じに設定してmasterブランチにPUSHされたタイミングをトリガーとしてCodeBuildのビルドが走るようにする
- CodeBuildする時に、CodeCommitのソースをイメージの中に追加で配置した状態でBuildが走るように追加設定する
この方法だと、CodeBuildが通った時に出来上がっているコンテナには、
画像①で作成したコンテナ(インフラ部分)が構築されていて、頻繁に更新されているソースの部分は、
masterブランチにgit pushされた時に自動で乗っかるようになっています。
ただ、コンテナに配置したソースはコンテナ停止するとなくなるのが基本なので、データの永続化対応は別途必要です。DBもコンテナだったら、EC2側に、ボリュームを設定してあげるとかで対応できるはずです。
ただEC2関連の理解がまだまだ浅いので、間違ってたら指摘待ってます!そして、ソースをコンテナに乗っけるって部分も
おそらくもっとスマートな方法があると思うので、
その辺は次回構築時か、環境見直そうぜって時に調査実装したいなと思ってます!まとめ
今回AWSを初めてしっかり触って環境構築をしていきました。
時々先輩エンジニアの知恵をお借りしてセキュリティ部分を設定したり、
EC2のロードバランサーを設定したりしましたが、初学者にはサービスとサービスの連携が少し難しいと感じました。
(結果的に、かなり自己流の設定になってそうなので、工数が許されるのなら作り直したい、、w)
ある程度基本的なEC2の知識がある状態で、ECSに手を出すのがオススメです!そして本記事で紹介している方法とは別で
より良いコンテナクラウド化の方法がわかる方は、こっそり教えてくださいませー!本日も最後までお読みいただきありがとうございました!
また今度ネタができたら呟きます!
- 投稿日:2021-01-29T15:46:44+09:00
Permission Denied Error Doker Laravel
Dockerでlaradockを導入し、laravelを起動したとき、以下のエラー文が出ました。
docker The stream or file "/var/www/storage/logs/laravel.log" could not be opened in append mode: failed to open stream: Permission denied
chown -R www-data:www-data /var/www
chmod -R 777 /var/www/storage
権限を変更してあげると、無事にlaravelを表示することができました。
以下のサイトを参考に、しました。
https://stackoverflow.com/questions/48619445/permission-denied-error-using-laravel-docker
- 投稿日:2021-01-29T15:33:53+09:00
Lambdaがコンテナイメージをサーポートしたので試してみた
はじめに ローカルでLambdaを開発する際に、いざデプロイしようと思った時に困った方も少なくないと思います。 というのも、デフォルトでプリインストールされていないライブラリをimportしている場合はzipファイルにしてAWSコンソール上でアップロードする必要があります。 もしくはServerless FrameworkやSAMを導入されている方が多いのかと思います。 個人的にはちょっとした関数をLambdaで実装しようとした時にServerless FrameworkやSAMはゴツすぎるというかやりたいことに対して出来ることと、開発環境や設定が手間になると思い敬遠していました。 そこで今回Lambdaがコンテナイメージをサーポートしたので慣れ親しんだDockerfileでデプロイできるなら良いのではと考え試してみました。 使用環境とバージョン macOS Catalina aws-cli/2.0.28 Docker version 19.03.13 Lambdaの使用言語 Python3.8 記事の対象 ある程度AWSとDockerの知識がある方 ECSもしくはEKSを利用してアプリケーションを作成している方 事前準備 AWS CLIを利用できること IAMユーザもしくはスイッチロール先にecr:GetAuthorizationToken権限が付与されていること ※1 Amazon ECR の作成 dockerイメージをpushするリポジトリを事前に作成します。 AWS CLIで作成します。以下のコマンドをローカルで実行して下さい。 aws ecr create-repository \ --repository-name lambda-container 実行ファイルの作成 今回作成するLambdaには以下の要素を含めようと思います。 Lambda実行環境に標準で含まれないライブラリを使用する boto3により、AWSリソースにアクセスする 自分の経験則から、Lambdaを使用する際にpythonのライブラリを追加したいシーンがよくありました。 今まではpython -m venv {環境名}でローカルに仮想環境を構築し、追加ライブラリをinstallしてからzipにしてAWSコンソールからLambdaにアップロードしていました。 その辺りがdockerイメージを使用することで改善できることを期待しています。 また、LambdaではよくAWSリソースを参照することがあるのでboto3での権限周りを整理できればより実用的なものになると思います。 以下のpythonファイルを使用することとします。 lambda-container.py import os import logging import requests import json import boto3 rds = boto3.client('rds') logger = logging.getLogger() logger.setLevel(logging.INFO) # 返却用クラス class LambdaResponse: # コンストラクタ def __init__(self, db, zip): self.db = db self.zip = zip # json形式で返却 def json(self): db = {} instances = [] for instance in self.db['DBInstances']: res = {} res['Identifier'] = instance['DBInstanceIdentifier'] res['Status'] = instance['DBInstanceStatus'] instances.append(res) db['Instances'] = instances return { 'db': db, 'zip': self.zip } # メインハンドラー def lambda_handler(event, context): logger.info('event: {}'.format(event)) # お試し: RDSインスタンスをDescribe describe = rds.describe_db_instances(DBInstanceIdentifier='edu-demodb-rds01-postgres11') logger.info('describe db instances: {}'.format(describe)) # お試し: Defaultライブラリーに含まれない機能(郵便番号から住所を検索) response = requests.get('https://zipcloud.ibsnet.co.jp/api/search?zipcode={}'.format(event['zip'])) logger.info('Status: {}, Body: {}'.format(response.status_code, json.dumps(response.json(), ensure_ascii=False))) return LambdaResponse(describe, response.json()).json() requirements.txtの作成 こちらはpipでの一般的なインストール方法のため説明を省きます。 詳しく知りたい方は以下を参照して下さい。 pip install - pip documentation v20.3.3 ###### Requirements without Version Specifiers ###### requests # boto3 <- Lambdaのdockerイメージに含まれているため不要です。無くても動きます ###### Requirements with Version Specifiers ###### Dockerfileの作成 以下に使用するDockerfileになります。 pip install -r requirements.txtにて追加のライブラリをインストールします。 インストール先はDockerコンテナ内になるため、ローカル環境を汚すことはありませんでした。 CMDには実行対象となるハンドラーを指定して下さい。 Dockerfile FROM public.ecr.aws/lambda/python:3.8 COPY lambda-container.py requirements.txt ${LAMBDA_TASK_ROOT}/ RUN pip install --upgrade pip RUN pip install -r requirements.txt RUN pip list CMD [ "lambda-container.lambda_handler" ] dockerイメージは2種類ありDocker Hubにも用意されています。 基本的に同じものでリポジトリがAWSかDockerかの違いだと思うので基本的には手順通りのAWS側を使用すれば良いと思います。 amazon/aws-lambda-python - Docker Hub FROM amazon/aws-lambda-python:3.8 また、dockerイメージから以下の環境変数が提供されています。 ${LAMBDA_TASK_ROOT}に必要なファイルをCOPYして下さい。 The AWS base images provide the following environment variables: LAMBDA_TASK_ROOT=/var/task LAMBDA_RUNTIME_DIR=/var/runtime Creating Lambda container images - AWS Lambda ローカル環境でLambdaを実行 以下のディレクトリに成果物を配置することにします。事前に作成しておいて下さい。 $ mkdir lambda-container $ cd lambda-container $ ls Dockerfile lambda-container.py requirements.txt 以下の手順でローカル環境にてLambdaを実行することができます。 $ docker build -t lambda-container . $ docker run -p 9000:8080 lambda-container $ curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"zip":"1310045"}' { "db": { "Instances": [ { "Identifier": "xxxxxxxxxx", "Status": "stopped" } ] }, "zip": { "message": null, "results": [ { "address1": "東京都", "address2": "墨田区", "address3": "押上", "kana1": "トウキョウト", "kana2": "スミダク", "kana3": "オシアゲ", "prefcode": "13", "zipcode": "1310045" } ], "status": 200 } } boto3の認証について 上記の通りにローカル実行すると、以下のようなエラーが発生します。 これはdockerコンテナ内にboto3用のCredentialsが存在しないためです。 { "errorMessage": "Unable to locate credentials", "errorType": "NoCredentialsError", "stackTrace": [ " File \"/var/task/lambda-container.py\", line 37, in lambda_handler\n describe = rds.describe_db_instances(DBInstanceIdentifier='xxxxxxxxx')\n", " File \"/var/runtime/botocore/client.py\", line 357, in _api_call\n return self._make_api_call(operation_name, kwargs)\n", " File \"/var/runtime/botocore/client.py\", line 662, in _make_api_call\n http, parsed_response = self._make_request(\n", " File \"/var/runtime/botocore/client.py\", line 682, in _make_request\n return self._endpoint.make_request(operation_model, request_dict)\n", " File \"/var/runtime/botocore/endpoint.py\", line 102, in make_request\n return self._send_request(request_dict, operation_model)\n", " File \"/var/runtime/botocore/endpoint.py\", line 132, in _send_request\n request = self.create_request(request_dict, operation_model)\n", " File \"/var/runtime/botocore/endpoint.py\", line 115, in create_request\n self._event_emitter.emit(event_name, request=request,\n", " File \"/var/runtime/botocore/hooks.py\", line 356, in emit\n return self._emitter.emit(aliased_event_name, **kwargs)\n", " File \"/var/runtime/botocore/hooks.py\", line 228, in emit\n return self._emit(event_name, kwargs)\n", " File \"/var/runtime/botocore/hooks.py\", line 211, in _emit\n response = handler(**kwargs)\n", " File \"/var/runtime/botocore/signers.py\", line 90, in handler\n return self.sign(operation_name, request)\n", " File \"/var/runtime/botocore/signers.py\", line 162, in sign\n auth.add_auth(request)\n", " File \"/var/runtime/botocore/auth.py\", line 357, in add_auth\n raise NoCredentialsError\n" ] } 幾つか解決方法があると思いますが、簡単な方法として以下のように、docker runする時に環境変数を設定します。 $ docker run \ -e AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \ -e AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \ -e AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} \ -p 9000:8080 lambda-container 以下のドキュメントにあるように、boto3はConfigオブジェクトを使用して明示的に上書しない限り、環境変数を使用して認証を行うようです。 Using environment variables Configurations can be set through the use of system-wide environment variables. If set, these configurations are global and will affect all clients created unless explicitly overwritten through the use of a Config object. Configuration — Boto3 Docs 1.16.49 documentation Amazon ECRにpush 無事ローカルでLambdaを実行することができたのでECRにpushします。 ECRへpushする方法については、以下の記事で解説していますので、手順のみ記載します。 Amazon ECRのDockerイメージをローカルにpull、pushする $ aws ecr get-login-password --region ap-northeast-1 \ | docker login --username AWS --password-stdin {aws_account_id}.dkr.ecr.{region}.amazonaws.com $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE lambda-container latest 9ec9f9c8cabf 5 months ago 402MB $ docker tag 9ec9f9c8cabf {aws_account_id}.dkr.ecr.{region}.amazonaws.com/lambda-container $ docker push {aws_account_id}.dkr.ecr.{region}.amazonaws.com/lambda-container Lmabdaをdockerイメージで作成 dockerイメージの準備が整ったので、Lambdaを作成していきます。 AWSコンソールにログインしてLambdaの作成でコンテナイメージを選択して下さい。 Lambdaの作成が完了しました。現状ではAWSコンソールではコードが表示されないようです。 テストも無事成功です。 まとめ ちょっとしたLambdaの場合は不要かと思いますが、何度も修正が想定される場合は良いと思いました。 また、CodeCommitで履歴管理し、CodePipelineで自動デプロイすればより使いやすいと思います。 参考記事 pip install - pip documentation v20.3.3 amazon/aws-lambda-python - Docker Hub Creating Lambda container images - AWS Lambda Configuration — Boto3 Docs 1.16.49 documentation Amazon ECRのDockerイメージをローカルにpull、pushする
- 投稿日:2021-01-29T12:52:49+09:00
【Docker・Laravel】docker-composer.ymlとDockerfileの作り方。
docker-composeを使ってDocker上にLaravelを構築する方法(Nginx & php-fpm & MySQL)で使った、docker-compose.ymlとDockerfileの中身について。
docker-compoer.yml
docker-compoer.ymlversion: '3' services: #PHP Service app: build: context: . dockerfile: Dockerfile image: app_php-fpm container_name: app restart: unless-stopped tty: true environment: SERVICE_NAME: app SERVICE_TAGS: dev working_dir: /var/www volumes: - ./:/var/www - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini networks: - app-network links: - webserver - db #Nginx Service webserver: image: nginx:alpine container_name: webserver restart: unless-stopped tty: true ports: - "80:80" - "443:443" volumes: - ./:/var/www - ./nginx/conf.d/:/etc/nginx/conf.d/ networks: - app-network #MySQL Service db: image: mysql:5.7.22 container_name: db restart: unless-stopped tty: true ports: - "3307:3307" environment: MYSQL_DATABASE: laravel MYSQL_ROOT_PASSWORD: password SERVICE_TAGS: dev SERVICE_NAME: mysql volumes: - dbdata:/var/lib/mysql/ - ./mysql/my.cnf:/etc/mysql/my.cnf networks: - app-network #Docker Networks networks: app-network: driver: bridge #Volumes volumes: dbdata: driver: local・
version: '3'
docker-composeはバージョンにより記述方法が異なる。基本的にはバージョン3を使用する。
1. php-fpmのイメージとコンテナを作成
php-fpmのイメージとコンテナをサービス名appとして定義している。
docker-compoer.yml#PHP Service app: build: context: . dockerfile: Dockerfile image: app_php-fpm container_name: app restart: unless-stopped tty: true environment: SERVICE_NAME: app SERVICE_TAGS: dev working_dir: /var/www volumes: - ./:/var/www - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini networks: - app-network links: - webserver - db1-1. イメージのビルド
PHPサービスのイメージを作成するための記述は
build
とimage
。
build
でイメージを作成し、作成したイメージ名をimage
で指定している。docker-compoer.ymlbuild: context: . dockerfile: Dockerfile image: app_php-fpmイメージの作成にはDockerfileを指定している。
context
で指定したパスから見て、dokerfile
で指定した場所の中のDockerfileを探す。・contextディレクティブ
Dockerfileを探すために基準となるパスを指定する。必須項目。
・dockerfileディレクティブ
dockerfileはファイル名の指定がなければ、デフォルトで指定したディレクトリのDockerfileを探す。
contextで指定した場所にDockerfileがある場合は記述しなくてもいい。
なので、上記設定は以下でも同じ動きになる。
build: context: . image: app_php-fpm
1-2. Dockerfile
DockerfileFROM php:7.3-fpm # Copy composer.lock and composer.json COPY composer.lock composer.json /var/www/ # Set working directory WORKDIR /var/www # Install dependencies RUN apt-get update && apt-get install -y \ build-essential \ libpng-dev \ libjpeg62-turbo-dev \ libfreetype6-dev \ locales \ zip \ jpegoptim optipng pngquant gifsicle \ vim \ unzip \ git \ curl \ libonig-dev \ libzip-dev # Clear cache RUN apt-get clean && rm -rf /var/lib/apt/lists/* # Install extensions RUN docker-php-ext-install pdo_mysql zip exif pcntl RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/ RUN docker-php-ext-install gd # Install composer RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer # Add user for laravel application RUN groupadd -g 1000 www RUN useradd -u 1000 -ms /bin/bash -g www www # Copy existing application directory permissions COPY --chown=www:www . /var/www # Change current user to www USER www # Expose port 9000 and start php-fpm server EXPOSE 9000 CMD ["php-fpm"]・FROM イメージ名:タグ名
ベースとなるイメージを指定。
ここではphp:7.3-fpmを指定している。タグを指定していない場合はlatestとなる。buildを実行すると、まずはローカルで指定したイメージを探し、なければdocker hubを探しにいく。
・バンドル関連ファイルのコピー
# Copy composer.lock and composer.json COPY composer.lock composer.json /var/www/・
COPY <ファイル1> <ファイル2>,,, <ディレクトリパス>
指定したローカルのファイルをdockerのディレクトリにコピーする。
・WORKDIR パス
コンテナ起動時の
# Set working directory WORKDIR /var/www以降のコマンドCOPY、RUN、CMD、ENTRYPOINTを実行する大元となるDockerコンテナ内のディレクトリを指定する。
コンテナ内に指定したディレクトリが存在しない場合は作成してくれる(エラーにならない)
▼複数記述することも可能
複数記述した場合は、そのディレクトリが追加され、ディレクトも移動してく。(cdコマンドみたいな感じ)WORKDIR app WORKDIR b WORKDIR c RUN pwd //現在地 app/b/c
Linux(Debian系)依存パッケージのインストール
# Install dependencies RUN apt-get update && apt-get install -y \ build-essential \ libpng-dev \ libjpeg62-turbo-dev \ libfreetype6-dev \ locales \ zip \ jpegoptim optipng pngquant gifsicle \ vim \ unzip \ git \ curl \ libonig-dev \ libzip-dev・
apt
Linux(DebianやUbuntuなど)のパッケージ管理コマンド。Advanced Package Toolの略。
・
apt-get
パッケージの操作・管理を行うコマンド。
・
apt-get update
インストール可能なパッケージの一覧を更新する。(一覧の更新のみでインストールはしない)
一覧は/etc/apt/sources.listにある。
・
apt-get install
sources.listに沿ってパッケージをインストール or アップデートする。
-y
オプション:すべてyesを選択する。
パッケージ 内容 build-essential Debian系のOSを使うために必須 libpng-dev png画像の読み込み・書き込み・編集 libjpeg62-turbo-dev jpeg画像の読み込み・書き込み・編集 libfreetype6-dev フォント関連の様々な操作をサポート(FreeType) locales 言語設定 zip zip操作の圧縮。zipコマンドが使えるようになる jpegoptim jpg画像の圧縮 optipng png画像の圧縮(画質を下げることなく圧縮。圧縮率低め) pngquant png画像の圧縮(optipngよりも圧縮。画質は低下) gifsicle gif画像とアニメーションの読み込み・書き込み・編集 vim テキストエディタ unzip zip操作の解凍。unzipコマンドが使えるようになる git ソースコードなどの変更履歴を記録・追跡 curl URLシンタックスを用いてファイルを送信または受信するコマンドラインツール libonig-dev 正規表現ライブラリ。鬼車(onigruma) libzip-dev zipアーカイブの読み取りと書き込み Linux(Debian系)の構築や必要なコマンドライブラリを一気にインストール。
・-devの意味
パッケージ名の後ろの-dev
は、developmentの略。プログラム開発で必要なヘッダーやツール、ライブラリなどが入っている。
aptのキャッシュ削除
apt-get installでパッケージをインストールすると、キャッシュが追加され容量が大きくなっていく。
キャッシュは不要なので削除する。
ダウンロードしたパッケージは.deb形式で、var/cache/apt/ archives/ディレクトリに保存されます。これらのインストーラパッケージは、アンインストール後もローカルストレージに保持されます。
# Clear cache RUN apt-get clean && rm -rf /var/lib/apt/lists/*・
apt-get clean
キャッシュを一掃する。・
rm -rf /var/lib/apt/lists/*
パッケージリストが削除する。apt-getで再度パッケージがインストールされたり、キャッシュファイルが増加するのを防ぐ。▼補足
実行すると、パッケージに関する情報がないため、apt-get install
はE: Unable to locate package でエラーを返す。
apt-get update
を実行すればリストが復活する。
PHP拡張機能(エクステンション)のインストール
# Install extensions RUN docker-php-ext-install pdo_mysql zip exif pcntl RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/ RUN docker-php-ext-install gd・
docker-php-ext-install
DockerにPHPの拡張機能をインストールするためのコマンド。
・インストールする拡張機能
PHP拡張機能 内容 pdo_mysql PHPからMySQLへのアクセスを可能にする zip zipのアーカイブとその内部のファイルに対する透過的な読み書きを可能にする exif 画像のメタデータ扱えるようになる。画像のヘッダ情報を読み込むなど pcntl プロセス制御機能。プロセスの並行処理を行う gd 画像をPHPスクリプトで生成する。画像のリサイズやグラフ作成などの描画機能を持たせることができる。 docker-php-ext-configure
docker-php-ext-configure <拡張機能> <オプション>
指定した拡張機能の環境設定をする。環境設定は各拡張機能に割り当てられたオプションを使う。
GDの主要オプション
RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/GDの環境設定をしている。jepgやpngを使うGDをビルドするためにはlibpegやfreetype, libpngが必要なためインストールの設定をする。
オプション 意味 --with-gd[=DIR] GDライブラリの保存場所を指定 --with-jpeg-dir[=DIR] libjpegの保存場所 --with-freetype-dir[=DIR] FreeType 2の保存場所 --with-png-dir[=DIR] libpngの保存場所 次の行でGDをインストール。
RUN docker-php-ext-install gdGDインストール時の注意点
PHP7.4以降からGDインストール時のオプションが変更となっている。(上記設定だとエラーが出る)
configure: error: unrecognized options: --with-gd, --with-freetype-dir, --with-jpeg-dir, --with-png-dir
PHP7.4以降は引数での環境設定が不要になる。必要なパッケージは
apt-get install
でインストールしておく。なので、
docker-php-ext-config gd ~
は不要。修正後# Install extensions RUN docker-php-ext-install pdo_mysql zip exif pcntl RUN docker-php-ext-install gd
composerのインストール
# Install composer RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer・
curl -sS
-s
オプション
--silent。通常表示される進捗状況を表示しない。エラーメッセージも表示しない。
-S
オプション
--show-error。エラーメッセージを表示する。-sとセットで使うことでエラーを表示する。curl --helpでオプション一覧が確認可能。
・
curl -sS https://getcomposer.org/installer
composerのinstallerをダウンドロードする。(composer-setup.phpを取得)
・
|
コマンドA | コマンドB
パイプライン。コマンドAの実行結果をコマンドBに渡す。
・
php -- --install-dir=/usr/local/bin --filename=composer
php [options] -- [args...]
なので、引数で、インストール先のディレクトリとファイル名を指定。
- --install-dir=/usr/local/bin
- -filename=composer
ユーザーとグループの追加
# Add user for laravel application RUN groupadd -g 1000 www RUN useradd -u 1000 -ms /bin/bash -g www www・groupadd
groupaddコマンドで新しいグループ
groupadd [オプション] [グループID] <グループ名>
-g
: --gidと同じ。作成するグループのID(GID)を指定。
指定がない場合は、未使用の番号を自動で割り振る。
▼作成したグループの確認
グループの情報は /etc/group に保存されている。コンテナの中で確認できる。$ docker exec -it app bash www@a1984dd1d4a4:/var/www$ cat /etc/group www:x:1000:・
①グループ名:②PW:③GID[④:所属メンバー名]
- グループ: www
- PW: x (セキュリティのため表示されない。設定なしの場合は*)
- GID: 1000
- 所属メンバー:なし
・useradd
useraddコマンドは新規ユーザーを作成し、ユーザーごとの設定ができる。
コマンドは長いが、最初のuseraddと最後のwww以外はすべてオプション。
useradd [オプション] ユーザー名
-u
: ユーザーID(UID)の指定
指定がない場合は、未使用の番号を自動で割り振る。
-m
: ユーザーのhomeディレクトリが存在しない場合に作成。
指定しない場合は、「/」配下にユーザー情報が保存される。
-s [dir]
: ユーザーのログインシェルをフルパスで指定(指定しなかった場合はデフォルト設定)
-g [グループ名/gid]
: 指定したユーザーをグループに追加する。
▼作成したユーザー情報の確認
ユーザー情報は /etc/passwd に保存されている。コンテナの中で確認できる。$ docker exec -it app bash www@a1984dd1d4a4:/var/www$ cat /etc/passwd www:x:1000:1000::/home/www:/bin/bash・
①ユーザー名:②PW:③UID:④GID::⑤/home/<ユーザー名>:⑥シェルのパス
- ユーザー名: www
- PW: x (セキュリティのため表示されない。設定なしの場合は*)
- UID: 1000
- GID: 1000
- ユーザーのホームディレクトリ: home/www
- ユーザーが使用するシェル: /bin/bash
ローカルのPJをコンテナ内にコピー & ファイルオーナーの変更
# Copy existing application directory permissions COPY --chown=www:www . /var/www・
COPY [--chown=<user>:<group>] <ローカルdir> <コンテナdir>
ローカルの「.」をコンテナ内の「/var/www」にまるごとコピー。ユーザー名をwww、グループ名をwwwに変更。
ユーザー名を指定
# Change current user to www USER www・
USER <user名 or uid>[:<group名 or gid>]
ポート開放とphp-fpmの起動
# Expose port 9000 and start php-fpm server EXPOSE 9000 CMD ["php-fpm"]・
EXPOSE ポート番号
指定したポートでリッスン(外部からのアクセスに備えて待機)する。
ここでは、php-fpmの9000番ポートを開けておく。
・
CMD [
コマンド,
引数1,
引数2,,,]
CMDはコンテナ実行時のデフォルト処理を定める。Dockerfileに必須。記述は1つのみ。
php-fpmコマンドを実行して、php-fpmを起動。
以上がDockerfileの中身。
php:7.4-fpmイメージをベースに、必要なパッケージをインストール、ユーザー名や権限変更をしたのち、9000番ポートを開けてphp-fpm起動するイメージが出来上がり。
イメージ名の設定
最後に作成したイメージに名前をつけて完了。(ここではapp_php-fpm)
image: app_php-fpm
1-3. コンテナの設定
1-2までがイメージのビルド。続いてコンテナ起動時に実行される処理の確認。
docker-compose.yml#php-fpmサービスの続き container_name: app restart: unless-stopped tty: true environment: SERVICE_NAME: app SERVICE_TAGS: dev working_dir: /var/www volumes: - ./:/var/www - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini networks: - app-network links: - webserver - dbcontainer_name: コンテナ名
コンテナを作成した時の名前。起動・停止・削除に使うのでわかりやすく短めの名前がおすすめ。
restart: コンテナ停止時の処理フラグ
コンテナが停止した時の処理をフラグで指定する。
フラグ 意味 no 再起動しない。デフォルト on-failure エラー発生時にコンテナを再起動(終了コードがゼロ以外) always 常に再起動。手動で停止時はDockerデーモンが再起動した場合にコンテナを起動する unless-stopped 手動停止時を除いて再起動。Dockerデーモンを起動しても再起動しない。 ▼再起動ポリシー
- コンテナ起動後が10秒以上立たない場合は自動再起動しない。(再起動ループを避ける)
- 手動でコンテナを停止すると、Dockerデーモンを再起動するか、コンテナを手動で再起動するまで再起動ポリシーを無視する。(再起動ループを避ける)
- 再起動ポリシーを適用できるのはコンテナのみです。(swarm サービスは対象外)
・
tty: <boolean>
疑似ターミナル (pseudo-TTY) の割り当て。
tty: true
で、ポート開放していないコンテナも起動状態をキープできる。(ないとコンテナがすぐに終了してしまう)
docker exec
コマンドでコンテナに入って操作する際に必要。
environment
環境変数の設定。
書き方は2種類。Key: Value
または、- Key=Value
。environment: SERVICE_NAME: app SERVICE_TAGS: dev以下と同じ。
environment: - SERVICE_NAME=app - SERVICE_TAGS=dev
- 値を指定しない場合は、シェルの値を適用する。
- DockerfileのARGやENVで指定した環境変数と被る場合は、docker-composeの環境変数が優先される。
env_file
で読み込んだ環境変数と被る場合は、environmentが優先される。
▼環境変数の優先度
- environment
- env_file
- DockerfileのARG, ENV
env_fileは環境変数を定義したファイルを指定する。たくさんの環境変数を一括で読み込む場合に便利。
.env_fileの例env_file: - ./Docker/api/api.env
working_dir
コンテナ内のデフォルトの作業用ディレクトリを指定する。
working_dir: /var/wwwコンテナに入ると/var/wwwに入る。ここはプロジェクトがコピーされるディレクトリ(Dockerfileにて設定)。
Volumes
ローカルのディレクトリをコンテナ内のディレクトリにマウントする。
volumes: - ./:/var/www - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
- ホストのパス:コンテナ内の絶対パス
コンテナ側は絶対パス。ホスト側は相対でも絶対でもいい。ボリューム名を定義指定いる場合は、ボリューム名でもいい。
- ./:/var/www
ローカルの現在のディレクトリをコンテナの「var/www」と同期させる。これで、ローカルのプロジェクトディレクトリで行った変更はコンテナ内に自動コピーされる。
自動同期したくないディレクトリやファイルは、.dockerignoreに記載する。
▼ボリューム名について
ボリューム名はserviceの外でvolumesを使って定義する。参照する際のボリューム名は「プロジェクト名_ボリューム名」となる。ボリューム名を指定しない(ホストのパスを指定した)場合はハッシュ値となる。
docker-compose.ymlの例#PJ名:laravel version: '3' services: #MySQL Service db: #省略 volumes: - dbdata:/var/lib/mysql/ - ./mysql/my.cnf:/etc/mysql/my.cnf volumes: dbdata: driver: local↓
ボリューム名$ docker volume ls DRIVER VOLUME NAME local laravel_dbdata local f0f9aa131ed1d74c0d2e9ff87b065170a1b142bd6a90a76ce9dcddbee3c69984networks
docker-composeはnetworkを指定しない場合、プロジェクト名のネットワークが自動生成され、すべてのサービスがそのネットワーク内に入る。
networkを自分で定義すると、指定したサービスだけをそのnetworkで繋ぐことができる。
version: '3' services: app: #省略 networks: - app-network #省略 networks: app-network: driver: bridge▼ネットワークの確認
ネットワーク名は指定の有無により名前が変わる
- 指定なし:
プロジェクト名_default
- 指定あり:
プロジェクト名_ネットワーク名
ネットワークの確認$ docker network ls NETWORK ID NAME DRIVER SCOPE 2cee68b9dc5a django_default bridge local 761212ed4b49 laravel_app-network bridge▼bridgeとは?
bridgeとはネットワークのブリッジモードのこと。複数のネットワークをつなげて、ひとまとめのネットワークにしている状態。links
サービスを関連づける。サービスを起動すると、linksで記述されているサービスも一緒に起動する。
version: '3' services: app: #省略 links: - webserver - db上記の場合、appにdbとwebserverがlinkしているため、appのみを起動すれば自動的にdbとwebserverも起動する。
起動の順序はlinksに記述したコンテナから。
起動例$ docker-compose up -d app Starting webserver ... done Starting db ... done Starting app ... done
以上で一つ目のphpサービスのdocker-composeの記述内容が完了。処理をまとめると、
(1)イメージのビルド
Dockerfileを元に、php:7.4-fpmをベースイメージとして、必要なパッケージなどを保持した新たなイメージを作成。(2)コンテナの起動
環境変数、ボリューム、ネットワーク、関連サービスを指定(リンク)してコンテナを起動。最後はDockerfileに記載されたCMDが実行され、イメージ通りのphp-fpmが起動する。
2. Nginxのコンテナを作成
php-fpmのコンテナが作成できるようになったので、続いてWEBサーバーとなるNginxを作成する。
.yml#Nginx Service webserver: image: nginx:alpine container_name: webserver restart: unless-stopped tty: true ports: - "80:80" - "443:443" volumes: - ./:/var/www - ./nginx/conf.d/:/etc/nginx/conf.d/ networks: - app-network2-1. イメージのビルド
イメージの作成は1行のみ。
image: nginx:alpinedocker-hubの
nginx:alpine
をイメージとして使用。(alpine上に構築したnginx)
▼alpineとは?
alpineは超軽量のLinuxディストリビューション。▼Linuxディストリビューションとは?
LinuxのコアとなるプログラムをLinuxカーネルという。この状態では普通のOSとして使うことが難しい。使いやすいようにパッケージをくっつけたのがLinuxディストリビューション。distributionは配布という意味なので、配布用Linuxということ。
Debian, Ubuntu, CentOSと同じ並びにalpineがくる。
2-2. コンテナの定義
container_name: webserver restart: unless-stopped tty: true ports: - "80:80" - "443:443" volumes: - ./:/var/www - ./nginx/conf.d/:/etc/nginx/conf.d/ networks: - app-networkphp-fpmサービスで使った内容とほぼ同じ。
作成したコンテナ名をwebserverとし、コンテナ手動停止(&エラー)以外は自動再起動する。
コンテナのbashを起動できるように擬似ターミナル(tty)を開けておく。
ports
ホスト側:コンテナ側
でポート番号を指定する。
- "80:80"
であれば、localhost:80にアクセスすると、Nginxの80番ポートに繋がるという意味。443ポートはhttpsプロトコル用のポート。
https://xxx
で接続すると、xxxのIPアドレスの443ポートに接続する。volumes
・
- ./:/var/www
ローカルの現在のディレクトリを、Dockerコンテナ内のNginxの/var/wwwと同期。・
- ./nginx/conf.d/:/etc/nginx/conf.d/
ローカルの./nginx/conf.d/をnginxの/etc/nginx/conf.d/と同期。networks
「project名_app-network」というネットワークに入ったサービス同士とつなげる。
2-3. DBの定義
#MySQL Service db: image: mysql:5.7.22 container_name: db restart: unless-stopped tty: true ports: - "3307:3307" environment: MYSQL_DATABASE: laravel MYSQL_ROOT_PASSWORD: password SERVICE_TAGS: dev SERVICE_NAME: mysql volumes: - dbdata:/var/lib/mysql/ - ./mysql/my.cnf:/etc/mysql/my.cnf networks: - app-network設定はNignxサービスとほぼ同じ。
ベースイメージに、mysql:5.7.22を使用。
ポート番号はホスト側の3307をローカル側の3307につなげるよう設定。environment
環境変数でDB名やPWなどを渡している。
2-4 networkとvolumeの定義
全体で使用するnetworkと、volume名をつけるものを定義している。。
#Docker Networks networks: app-network: driver: bridgeapp-networkを定義。ドライバーはbridge(複数のネットワークを一つとみなす)
#Volumes volumes: dbdata: driver: local名前ボリュームを設定する。名前ありボリュームを使うとデータを永続化できる。
ここでは、DBのデータはコンテナを終了しても残しておきたいので、dbdataボリュームを作成し、/var/lib/mysql/と連動させている。
コンテナ終了時にDocker内のデータは消えるが、ローカルにデータが残る。
Dockerではボリューム名dbdataでローカルのパスを保存してあるため、次のコンテナ起動時にそのローカルに接続し、/var/lib/mysql/配下にデータを保存する。(ローカルと同じ状態にする)
まとめ
php-fpmは自分のLaravelプロジェクトを反映するためイメージの再構築をしているのでビルドに時間がかかる。
NginxとDB(MySQL)は公式のイメージを取得するのみなのでビルドもあっさり。(ただdocker-hubからプルするだけ)
コンテナ起動時にポート番号、環境変数、ボリューム、ネットワークを指定している。
- 投稿日:2021-01-29T12:30:17+09:00
【Rails】EC2上でのbundle install時のメモリ不足のエラーと解消方法
DockerでRailsのコンテナを
Run
する際に、bundle install
とyarn install
を起動させているのですが、Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
といったエラーが発生しました。web_1 | Gem::Ext::BuildError: ERROR: Failed to build gem native extension. web_1 | web_1 | current directory: web_1 | /app/vendor/bundle/ruby/2.7.0/gems/racc-1.5.2/ext/racc/cparse web_1 | /usr/local/bin/ruby -I /usr/local/lib/ruby/2.7.0 -r web_1 | ./siteconf20210129-9-ef1ov1.rb extconf.rb web_1 | extconf failedOut of memory - /usr/local/bin/ruby web_1 | web_1 | Gem files will remain installed in /app/vendor/bundle/ruby/2.7.0/gems/racc-1.5.2 web_1 | for inspection. web_1 | Results logged to web_1 | /app/vendor/bundle/ruby/2.7.0/extensions/x86_64-linux-musl/2.7.0/racc-1.5.2/gem_make.out web_1 | web_1 | An error occurred while installing racc (1.5.2), and Bundler cannot continue. web_1 | Make sure that `gem install racc -v '1.5.2' --source 'https://rubygems.org/'` web_1 | succeeds before bundling. web_1 | web_1 | In Gemfile: web_1 | rails was resolved to 6.0.3.4, which depends on web_1 | actioncable was resolved to 6.0.3.4, which depends on web_1 | actionpack was resolved to 6.0.3.4, which depends on web_1 | actionview was resolved to 6.0.3.4, which depends on web_1 | rails-dom-testing was resolved to 2.0.3, which depends on web_1 | nokogiri was resolved to 1.11.0, which depends on web_1 | racc web_1 | web_1 | web_1 | Gem::Ext::BuildError: ERROR: Failed to build gem native extension. web_1 | 〜〜〜 以下、他のGemでも同様のエラー 〜〜〜 web_1 | web_1 | In Gemfile: web_1 | mysql2 web_1 | !! exit status 5原因
EC2上でのメモリ不足でした。
AWSの無料利用枠の対象であるt2.microはRAMが1GBしかなく、そりゃ足りないよねといった状態でした。解決方法
以下の通りメモリスワップさせ、記憶できる容量を1GB→3GBに増やしたところ、
bundle install
とyarn install
が正常に完了しました。SSHでEC2にログイン$ sudo dd if=/dev/zero of=/swapfile bs=16M count=128 #スワップ用のファイル作成 $ sudo chmod 600 /swapfile $ sudo mkswap /swapfile # スワップ領域の作成 スワップ空間バージョン 1 を設定します。サイズ = 2 GiB (2147479552 バイト) ラベルはありません, UUID=a0628f7c-7088-4829-9258-e533a2b067f6 $ sudo swapon /swapfile # スワップ領域を有効化する $ sudo swapon -s # スワップ設定内容の確認 ファイル名 タイプ サイズ 使用済み 優先順位 /swapfile file 2097148 0 -2 $ sudo vi /etc/fstabfstabにvimで新たな行として追記/swapfile swap swap defaults 0 0ddコマンド
ファイルを変換してコピーする
if=/dev/zero
:0埋め
of=/swapfile
:作成対象のファイル名
bs=16M
:1ブロックあたり16MB
count=128
:128ブロック
→約2GBをスワップ領域として確保。(最適な分け方かは不明。)スワップ領域の推奨サイズ
一般的な推奨されるスワップ領域は以下の通りです。
t2.microは1GBのため、2GB分作成しました。
物理 RAM の量 推奨されるスワップ領域 2 GB 以下の RAM RAM 容量の 2 倍、ただし常に 32 MB を超える 2 GB 以上の RAM、ただし 32 GB 未満 4 GB + (RAM – 2 GB) 32 GB 以上の RAM RAM 容量の 1 倍 スワップ領域の無効化
スワップ領域を無効化したい場合は、
swapoff
で可能です。SSHでEC2にログイン$ swapon -s ファイル名 タイプ サイズ 使用済み 優先順位 /swapfile file 2097148 90368 -2 $ sudo swapoff /swapfile $ swapon -s 〜〜〜 何も表示されない 〜〜〜参考記事
・スワップファイルを使用して Amazon EC2 インスタンスでスワップ領域としてメモリを割り当てる
・linux スワップ(swap)領域の作成
- 投稿日:2021-01-29T11:03:19+09:00
Dockerで動かすGhostに Mailgunを使って mailの設定をする
Ghost では mail の設定が必須です。後回しにしていてとても後悔したので、手順を書いておきます。
Ghost での mail 設定について、公式では Maiilgunの使用が推奨されています。
Configuration - Adapt your publication to suit your needs
(以下「公式」という)
Mailgunを使用して、Ghostにmailを設定・運用するには、下記のモノが必要です。
- 取得したドメイン(以下「sample.com」とする)
- クレジットカード
- SMSメッセージ確認用の電話番号
Ghostの設定
Ghostの設定は最終的にconfig.production.jsonに反映されている必要があります。
自分の場合は、docker のimageghost:latest
を利用しているので、docker-compose.yml に設定を書いていきます.
docker-compose.yml は下記です。docker-compose.ymlversion: '3.1' services: ghost: image: ghost:latest container_name: sample-ghost tty: true restart: always volumes: - ./ghost:/var/lib/ghost/content # - ./ghost-setting/config.production.json:/var/lib/ghost/config.production.json environment: url: https://sample.com database__client: mysql database__connection__host: db database__connection__user: root database__connection__password: password database__connection__database: ghost server__host: '0.0.0.0' server__port: '2368' mail__transport: 'SMTP' mail__options__service: 'Mailgun' # mail__options__host: smtp.mailgun.org # mail__options__port: 465 # mail__options__secureConnection: 'true' mail__options__auth__user: 'postmaster@mg.sample.com' mail__options__auth__pass: '799XXXXXXXXXXXXXXXXXXXXXXXXXX-XXXXXXXX-XXXXXX' forceAdminSSL: 'true' networks: - sample_net db: image: mysql:5.7 container_name: sample-ghost-db tty: true restart: always environment: MYSQL_ROOT_PASSWORD: password BIND-ADDRESS: 0.0.0.0 volumes: - ./mysql:/var/lib/mysql networks: - sample_net networks: sample_net: external: true上記 yml の中で、
mail__
と書いている項目部分が config.production.json へ渡すmail の設定です。*今回は書きませんが、
config.production.json を volume と紐付けて(volumes の コメントアウトしている、- ./ghost-setting/config.production.json:/var/lib/ghost/
部分です)containerの中のファイルにして設定するコトも出来ます。Mailgun の登録
下記記事では画像付きでご説明いただいているのでとても参考になります。感謝?。下記の通り進めましょう。
いますぐ使う Mailgun - Qiita
(以下「Mailgun設定記事」という)一部追記していきます。
Mailgun設定記事で、 [Sandboxから送信] の部分です。
Mailgun設定記事 では
画面下側? 右側? の Try Now
とあった部分です。
自分は下記の手順でたどり着きました。
左側サイドバーの Sending 欄、 Domains 項目を開き、Domainsのリストの中にある、”sandboxXXXXXXXXXXXXXXXXXXXX…”を選択します。
すると、”sandboxXXXXXXXXXXXXXXXXXXXX…”のOverview が開くので、API の Select ボタンをクリックし、cURL の項目を選択すると、Mailgun設定記事のお試し用 コマンドが表示されます。そのコマンドを terminal に貼り付けて実行してみて下さい。
自分が実際に使用したコマンドは下記です。(Mailgun サンプルから変えています)
*API key 、API base URL は個別のものなので書き換えて下さい(cURL ボタンの下に表示されています)
*あと、-F to=
の部分も、送信したい mail アドレス(確認できるモノ)に書き換えてください。curl -s --user 'api:6d8XXXXXXXXXXXXXXXXXXXXXXXX-XXXXXXXX-XXXXXXXXXX' \ https://api.mailgun.net/v3/sandbox0d7XXXXXXXXXXXXXXXXXXXXX.mailgun.org/messages \ -F from='Mailgun Sandbox <postmaster@sandbox0d7XXXXXXXXXXXXXXXXXXXXX.mailgun.org>' \ -F to='sample@sample.com' \ -F subject='Hello' \ -F text='Testing some Mailgun awesomeness!'お試し、届きましたかね?
自分の場合は、/messages
が抜けていたりして、入力するコマンドを何回も確認・修正したら送信・確認できました。
(迷惑メールフォルダに入っていたりするので、そちらも確認してみてください)Mailgun設定記事で、[DNSレコード作成] の部分です。
Mailgun設定記事では、Route53を使用されていますが、自分は Google Domains で設定しています。
なので、GoogleDomainsでの設定方法を書いておきます。カスタムリソースレコードに 4つの 項目を追加します。
名前(@):タイプ(A):TTL(1H):データ(IPv4 アドレス)の順に列挙します
- mg:TXT:未入力(空欄で良いです):v=spf1 include:mailgun.org ~all
- smtp._domainkey.mg.sample.com:TXT:未入力(空欄で良いです):k=rsa; p=MIGXXXX(個別の環境で変化します)
- mg:MX:未入力(空欄で良いです):mxa.mailgun.org (この項目ではデータ入力時にプラスで追加して下さい → [mxb.mailgun.org] を 追加します)
- email.mg:CNAME:未入力(空欄で良いです):mailgun.org
Mailgun設定記事にも、ある通り DNS が紐づくまで放置しつつ、たまに [Verify DNS Settings] で確認しましょう。
*自分の場合は、次の部分で間違っていました。
名前(@)の部分に、mg のサブドメイン + sample.com のドメイン まで入力していた。正しくは、mg のサブドメインのみでOK。
下記の記事に助けていただきました。感謝?。
value-domainでmaingunのDNS設定をするどうでしょう。いけましたかね?
Mailgun設定記事を参照して、今回設定する Mailgun の設定は以上です。
Ghost のmail 設定時、Mailgun の画面で参照するのは、次の画面SMTP credentials
です。以下、表示方法です。
左側サイドバーの Sending欄、Domain settings項目の、右画面のタブ SMTP credentials 項目です。
公式のリンク先で [create a Mailgun account] の項目で表示されているものです。SMTPの設定をする Mailgun から Ghostへ
SMTP credentials 画面を参照しながら、設定を [docker-compose.yml] へコピーしていきます。
下記の部分です。docker-compose.ymlmail__options__auth__user: 'postmaster@mg.sample.com' mail__options__auth__pass: '799XXXXXXXXXXXXXXXXXXXXXXXXXX-XXXXXXXX-XXXXXX'自分は
mail__options__auth__pass
って何? となりましたが、ちゃんと公式では説明されています。
SMTP credentials 画面の [Reset Password] をクリックして下さい。
すると、現在のPassword をコピーできます。
コピーした Password を [docker-compose.yml] に ペーストしてください。以上で、Mailgun と Ghost の紐付けは終了です。
確認方法ですが、自分の場合は Ghost のLabs でbeta のmember 機能で確認しました。(memberを登録する際に使用するmagic link の mail 部分でerror が出ていたので)
どうでしょう。動いていますかね?公式にもある通り( [Secure connection]の項目です)、セキュアの設定も出来ます。
[docker-compose.yml] でコメントアウトしていた下記の部分です。# mail__options__host: smtp.mailgun.org # mail__options__port: 465 # mail__options__secureConnection: 'true'コメントアウトを外しましょう。
公式では、
”port”: 587
とあるのですが、自分の場合 error になったので、465
に変更したら 動きました。
下記のやりとりに感謝です?。
Signup/login fails in Dawn theme with Portal (Beta) - Members (beta) - Ghost Forum設定は以上で終了です。お疲れ様でした。
参考
Configuration - Adapt your publication to suit your needs
いますぐ使う Mailgun - Qiita
value-domainでmaingunのDNS設定をする
Signup/login fails in Dawn theme with Portal (Beta) - Members (beta) - Ghost Forum
Local Ghost 3.0 - subscribing does not work - #26 by mindtrades - Members (beta) - Ghost Forum
- 投稿日:2021-01-29T09:59:31+09:00
[Rails] Errno::ENOENT - No such file or directory - bs_fetch:atomic_write_cache_file:rename
キャッシュが残っているのが原因っぽい。だから、それを消したらok
docker-compose down rm -rf tmp/cache/bootsnap-* docker-compose up -d参考
https://github.com/Shopify/bootsnap/issues/177#issuecomment-604981988
- 投稿日:2021-01-29T07:55:31+09:00
ECS+ロードバランサー的なことをEC2で実現して、コスト削減
dockerで開発している場合に、ECSとロードバランサーを遣うと、SSL環境でのサブドメインステージング環境とかあっという間に立てられますよね。
なれてないときはそんなのでポコポコサーバーを立てていたいのですが、ロードバランサー毎に費用がかかったりして立ち上げ期とかで開発予算が少ないときはなにげにボディーブローとなります。そこで、極小のリソースでワードプレスをAWS上に立ててみた方法をまとめます
要件
- 規模が大きくなってきたときにECSを遣うことを想定してそれに近い環境を構築する
- ほぼほぼ、それに近い形の開発環境でdocker-composeで実現する。というか、開発環境のdocker-composeをできる限りAWS上で実現する
- 取得済みのサブドメインでアクセスできる様にする
- 当然SSL接続を実現する
手順
ということで、wordpress のdocker環境をawsに立てる手順をまとめます
- amazon linux2 のEC2イメージを立てる
- 1のEC2イメージにdocker-compose可能な環境を構築する
- route53にドメインが登録されていることを前提に、1のEC2イメージにサブドメインでアクセスできる様にする
- 1のEC2イメージのapacheを設定しサブドメインでのアクセスに対応する
- 1のEC2イメージに無料のSSLをインストールする
- 1のEC2イメージにwordpressのdocker環境を作成して、81版ポートでアクセスできる様に設定する
- まずは sslなしのポート直接指定でアクセスする
- 1のEC2イメージのポートフォワード設定をし、ssl接続を可能にする
1. amazon linux2 のEC2イメージを立てる
AWSのアカウントはお持ちでしょうか?
AWSって、サインアップから12ヶ月間の無料枠が結構充実しているんですよね。
AWSのハンズオンイベントに参加すると、新規アカウントを作って初年度の無料クレジットを使ってハンズオンする手順が前提になっていたりします。
ということで、AWSのアカウントを作って12ヶ月以上経っている場合も異なるメールアドレスで新たにアカウント作成して無料枠で色々試してみるということが半ば公式になっていると考えていもいいかもですね。。
開発環境のdockerイメージのとして、centosやubuntuを選択していることが多いかと思いますし、最近だとalpineイメージをベースにして極限までdockerimageを減らす方法もおおい気もします。
で、docker imageを動かすことを前提にEC2環境を構築するとなると、EC2タイプのECSと同じ環境を構築すればいいのかなと。それが amazon-linux-2の様で、下を見ると別のECSに特化しているわけではなさそうです。中身は redhatとのことで、運用に当たって web上でも情報が検索出来る感じになっています
なにげに何か必要なものが出てきたら yum install でインストールして行きます今回必要なEC2イメージは 将来ECSに移行したときに再テストの懸念を極小にすることを念頭に置いているので、ECS向けのEC2構築と同じ手順で立ててみます。
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/getting-started-ecs-ec2.html
2021年1月現在、上の手順の真ん中辺にある「Amazon ECS-optimized AMI」がそれに当たります
AMIイメージにたどり着くのが結構大変なのですが
- https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-optimized_AMI.html
- Amazon ECS-optimized Amazon Linux 2 AMI バリアントという情報を知る
- AMI IDをAWS CLIで取得する(AWS CLIのインストールが必要・・)
- と書いてあるものの、こちらのページで最新情報がリストされていると見つける https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-ami-versions.html#ecs-ami-versions-linux
- Amazon ECS-optimized Amazon Linux 2 AMI の最新IDを見つけます
けど、image idが分からないんですよね。。とはいえ、ここでは、
20201209
というキーワードが見つかるので、"ECS optimized 20201209"というキーワードで検索してみると・・
コミュニティAMIで一件見つかりました正解は "amzn2-ami-ecs-hvm x86_64 20201209" とかで投げた結果が今の時点ではよさそうです。
もっと確実なのは、ちなみに AWS-CLIでコマンドを投げて返ってくる情報
この結果を基にすると
ami-021541b9f47c3c5cc
により、マシンイメージが特定されるわけです
違うのが返ってくるけど、まあ、amazon-ecs-optimizedとなっているのでどちらでも大丈夫そう・・
今回はAWS-CLIコマンドで返ってくるimage-idで作成します。
- EC2ダッシュボード → インスタンスを起動 →image-idで検索 → t2.microを選択 → "インスタンスの詳細設定", "ストレージの追加" それぞれデフォルトで進む(IAMロールとか特に設定しなくても目的は達せられます)
![]()
- セキュリティグループ設定:とりあえずは ssh, http, httpsを必要に応じて設定しましょう。ロードバランサーを遣わないので、このインスタンスに外部から直接つながる様に設定する必要があります
2. 1のEC2イメージにdocker-compose可能な環境を構築する
- userの作成(下の例では someuser) とsudo権限付与
- 'sudo adduser someuser'
- 'sudo visudo'
- %wheel ALL=(ALL) NOPASSWD: ALL のコメントを外す
- 'sudo usermod -aG wheel someuser'
- dockerのインストール→インストール済みだった。。
- 起動時にdockerが立ち上がっているようにする 'sudo systemctl enable docker'
- docker-composeの取得(最新版だとGLIBCのエラーになるのでその場合はバージョンを下げます)
- sudo curl -L "https://github.com/docker/compose/releases/download/1.28.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
- sudo chmod +x /usr/local/bin/docker-compose
3. route53にドメインが登録されていることを前提に、1のEC2イメージにサブドメインでアクセスできる様にする
4. 1のEC2イメージのapacheを設定しサブドメインでのアクセスに対応する
5. 1のEC2イメージに無料のSSLをインストールする
6. 1のEC2イメージにwordpressのdocker環境を作成して、81版ポートでアクセスできる様に設定する
7. まずは sslなしのポート直接指定でアクセスする
8. 1のEC2イメージのポートフォワード設定をし、ssl接続を可能にする
- 投稿日:2021-01-29T07:55:31+09:00
[書きかけ] ECS+ロードバランサー的なことをEC2で実現して、コスト削減
dockerで開発している場合に、ECSとロードバランサーを遣うと、SSL環境でのサブドメインステージング環境とかあっという間に立てられますよね。
なれてないときはそんなのでポコポコサーバーを立てていたいのですが、ロードバランサー毎に費用がかかったりして立ち上げ期とかで開発予算が少ないときはなにげにボディーブローとなります。そこで、極小のリソースでワードプレスをAWS上に立ててみた方法をまとめます
要件
- 規模が大きくなってきたときにECSを遣うことを想定してそれに近い環境を構築する
- ほぼほぼ、それに近い形の開発環境でdocker-composeで実現する。というか、開発環境のdocker-composeをできる限りAWS上で実現する
- 取得済みのサブドメインでアクセスできる様にする
- 当然SSL接続を実現する
手順
ということで、wordpress のdocker環境をawsに立てる手順をまとめます
- amazon linux2 のEC2イメージを立てる
- 1のEC2イメージにdocker-compose可能な環境を構築する
- route53にドメインが登録されていることを前提に、1のEC2イメージにサブドメインでアクセスできる様にする
- 1のEC2イメージに無料のSSLをインストールする
- 1のEC2イメージにwordpressのdocker環境を作成して、81版ポートでアクセスできる様に設定する
- まずは sslなしのポート直接指定でアクセスする
- 1のEC2イメージのポートフォワード設定をし、ssl接続を可能にする
1. amazon linux2 のEC2イメージを立てる
AWSのアカウントはお持ちでしょうか?
AWSって、サインアップから12ヶ月間の無料枠が結構充実しているんですよね。
AWSのハンズオンイベントに参加すると、新規アカウントを作って初年度の無料クレジットを使ってハンズオンする手順が前提になっていたりします。
ということで、AWSのアカウントを作って12ヶ月以上経っている場合も異なるメールアドレスで新たにアカウント作成して無料枠で色々試してみるということが半ば公式になっていると考えていもいいかもですね。。
開発環境のdockerイメージのとして、centosやubuntuを選択していることが多いかと思いますし、最近だとalpineイメージをベースにして極限までdockerimageを減らす方法もおおい気もします。
で、docker imageを動かすことを前提にEC2環境を構築するとなると、EC2タイプのECSと同じ環境を構築すればいいのかなと。それが amazon-linux-2の様で、下を見ると別のECSに特化しているわけではなさそうです。中身は redhatとのことで、運用に当たって web上でも情報が検索出来る感じになっています
なにげに何か必要なものが出てきたら yum install でインストールして行きます今回必要なEC2イメージは 将来ECSに移行したときに再テストの懸念を極小にすることを念頭に置いているので、ECS向けのEC2構築と同じ手順で立ててみます。
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/getting-started-ecs-ec2.html
2021年1月現在、上の手順の真ん中辺にある「Amazon ECS-optimized AMI」がそれに当たります
AMIイメージにたどり着くのが結構大変なのですが
- https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-optimized_AMI.html
- Amazon ECS-optimized Amazon Linux 2 AMI バリアントという情報を知る
- AMI IDをAWS CLIで取得する(AWS CLIのインストールが必要・・)
- と書いてあるものの、こちらのページで最新情報がリストされていると見つける https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-ami-versions.html#ecs-ami-versions-linux
- Amazon ECS-optimized Amazon Linux 2 AMI の最新IDを見つけます
けど、image idが分からないんですよね。。とはいえ、ここでは、
20201209
というキーワードが見つかるので、"ECS optimized 20201209"というキーワードで検索してみると・・
コミュニティAMIで一件見つかりました正解は "amzn2-ami-ecs-hvm x86_64 20201209" とかで投げた結果が今の時点ではよさそうです。
もっと確実なのは、ちなみに AWS-CLIでコマンドを投げて返ってくる情報
この結果を基にすると
ami-021541b9f47c3c5cc
により、マシンイメージが特定されるわけです
違うのが返ってくるけど、まあ、amazon-ecs-optimizedとなっているのでどちらでも大丈夫そう・・
今回はAWS-CLIコマンドで返ってくるimage-idで作成します。
- EC2ダッシュボード → インスタンスを起動 →image-idで検索 → t2.microを選択 → "インスタンスの詳細設定", "ストレージの追加" それぞれデフォルトで進む(IAMロールとか特に設定しなくても目的は達せられます)
![]()
- セキュリティグループ設定:とりあえずは ssh, http, httpsを必要に応じて設定しましょう。ロードバランサーを遣わないので、このインスタンスに外部から直接つながる様に設定する必要があります
2. 1のEC2イメージにdocker-compose可能な環境を構築する
- userの作成(下の例では someuser) とsudo権限付与
- 'sudo adduser someuser'
- 'sudo visudo'
- %wheel ALL=(ALL) NOPASSWD: ALL のコメントを外す
- 'sudo usermod -aG wheel someuser'
- dockerのインストール→インストール済みだった。。
- 起動時にdockerが立ち上がっているようにする 'sudo systemctl enable docker'
- docker-composeの取得(最新版だとGLIBCのエラーになるのでその場合はバージョンを下げます)
- sudo curl -L "https://github.com/docker/compose/releases/download/1.28.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
- sudo chmod +x /usr/local/bin/docker-compose
3. route53にドメインが登録されていることを前提に、1のEC2イメージにサブドメインでアクセスできる様にする
3-1. 固定ipをわりあてる。
起動しているEC2インスタンスに対してelastic ipを使う場合は料金が発生しないとのこと!
2. Elastic IPアドレスの割り当て 3. Elastic IPアドレスの関連付け 4. 上で起動したインスタンスを選択して「関連付ける」3-2. DNS(Route53)でサブドメインを割り当てる
(既にホストゾーンが作成されていることを前提としています)
* 上で取得したIPアドレスをAレコードとして、サブドメン設定を追加する
* レコード名:サブドメイン ○○.sample.jp とか
* レコードタイプ:A
* 値:上で取得したipアドレス
* その他 デフォルト値で大丈夫かと (ex. TTL=300)4. 1のEC2イメージに無料のSSLをインストールする
ここからは1で作成したEC2イメージに ssh接続しての作業になります
インスタンス概要の「接続」の説明等が参考になります
色々とわかりやすい記事もたくさんあるので、こちらでは割愛します4-1. apacheにバーチャルホストを設定する
大事なのは、次のプロセスで、certbot というツールを使って、証明書を取得するのですが、その際に証明書を取得したいアドレスでhttp接続出来ることが必要なのです。
ということで、まずはhttpサーバーを立てます。ここではapacheをインストールして、サービス登録します
(この先rootユーザーではなく、ステップ2で作ったユーザーでログインしている前提なので注意)sudo yum install -y httpd sudo systemctl start httpd sudo systemctl enable httpdこの環境だと、/etc/httpd/conf配下に httpd.confファイルがあるので、設定ファイル httpd.confを編集し、接続したいサブドメインをバーチャルホストとして設定します
設定の例はこちら
https://httpd.apache.org/docs/2.2/ja/vhosts/examples.htmlsudo vi /etc/httpd/conf/httpd.conf42行目あたりの
Listen 80
を見つけて、その下あたりに次の様な設定を記載する
sub.sample.jp のあたりを書き換えてください。
ここでは、/var/www/html 配下のファイルを sub.sample.jpでアクセスできる様に設定しています
ちなみに、viコマンドで行番号を表示する場合 esc で:set number
で表示されます
DocumentRoot /var/www/html
ServerName sub.sample.jpOther directives here
書き換えたらsudo systemctl restart httpd
で再起動します。
エラーがでたら、httpd.confの記載を見直してください4-2.certbotをインストールして証明書を導入
次の順番でcertbotがインストール出来ました
sudo yum install -y wget sudo yum install -y yum-config-manager sudo wget -r --no-parent -A 'epel-release-*.rpm' http://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/ sudo rpm -Uvh dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-*.rpm sudo amazon-linux-extras install epel -y sudo yum install -y certbot python2-certbot-apacheapacheに対して、SSL設定を導入します
sudo certbot
すると下のメッセージが得られるので、サブドメインを入力しますここまで出来ていたら、certbotコマンドで証明書がインストール出来るはずなので、詳細は割愛します。
詳しくはcertbot apacheとかで検索してみて下さい
参考:https://avinton.com/academy/creating-ssl-certificate-by-certbot/
インストールすると、/etc/httpd/conf 下に httpd-le-ssl.confが生成され、
/etc/httpd/conf/httpd.confのバーチャルホスト設定に以下が追記されるようですRewriteEngine on RewriteCond %{SERVER_NAME} =wp.urcareer.jp RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]と最後の行に
Include /etc/httpd/conf/httpd-le-ssl.conf
4-3. 証明書更新をスケジュールする
この状態だと3ヶ月で証明書が切れてしまうので、スケジューラー cronで自動更新するように設定します
crontab -e
でcron設定のエディタを起動し
00 04 01 * * root /bin/certbot renew --webroot-path /var/www/html/ --post-hook "systemctl reload httpd"
と入力しますで、https://sub.sample.jpとかにアクセス出来るか確認してみましょう
5. 1のEC2イメージにwordpressのdocker環境を作成して、81版ポートでアクセスできる様に設定する
6. まずは sslなしのポート直接指定でアクセスする
7. 1のEC2イメージのポートフォワード設定をし、ssl接続を可能にする
- 投稿日:2021-01-29T06:07:23+09:00
CircleCIのmachine Executorでbuildジョブからdeployジョブへとファイルの受け渡しを行う(Workspace)
概要
CircleCIの
machine Executor
を使用して「Dockerビルド〜デプロイ」を行なっているプロジェクトにおいて、build jobで生成したファイル/ディレクトリをdeploy jobに渡す手順をメモ書きします。方法(結論)
job間にWorkspaceを介してdeployに必要なファイル/ディレクトリを共有します。
persist_to_workspace
後続のdeploy jobへ提供したいファイル/ディレクトリをWorkspaceへアップロードします。
具体的には、build jobの最後のstepで
persist_to_workspace
を実行します。config.yml- persist_to_workspace: root: . paths: - ./app/build - ./app/deps
root:
- ルートにしたいコンテナ上のディレクトリ。
- 絶対パス(もしくは
working_directory
からの相対パス)の形で指定します。paths:
- 上記rootからの相対パスで、jobs間で共有したいファイル/ディレクトリを指定します。
attach_workspace
Workspaceに保存されたデータを
attach_workspace
で取得します。.circleci/config.yml- attach_workspace: at: .
at:
- 絶対パス(もしくは
working_directory
からの相対パス)の形で指定します。補足説明
CircleCIの
jobs
は隔離されている個々の環境で実行される仕様になっています。.circleci/config.yml# 例:build jobで生成されたファイルは、そのままではdeploy jobには渡らない jobs: build: ...: ... deploy: ...: ...そのため、特定のjobの結果を別のjobで使うためには、こういった「Workspaceでデータ共有する」などの方法で受け渡しを行う処理が必要となります。
(画像引用:CircleCI / Jobs overview)
例
実行環境
- macOS
- GitHub(CircleCIと連携済)
シチュエーション
. ├── .circleci/ │ └── config.yml ├── app │ ├── Dockerfile │ ├── (build/) │ ├── (deps/) │ └── moge.json └── docker-compose.yml
- (build)
build job中、docker-compose build
により生成されたビルドファイル群を格納しています- (deps)
擬似コードmoge deps.get
の実行により、app/moge.jsonへ記述した依存パッケージ群が生成されてdepsディレクトリに格納します
npm install
でpackage.json記述パッケージをnode_modules/に格納するのと同じイメージですコード
.circleci/config.ymlversion: 2.1 orbs: # 擬似Orb deploy-orb: deploy-orb/deploy-orb@latest executors: machine-executor: machine: image: ubuntu-1604:202010-01 workflows: version: 2 build-deploy: jobs: - build - deploy: requires: - build jobs: build: executor: name: machine-executor steps: - checkout - run: name: Build Docker container command: | set -x docker-compose build - run: name: Moge deps.get command: | set -x # 擬似コード(依存パッケージ取得) docker-compose run --rm app bash -c "moge deps.get" - run: name: Up Docker container command: docker-compose up -d - run: name: Moge test command: | set -x # 擬似コード(テスト実行) docker-compose exec app bash -c "moge test" - persist_to_workspace: root: . paths: - ./app/build - ./app/deps - run: name: Finish build command: echo "Finish build" deploy: executor: name: machine-executor steps: - checkout - attach_workspace: at: . - run: name: Check files/directories command: | set -x pwd && ls -a && ls app - run: name: Container push and release working_directory: app command: | # 擬似コード(本番環境へビルドコンテナをデプロイ) deploy-orb/install-and-push-release -a $YOUR_APP_NAME - run: name: Finish deploy command: echo "Finish deploy"(参考)
- CircleCI
- Using Workflows to Schedule Jobs
https://circleci.com/docs/2.0/workflows/- Orbs, Jobs, Steps, and Workflows
https://circleci.com/docs/2.0/jobs-steps/- Choosing an Executor Type
https://circleci.com/docs/2.0/executor-types/