TECH PLAY

電通総研

電通総研 の技術ブログ

822

はじめに ISID X(クロス) イノベーション 本部 の三浦です。 権限の問題でシステム部門での作業が必要だったのですが、ようやくシステム部門での作業が完了し、弊社でも AWS Chatbotが Microsoft Teamsでも使えるようになりました。 ということで今さら感もありますが、システム部門の作業前の状態、作業後の一般ユーザーによる設定例、利用方法について記述しようと思います。 目次 はじめに 目次 AWS Chatbot の概要 システム部門の作業前の状態 作業後の一般ユーザーによる設定例 利用例 エイリアスの利用 まとめ AWS Chatbot の概要 簡易な作業でTeams等から AWS の操作を可能にする機能です。同様のことは、 AWS Lambda、webhookを利用すれば実装可能でしたが、 AWS Chatbotによって非常に簡易にできるようになりました。 筆者の場合、開発環境、デモ環境の立ち上げを簡易にやりたいというニーズがありました。 エンジニアが対象の場合は、自身で AWS コンソールから立ち上げるようにする、 スクリプト で起動するといった手も取れます。しかし、非エンジニアが多い場合、依頼を受けて運用エンジニアが起動する、停止するという運用をしている例がありました。 これらの問題を AWS Chatbotを使用して対応する例を示します。 システム部門の作業前の状態 下記の要領で、『Teamsクライアント > アプリ > AWS で検索 > チームに追加』でアプリの登録を試みます。 しかしながら、テナントの設定状況の問題でアプリが使えない状態でした。 上記の旨をシステム部門に申請し、アプリの承認および AWS からのアクセス権付与を対応していただきました。 本作業は、多くのテナントでは一般ユーザーに権限解放されていないと思いますので、システム部門に実施していただく必要があります。 作業後の一般ユーザーによる設定例 上記の対応が済んでいる場合、下記画面より先に進めます。 連携するチャネルを選択します。 しかし、privateチャネルは表示されない、5個以上のチャネルは表示されない(team名+チャネル名で絞り込めます)などのやや癖のある動きをするようです。 連携が終わると、上記のようにメッセージが投稿されます。 続いて、 AWS アカウント側で AWS Chatbot の設定を行っていきます。 まず、チャネル情報を AWS Chatbot で設定する必要があります。ですので、 Microsoft Teams のチャネル一覧から対象チャネルを右クリックし「チャネルへのリンクを取得」メニューから URL を取得します。 続いて、 AWS コンソールにログインし、 AWS Chatbot コンソールを開きます。 チャットクライアント設定画面で Microsoft Teams が選択できるようになっているので、選択します。 先ほど取得した対象チャネルの URL を設定します。 組織として認証済みのため、特に認証画面が出ることなく完了します。 続いて、チャネル登録をします。 チャネル名の表記がURL エンコード で表示されていて見た目が悪いですが、問題なく動作します。 次にこのチャットボットで何ができるか権限を指定します。 下記のように、いくつかロールのテンプレートがあるのですが、それらでは限られた権限しかありません。 そのため、下記の設定より新規にロールを作成します。 『信頼されたエンティティ』に AWS Chatbotを選び 今回はec2の起動、停止をしたいため、一旦雑にEc2FullAccessを指定します。実際に利用されるときは、そのチャネルの利用者のロールに応じて権限を設定するのがよいでしょう。 このようにして作成したIAMロールには、chatbotに対する信頼関係が設定されています。 本ロールを元の画面で設定し、チャネルガードレールポリシーにも同等の権限であるEc2FullAccessを指定します。 これで、chatbotの設定が完了しました。 利用例 それでは、chatbotを利用してみましょう。 chatbotの構文は、ほぼ、 aws cli と同じです。 ということで、 インスタンス の起動を試みます。 初回利用のため、リージョンを設定しろと言われてしまいました。 ということでchatbot上でリージョンを設定します。 再度コマンドを実行すると、本当にこのコマンドを流していいかと聞かれるため実行します。 コマンドが実行されました。 AWS コンロールで確認したところ、 インスタンス が起動していることを確認できました。 同様の手順で インスタンス の停止も可能です。 エイリアス の利用 が、 AWS CLI に相当するものをTeam上で叩けというのは敷居が高いため、 エイリアス を設定します。 下記のような要領で エイリアス の作成が可能です。 開始、停止用の エイリアス を作成したので、さっそく試します。 エイリアス を使用して環境1を立ち上げろと命じたところ、実際に実行するコマンドが展開されて表示されました。 便利ですね。 で、実行すると、下記のようにコマンドが実行されます。 なお、日本語での エイリアス は設定できませんでした。 まとめ このようにして、簡易にTeamsから AWS の インスタンス の開始、停止ができるようになりました。非エンジニアにとって非常に良い機能なのではないかと思っています。 執筆: @miura.toshihiko 、レビュー: @wakamoto.ryosuke ( Shodo で執筆されました )
アバター
はじめに ISID X(クロス) イノベーション 本部 の三浦です。 権限の問題でシステム部門での作業が必要だったのですが、ようやくシステム部門での作業が完了し、弊社でも AWS Chatbotが Microsoft Teamsでも使えるようになりました。 ということで今さら感もありますが、システム部門の作業前の状態、作業後の一般ユーザーによる設定例、利用方法について記述しようと思います。 目次 はじめに 目次 AWS Chatbot の概要 システム部門の作業前の状態 作業後の一般ユーザーによる設定例 利用例 エイリアスの利用 まとめ AWS Chatbot の概要 簡易な作業でTeams等から AWS の操作を可能にする機能です。同様のことは、 AWS Lambda、webhookを利用すれば実装可能でしたが、 AWS Chatbotによって非常に簡易にできるようになりました。 筆者の場合、開発環境、デモ環境の立ち上げを簡易にやりたいというニーズがありました。 エンジニアが対象の場合は、自身で AWS コンソールから立ち上げるようにする、 スクリプト で起動するといった手も取れます。しかし、非エンジニアが多い場合、依頼を受けて運用エンジニアが起動する、停止するという運用をしている例がありました。 これらの問題を AWS Chatbotを使用して対応する例を示します。 システム部門の作業前の状態 下記の要領で、『Teamsクライアント > アプリ > AWS で検索 > チームに追加』でアプリの登録を試みます。 しかしながら、テナントの設定状況の問題でアプリが使えない状態でした。 上記の旨をシステム部門に申請し、アプリの承認および AWS からのアクセス権付与を対応していただきました。 本作業は、多くのテナントでは一般ユーザーに権限解放されていないと思いますので、システム部門に実施していただく必要があります。 作業後の一般ユーザーによる設定例 上記の対応が済んでいる場合、下記画面より先に進めます。 連携するチャネルを選択します。 しかし、privateチャネルは表示されない、5個以上のチャネルは表示されない(team名+チャネル名で絞り込めます)などのやや癖のある動きをするようです。 連携が終わると、上記のようにメッセージが投稿されます。 続いて、 AWS アカウント側で AWS Chatbot の設定を行っていきます。 まず、チャネル情報を AWS Chatbot で設定する必要があります。ですので、 Microsoft Teams のチャネル一覧から対象チャネルを右クリックし「チャネルへのリンクを取得」メニューから URL を取得します。 続いて、 AWS コンソールにログインし、 AWS Chatbot コンソールを開きます。 チャットクライアント設定画面で Microsoft Teams が選択できるようになっているので、選択します。 先ほど取得した対象チャネルの URL を設定します。 組織として認証済みのため、特に認証画面が出ることなく完了します。 続いて、チャネル登録をします。 チャネル名の表記がURL エンコード で表示されていて見た目が悪いですが、問題なく動作します。 次にこのチャットボットで何ができるか権限を指定します。 下記のように、いくつかロールのテンプレートがあるのですが、それらでは限られた権限しかありません。 そのため、下記の設定より新規にロールを作成します。 『信頼されたエンティティ』に AWS Chatbotを選び 今回はec2の起動、停止をしたいため、一旦雑にEc2FullAccessを指定します。実際に利用されるときは、そのチャネルの利用者のロールに応じて権限を設定するのがよいでしょう。 このようにして作成したIAMロールには、chatbotに対する信頼関係が設定されています。 本ロールを元の画面で設定し、チャネルガードレールポリシーにも同等の権限であるEc2FullAccessを指定します。 これで、chatbotの設定が完了しました。 利用例 それでは、chatbotを利用してみましょう。 chatbotの構文は、ほぼ、 aws cli と同じです。 ということで、 インスタンス の起動を試みます。 初回利用のため、リージョンを設定しろと言われてしまいました。 ということでchatbot上でリージョンを設定します。 再度コマンドを実行すると、本当にこのコマンドを流していいかと聞かれるため実行します。 コマンドが実行されました。 AWS コンロールで確認したところ、 インスタンス が起動していることを確認できました。 同様の手順で インスタンス の停止も可能です。 エイリアス の利用 が、 AWS CLI に相当するものをTeam上で叩けというのは敷居が高いため、 エイリアス を設定します。 下記のような要領で エイリアス の作成が可能です。 開始、停止用の エイリアス を作成したので、さっそく試します。 エイリアス を使用して環境1を立ち上げろと命じたところ、実際に実行するコマンドが展開されて表示されました。 便利ですね。 で、実行すると、下記のようにコマンドが実行されます。 なお、日本語での エイリアス は設定できませんでした。 まとめ このようにして、簡易にTeamsから AWS の インスタンス の開始、停止ができるようになりました。非エンジニアにとって非常に良い機能なのではないかと思っています。 執筆: @miura.toshihiko 、レビュー: @wakamoto.ryosuke ( Shodo で執筆されました )
アバター
こんにちは、ISID 金融ソリューション事業部の岡崎です。 今回はUE5で コリジョン (衝突)判定機能を使って、自動で開閉するドアや、 NPC との簡単な会話システムを作成してみます。 はじめに UE5ではフィールド上のさまざまなオブジェクトや、プレイヤーが操作するキャ ラク ターに コリジョン 判定機能を持たせることができます。 これにより、物体にキャ ラク ターが当たった時や、前もって設定しておいた領域に他のオブジェクトが侵入した時などに、 任意の機能を作成できます。 今回はこの コリジョン 判定機能を利用して下記2つの機能を実装します。 キャ ラク ターが近づくと開き、遠ざかると閉じる自動ドアの機能 対象キャ ラク ター( NPC )にプレイヤーが近づき、任意のキーボードを押すと会話が行われる機能 検証環境/ツール Unreal Engine5.2.0 AWS EC2 Windows _Server-2022-English-Full-Base-2023.01.19 実装手順 【自動ドア編】タイムラインを利用したドアのアニメーションの作成 【自動ドア編】 コリジョン を利用した自動開閉システムの作成 【 NPC 会話編】会話UI用の ウィジェット の作成 【 NPC 会話編】 コリジョン を利用した会話UI用の ウィジェット の表示 【 NPC 会話編】 NPC 毎のメッセージ内容切り替え 1. 【自動ドア編】タイムラインを利用したドアのアニメーションの作成 今回はThirdPersonテンプレートを利用したプロジェクトで進めていきます。 まず初めにドアに使用するアクターのBluePrintを作成します。 コンテンツドロワーより、BlueprintClassを選び、Actorを選択します。今回は「BP_Door」という名前にします。 「BP_Door」の編集画面に入ります。 コンポーネント 追加ボタンより、「Static Mesh」を追加し、「Door」と 命名 します。 右側の詳細パネルより、Static Meshのセレクトボックスでスターターコンテンツの「SM_Door」を選びます。 次にドアの当たり判定用に コンポーネント 追加ボタンより、「Box Collision」を追加し、ドアの大きさに合わせて変更します。 またキャ ラク ターがドアをすり抜けてしまわないよう、今作った「Box Collision」のあたり判定を設定する コリジョン プリセットの値を「BlockAllDynamic」に変更します。 続いて、作成したドアにアニメーションをつけていきます。 本ステップでは、ドアにアニメーションをつけることが目的なので、わかりやすくするため、 ゲーム開始時に、ドアが開く仕組みを作成します。 「BP_Door」のイベントグラフを開きます。 「イベント BeginPlay」の後に、ドアに動きをつけるためにタイムラインを使用します。 以前のこちらの記事(UE5 x ZBrushでタイムラインを活用したアニメーションを作成する) で、タイムラインについて詳しく説明しているので、今回は割愛します。 「DoorOpenRate」という名前でタイムラインを作成し、さらに「Rate」というトラックを作成し、下記値を追加しました。 秒数0:値0 秒数0.5:値1 イベントグラフに戻ると、返却値として「Rate」を持つタイムラインができているので、「イベント BeginPlay」のピンとつなぎます。 次に「Make Rotator」ノードを作成しZ軸の値を「90」に設定します。これはドアが90度開くための値になります。 「乗算」ノードを追加し、下の写真のように作成したタイムラインとつなぎます。 最後に「Set Relative Rotation(Door)」を選択し、「New Rotation」にタイムラインから乗算した値をつなぎます。 コンパイル し、Map上に「BP_Door」を配置を行い、ゲームを開始することでドアが開くアニメーションを確認できます。 2. 【自動ドア編】 コリジョン を利用した自動開閉システムの作成 ここでは、 コリジョン を利用して、キャ ラク ターが近づくと自動で開き、離れると自動で閉じるドアにします。 ちなみに先ほどドアに「Box Collision」を使いましたが、これはキャ ラク ターがドアを通り抜けられなくするための コリジョン のため、 これから作る自動ドアの範囲を示す コリジョン とは別のものになります。 「BP_Door」を開き、「 Sphere Collision」を追加します。 次に、「 Sphere Collision」をドアの中心へ移動し拡大を行い、キャ ラク ターが入ると自動でドアが開く領域を設定します。 詳細パネルのイベント欄から「On Component Begin Overlap」と「On Component End Overlap」の右のプラスボタンを押します。 イベントグラフに下のようなノードができていることを確認します。 作成された「On Component Begin Overlap」を「イベント BeginPlay」と入れ替えることで、キャ ラク ターが コリジョン で設定した領域に入ることでドアが開く挙動になります。 また、「On Component End Overlap」をタイムラインの「Reverse」ピンに接続することで、タイムラインで設定した値と逆の挙動が行われるので、キャ ラク ターが領域からでた際にドアが閉まります。 以上がキャ ラク ターが近づくと開き、遠ざかると閉じる自動のドアの機能の紹介になります。 3. 【 NPC 会話編】会話UI用の ウィジェット の作成 続いて、対象キャ ラク ター( NPC )にプレイヤーが近づき、任意のキーボードを押すと会話が行われる機能の作成手順を紹介します。 まずは会話UIに使用する ウィジェット を作成するために、「 Widget Blueprint」を「WBP_ Talk 」という名前で作成します。 ウィジェット の作成方法は 以前のこちらの記事(UE5 PixelStreamingで、マウスカーソルを別の画像に変更してクリックイベントを作成する) で紹介しております。 まずはパレット内の一般から「Border」を「WBP_ Talk 」内に ドラッグ&ドロップ し、「 Canvas Panel」でラップします。 詳細パネルからアンカーを選び、下に伸びているものを選びます。 「Brush」内の「Tint」の部分にカラーピッカーがあるので「A(アルファ)」の値を「0.5」まで下げて、先ほど作成した「Border」を半透明にします。サイズを下の写真のように大きくして簡易的な会話テキストを置く部分のUIとします。 次にパレット内から「Text」を選び、今作成した「Border」内に ドラッグ&ドロップ します。 詳細タブの「Padding」から上下左右中央そろえにします。また、「Font」から文字サイズも「36」に変更します。 これで会話UI用の ウィジェット が出来ました。 実際に画面に表示させてみます。 スターターコンテンツで初期から入っているキャ ラク ターを使用します。 ファイルは、コンテンツ>ThirdPerson>Blueprints>BP_ThirdPersonCharacter にあります。 まずはこのBlueprintから ウィジェット にアクセスできるように設定します。 「 ウィジェット を作成」ノードを追加し、Class属性にWBP_ Talk を設定します。また「Owning Player」には「Get Player Controller」をつなぎます。 次に ウィジェット を作成ノードを「イベント BeginPlay」のピンとつなげます。 「WBP_ Talk ウィジェット を作成」のノードの「Return Value 」を変数としてセットし、「UI_ Talk 」と 命名 します。 次に 「Q」 を押した時に ウィジェット を画面に表示させるようにします。 「Add to Viewport(UI_ Talk )」を選び、 「Q」 のノードとつなぎます。 これで実際に画面に会話用のUIを表示することが出来ました。 ここまでで、会話用のUIに必要な ウィジェット の準備が整いました。 続いて コリジョン を利用して、プレイヤーが操作しているキャ ラク ターの前に、他のキャ ラク ターがいる時のみ 「Q」 を押すことで、会話用のUIを出す機能を作成します。 4. 【 NPC 会話編】 コリジョン を利用した会話UI用の ウィジェット の表示 まずは「BP_ThirdPersonCharacter」のキャ ラク ターに、先ほどドアを作成した時と同じように「 Sphere Collision」を作成します。 キャ ラク ターの前方に下の写真のように「 Sphere Collision」を配置します。 イベントグラフに戻り、「Get Overlapping Actors( Sphere )」を作成します。これは先ほど作成した「 Sphere Collision」に 接触 しているアクターの一覧を配列で返してくれるノードになります。 先ほど作成した 「Q」 を押した後の「ブランチ(IF文)」でfalseだった時に「For Each Loop With Break」ノードで「 Sphere Collision」に 接触 しているアクターの配列を展開します。 本ステップではまだアクターごとに会話の文章の内容を分けず、 コリジョン 内にアクターがある場合のみ会話用のUIを出すだけの処理なので下の写真のように「Add to Viewport」につなぎ、配列がなくなるまでループさせます。 これで、 コリジョン 内にアクターが1つでもあれば、 「Q」 を押すことで会話用のUIを表示できます。 また、このままだと会話用UIが出たままになってしまうので、消去する処理も作成します。 「IsTalk」というBooleanの変数を作成し、会話中ではない時のみ画面に会話用UIが出るように設定します。 また会話中の場合は、画面から会話用UIを消すために「Remove From Parent」ノードを追加し、画面から会話用UIを消去し、「IsTalk」のフラグをfalseに変更します。 実際に試してみるために、マップにいくつかアクターを設置させます。 どんなアクターでも良いですが、今回は NPC 風の人型アクターを作成して設置します。 Blueprint作成画面からCharacterを選択して「BP_ NPC 」を作成します。 コンポーネント 一覧よりより、「Mesh」を選択し、詳細パネルよりメッシュを選びます。今回は「SK_Mannequin」を選択します。 マテリアルも任意のものを選び、マップに配置します。 ここまでの実装で、プレイヤーが操作するキャ ラク ターの前にアクターがある時のみ、 「Q」 を押すことで、会話用のUIが出てくる処理が完成しました。 続いて、マップに配置した NPC ごとに会話の内容を変更させる機能を作成し説明します。 5. 【 NPC 会話編】 NPC 毎のメッセージ内容切り替え まずはアクター間を超えて共通の会話用の関数を使用できるようにブループリントインターフェースを作成します。 コンテンツドロワーからブループリントインターフェースを作成し、「BPI_ Talk 」と 命名 します。 編集画面で「CanTalk」というBooleanを返す関数と、「GetTalkMessage」というTextを返す関数を作成します。 「BP_ NPC 」で2つの関数を使用するために、「BP_ NPC 」を開き画面上部のクラス設定を押し、右側の実装インターフェースのセレクトボックスより「BPI_ Talk 」を選択します。 左側にインターフェース欄が追加され、先ほど作成した2つの関数があることを確認します。 左側のインターフェース欄から「CanTalk」をダブルクリックで開き、Booleanの返り値をtrueに設定します。 同様に「GetTalkMessage」を開き、リターンノードのTextの返り値を変数としてセットし、「TalkMessage」と 命名 します。 さらに、変数欄の右側の目のアイコンをクリックして、UEの全体の編集画面から直接変数の値を変更できるように設定しておきます。 最後のステップとして「BP_ThirdPersonCharacter」を開き、前にいるアクター(BP_ NPC )が「CanTalk」でtrueを返しているかをチェックし、trueだった場合に「TalkMessage」でセットした文字列を会話用UIに埋め込んで表示させる処理を作成します。 先ほど配列で取得した コリジョン 内のアクターをForEachで回している部分で、「CanTalk」がtrueかどうか確認するためにノードを追加します。 trueだった場合に、さらにそのアクターが設定してある会話の内容を「GetTalkMessage」から取得します。 (BP_ NPC は全て「CanTalk」をtrueで返す設定をしています。) 「GetTalkMessage」のターゲットはアクターの配列が入っている「Array Element」です。 次に取得してきた会話の内容を「WBP_ Talk 」の中に埋め込みます。 「WBP_ Talk 」を開き、階層から「Text」を選択します。次に右上の「is Variable」にチェックを入れ、「 Widget _TalkMessage」と 命名 します。 「WBP_ Talk 」をグラフ表示に変更して、関数を作成します。今回は「 Widget _SetTextMessage」と 命名 します。 インプットにTextを設定します。 「SetText(Text)」ノードをつなぎ、ターゲットに「 Widget _TalkMessage」を設定し、ターゲットに「UI_ Talk 」をつなぎます。 「BP_ThirdPersonCharacter」に戻り、「 Widget _SetTextMessage」ノードを作成し、「GetTalkMessage」とつなぎます。 最後に「Add to Viewport」と繋ぐことでBlueprint側での処理は完了です。 全体の処理は下記のような流れになっています。 UEの編集画面からアクターを選択し、詳細タブの「 Talk Massage」欄に任意の文言を追加することで、アクターごとに会話する内容を設定できます。 実際に会話を行ってみます。 以上が コリジョン 機能を使って、自動で開閉するドアや、 NPC との簡単な会話システムの作成方法の紹介です。 所感 コリジョン を利用することで、オブジェクトを動かしたり、重なったアクターの情報を取得したりと、さまざまな使い方ができることがわかりました。 また、基本的な会話の作り方もわかったので、より複雑な会話方法や、 ウィジェット の作成方法なども学習していきます。 特に ウィジェット でできることはまだまだありそうなので、もう少し深ぼって調査していきたいと思います。 現在ISIDは web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間を、是非お待ちしております! ISID採用ページ(Web3/メタバース/AI) 参考 https://note.com/ak_schweitzer/n/n2a7b116c8ee8 https://qiita.com/4_mio_11/items/fed86efca7407a7975fb https://www.youtube.com/watch?v=b8AwUvTaCs0& 執筆: @okazaki.wataru 、レビュー: @wakamoto.ryosuke ( Shodo で執筆されました )
アバター
こんにちは、ISID 金融ソリューション事業部の岡崎です。 今回はUE5で コリジョン (衝突)判定機能を使って、自動で開閉するドアや、 NPC との簡単な会話システムを作成してみます。 はじめに UE5ではフィールド上のさまざまなオブジェクトや、プレイヤーが操作するキャ ラク ターに コリジョン 判定機能を持たせることができます。 これにより、物体にキャ ラク ターが当たった時や、前もって設定しておいた領域に他のオブジェクトが侵入した時などに、 任意の機能を作成できます。 今回はこの コリジョン 判定機能を利用して下記2つの機能を実装します。 キャ ラク ターが近づくと開き、遠ざかると閉じる自動ドアの機能 対象キャ ラク ター( NPC )にプレイヤーが近づき、任意のキーボードを押すと会話が行われる機能 検証環境/ツール Unreal Engine5.2.0 AWS EC2 Windows _Server-2022-English-Full-Base-2023.01.19 実装手順 【自動ドア編】タイムラインを利用したドアのアニメーションの作成 【自動ドア編】 コリジョン を利用した自動開閉システムの作成 【 NPC 会話編】会話UI用の ウィジェット の作成 【 NPC 会話編】 コリジョン を利用した会話UI用の ウィジェット の表示 【 NPC 会話編】 NPC 毎のメッセージ内容切り替え 1. 【自動ドア編】タイムラインを利用したドアのアニメーションの作成 今回はThirdPersonテンプレートを利用したプロジェクトで進めていきます。 まず初めにドアに使用するアクターのBluePrintを作成します。 コンテンツドロワーより、BlueprintClassを選び、Actorを選択します。今回は「BP_Door」という名前にします。 「BP_Door」の編集画面に入ります。 コンポーネント 追加ボタンより、「Static Mesh」を追加し、「Door」と 命名 します。 右側の詳細パネルより、Static Meshのセレクトボックスでスターターコンテンツの「SM_Door」を選びます。 次にドアの当たり判定用に コンポーネント 追加ボタンより、「Box Collision」を追加し、ドアの大きさに合わせて変更します。 またキャ ラク ターがドアをすり抜けてしまわないよう、今作った「Box Collision」のあたり判定を設定する コリジョン プリセットの値を「BlockAllDynamic」に変更します。 続いて、作成したドアにアニメーションをつけていきます。 本ステップでは、ドアにアニメーションをつけることが目的なので、わかりやすくするため、 ゲーム開始時に、ドアが開く仕組みを作成します。 「BP_Door」のイベントグラフを開きます。 「イベント BeginPlay」の後に、ドアに動きをつけるためにタイムラインを使用します。 以前のこちらの記事(UE5 x ZBrushでタイムラインを活用したアニメーションを作成する) で、タイムラインについて詳しく説明しているので、今回は割愛します。 「DoorOpenRate」という名前でタイムラインを作成し、さらに「Rate」というトラックを作成し、下記値を追加しました。 秒数0:値0 秒数0.5:値1 イベントグラフに戻ると、返却値として「Rate」を持つタイムラインができているので、「イベント BeginPlay」のピンとつなぎます。 次に「Make Rotator」ノードを作成しZ軸の値を「90」に設定します。これはドアが90度開くための値になります。 「乗算」ノードを追加し、下の写真のように作成したタイムラインとつなぎます。 最後に「Set Relative Rotation(Door)」を選択し、「New Rotation」にタイムラインから乗算した値をつなぎます。 コンパイル し、Map上に「BP_Door」を配置を行い、ゲームを開始することでドアが開くアニメーションを確認できます。 2. 【自動ドア編】 コリジョン を利用した自動開閉システムの作成 ここでは、 コリジョン を利用して、キャ ラク ターが近づくと自動で開き、離れると自動で閉じるドアにします。 ちなみに先ほどドアに「Box Collision」を使いましたが、これはキャ ラク ターがドアを通り抜けられなくするための コリジョン のため、 これから作る自動ドアの範囲を示す コリジョン とは別のものになります。 「BP_Door」を開き、「 Sphere Collision」を追加します。 次に、「 Sphere Collision」をドアの中心へ移動し拡大を行い、キャ ラク ターが入ると自動でドアが開く領域を設定します。 詳細パネルのイベント欄から「On Component Begin Overlap」と「On Component End Overlap」の右のプラスボタンを押します。 イベントグラフに下のようなノードができていることを確認します。 作成された「On Component Begin Overlap」を「イベント BeginPlay」と入れ替えることで、キャ ラク ターが コリジョン で設定した領域に入ることでドアが開く挙動になります。 また、「On Component End Overlap」をタイムラインの「Reverse」ピンに接続することで、タイムラインで設定した値と逆の挙動が行われるので、キャ ラク ターが領域からでた際にドアが閉まります。 以上がキャ ラク ターが近づくと開き、遠ざかると閉じる自動のドアの機能の紹介になります。 3. 【 NPC 会話編】会話UI用の ウィジェット の作成 続いて、対象キャ ラク ター( NPC )にプレイヤーが近づき、任意のキーボードを押すと会話が行われる機能の作成手順を紹介します。 まずは会話UIに使用する ウィジェット を作成するために、「 Widget Blueprint」を「WBP_ Talk 」という名前で作成します。 ウィジェット の作成方法は 以前のこちらの記事(UE5 PixelStreamingで、マウスカーソルを別の画像に変更してクリックイベントを作成する) で紹介しております。 まずはパレット内の一般から「Border」を「WBP_ Talk 」内に ドラッグ&ドロップ し、「 Canvas Panel」でラップします。 詳細パネルからアンカーを選び、下に伸びているものを選びます。 「Brush」内の「Tint」の部分にカラーピッカーがあるので「A(アルファ)」の値を「0.5」まで下げて、先ほど作成した「Border」を半透明にします。サイズを下の写真のように大きくして簡易的な会話テキストを置く部分のUIとします。 次にパレット内から「Text」を選び、今作成した「Border」内に ドラッグ&ドロップ します。 詳細タブの「Padding」から上下左右中央そろえにします。また、「Font」から文字サイズも「36」に変更します。 これで会話UI用の ウィジェット が出来ました。 実際に画面に表示させてみます。 スターターコンテンツで初期から入っているキャ ラク ターを使用します。 ファイルは、コンテンツ>ThirdPerson>Blueprints>BP_ThirdPersonCharacter にあります。 まずはこのBlueprintから ウィジェット にアクセスできるように設定します。 「 ウィジェット を作成」ノードを追加し、Class属性にWBP_ Talk を設定します。また「Owning Player」には「Get Player Controller」をつなぎます。 次に ウィジェット を作成ノードを「イベント BeginPlay」のピンとつなげます。 「WBP_ Talk ウィジェット を作成」のノードの「Return Value 」を変数としてセットし、「UI_ Talk 」と 命名 します。 次に 「Q」 を押した時に ウィジェット を画面に表示させるようにします。 「Add to Viewport(UI_ Talk )」を選び、 「Q」 のノードとつなぎます。 これで実際に画面に会話用のUIを表示することが出来ました。 ここまでで、会話用のUIに必要な ウィジェット の準備が整いました。 続いて コリジョン を利用して、プレイヤーが操作しているキャ ラク ターの前に、他のキャ ラク ターがいる時のみ 「Q」 を押すことで、会話用のUIを出す機能を作成します。 4. 【 NPC 会話編】 コリジョン を利用した会話UI用の ウィジェット の表示 まずは「BP_ThirdPersonCharacter」のキャ ラク ターに、先ほどドアを作成した時と同じように「 Sphere Collision」を作成します。 キャ ラク ターの前方に下の写真のように「 Sphere Collision」を配置します。 イベントグラフに戻り、「Get Overlapping Actors( Sphere )」を作成します。これは先ほど作成した「 Sphere Collision」に 接触 しているアクターの一覧を配列で返してくれるノードになります。 先ほど作成した 「Q」 を押した後の「ブランチ(IF文)」でfalseだった時に「For Each Loop With Break」ノードで「 Sphere Collision」に 接触 しているアクターの配列を展開します。 本ステップではまだアクターごとに会話の文章の内容を分けず、 コリジョン 内にアクターがある場合のみ会話用のUIを出すだけの処理なので下の写真のように「Add to Viewport」につなぎ、配列がなくなるまでループさせます。 これで、 コリジョン 内にアクターが1つでもあれば、 「Q」 を押すことで会話用のUIを表示できます。 また、このままだと会話用UIが出たままになってしまうので、消去する処理も作成します。 「IsTalk」というBooleanの変数を作成し、会話中ではない時のみ画面に会話用UIが出るように設定します。 また会話中の場合は、画面から会話用UIを消すために「Remove From Parent」ノードを追加し、画面から会話用UIを消去し、「IsTalk」のフラグをfalseに変更します。 実際に試してみるために、マップにいくつかアクターを設置させます。 どんなアクターでも良いですが、今回は NPC 風の人型アクターを作成して設置します。 Blueprint作成画面からCharacterを選択して「BP_ NPC 」を作成します。 コンポーネント 一覧よりより、「Mesh」を選択し、詳細パネルよりメッシュを選びます。今回は「SK_Mannequin」を選択します。 マテリアルも任意のものを選び、マップに配置します。 ここまでの実装で、プレイヤーが操作するキャ ラク ターの前にアクターがある時のみ、 「Q」 を押すことで、会話用のUIが出てくる処理が完成しました。 続いて、マップに配置した NPC ごとに会話の内容を変更させる機能を作成し説明します。 5. 【 NPC 会話編】 NPC 毎のメッセージ内容切り替え まずはアクター間を超えて共通の会話用の関数を使用できるようにブループリントインターフェースを作成します。 コンテンツドロワーからブループリントインターフェースを作成し、「BPI_ Talk 」と 命名 します。 編集画面で「CanTalk」というBooleanを返す関数と、「GetTalkMessage」というTextを返す関数を作成します。 「BP_ NPC 」で2つの関数を使用するために、「BP_ NPC 」を開き画面上部のクラス設定を押し、右側の実装インターフェースのセレクトボックスより「BPI_ Talk 」を選択します。 左側にインターフェース欄が追加され、先ほど作成した2つの関数があることを確認します。 左側のインターフェース欄から「CanTalk」をダブルクリックで開き、Booleanの返り値をtrueに設定します。 同様に「GetTalkMessage」を開き、リターンノードのTextの返り値を変数としてセットし、「TalkMessage」と 命名 します。 さらに、変数欄の右側の目のアイコンをクリックして、UEの全体の編集画面から直接変数の値を変更できるように設定しておきます。 最後のステップとして「BP_ThirdPersonCharacter」を開き、前にいるアクター(BP_ NPC )が「CanTalk」でtrueを返しているかをチェックし、trueだった場合に「TalkMessage」でセットした文字列を会話用UIに埋め込んで表示させる処理を作成します。 先ほど配列で取得した コリジョン 内のアクターをForEachで回している部分で、「CanTalk」がtrueかどうか確認するためにノードを追加します。 trueだった場合に、さらにそのアクターが設定してある会話の内容を「GetTalkMessage」から取得します。 (BP_ NPC は全て「CanTalk」をtrueで返す設定をしています。) 「GetTalkMessage」のターゲットはアクターの配列が入っている「Array Element」です。 次に取得してきた会話の内容を「WBP_ Talk 」の中に埋め込みます。 「WBP_ Talk 」を開き、階層から「Text」を選択します。次に右上の「is Variable」にチェックを入れ、「 Widget _TalkMessage」と 命名 します。 「WBP_ Talk 」をグラフ表示に変更して、関数を作成します。今回は「 Widget _SetTextMessage」と 命名 します。 インプットにTextを設定します。 「SetText(Text)」ノードをつなぎ、ターゲットに「 Widget _TalkMessage」を設定し、ターゲットに「UI_ Talk 」をつなぎます。 「BP_ThirdPersonCharacter」に戻り、「 Widget _SetTextMessage」ノードを作成し、「GetTalkMessage」とつなぎます。 最後に「Add to Viewport」と繋ぐことでBlueprint側での処理は完了です。 全体の処理は下記のような流れになっています。 UEの編集画面からアクターを選択し、詳細タブの「 Talk Massage」欄に任意の文言を追加することで、アクターごとに会話する内容を設定できます。 実際に会話を行ってみます。 以上が コリジョン 機能を使って、自動で開閉するドアや、 NPC との簡単な会話システムの作成方法の紹介です。 所感 コリジョン を利用することで、オブジェクトを動かしたり、重なったアクターの情報を取得したりと、さまざまな使い方ができることがわかりました。 また、基本的な会話の作り方もわかったので、より複雑な会話方法や、 ウィジェット の作成方法なども学習していきます。 特に ウィジェット でできることはまだまだありそうなので、もう少し深ぼって調査していきたいと思います。 現在ISIDは web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間を、是非お待ちしております! 私たちは一緒に働いてくれる仲間を募集しています! 電通総研中途採用ページ 電通総研新卒採用ページ 参考 https://note.com/ak_schweitzer/n/n2a7b116c8ee8 https://qiita.com/4_mio_11/items/fed86efca7407a7975fb https://www.youtube.com/watch?v=b8AwUvTaCs0& 執筆: @okazaki.wataru 、レビュー: @wakamoto.ryosuke ( Shodo で執筆されました )
アバター
電通国際情報サービス 、オープン イノベーション ラボの 比嘉康雄 です。 今回は、 Expo に入門します。 Expo とは、開発者が React Native 単体で開発した場合に意識しないといけなかったネイティブ部分を隠蔽して、アプリケーション本体の開発をより Web アプリケーションの開発体験に近づけたものです。 expo cliのインストール Expo Goのインストール プロジェクトの作成 QRコードの読み取り アプリの修正 まとめ 仲間募集 expo cli のインストール expo cli は、下記のようにして、npxでインストールするようです。 npx expo -h 実行すると下記のように言われるので、yでインストールします。 Need to install the following packages: expo@48.0.17 Ok to proceed? (y) Expo Goのインストール Expo Go は、ローカルで何も構築する必要がなく、Android および iOS 上で React Native アプリをテストするための無料のオープンソース クライアントです。 Android または iOS デバイスで Expo Go クライアントアプリを使用するのが、最も速く起動して実行できる方法です。これにより、Expo CLI を通じて提供されるアプリを開いて、開発時にプロジェクトをより速く実行できます。 と公式が言っているので、Expo Goを使いましょう。 iOSのApp Store や AndroidのPay Store からインストールしてください。 プロジェクトの作成 npx create-expo-app my-app でプロジェクトを作成しましょう。 my-app に移動して、プロジェクトを開始します。 cd my-app npx expo start QRコード の読み取り QRコード が表示されます。 Scan the QR code above with Expo Go (Android) or the Camera app (iOS) と言われるので、僕は、 iPhone のカメラで QRコード を読み込みました。Expo Goが立ち上がって、下記のようにアプリが表示されます。 Open up App.js to start working on your app! アプリの修正 my-app ディレクト リで、 VS Code を立ち上げます。 code . App.js のTextタグで囲まれている部分を適当に修正してください。アプリの表示もすぐ変わります(HOT Reloading)。 まとめ Expoは、Webアプリを開発しているような感覚で、Nativeアプリを開発できるというのは、本当だなと感じました。Expoはもう少し詳しく見ていきたいと思います。 仲間募集 私たちは同じグループで共に働いていただける仲間を募集しています。 現在、以下のような職種を募集しています。 ソリューションアーキテクト AIエンジニア 執筆: @higa ( Shodo で執筆されました )
アバター
電通国際情報サービス 、オープン イノベーション ラボの 比嘉康雄 です。 今回は、 Expo に入門します。 Expo とは、開発者が React Native 単体で開発した場合に意識しないといけなかったネイティブ部分を隠蔽して、アプリケーション本体の開発をより Web アプリケーションの開発体験に近づけたものです。 expo cliのインストール Expo Goのインストール プロジェクトの作成 QRコードの読み取り アプリの修正 まとめ 仲間募集 expo cli のインストール expo cli は、下記のようにして、npxでインストールするようです。 npx expo -h 実行すると下記のように言われるので、yでインストールします。 Need to install the following packages: expo@48.0.17 Ok to proceed? (y) Expo Goのインストール Expo Go は、ローカルで何も構築する必要がなく、Android および iOS 上で React Native アプリをテストするための無料のオープンソース クライアントです。 Android または iOS デバイスで Expo Go クライアントアプリを使用するのが、最も速く起動して実行できる方法です。これにより、Expo CLI を通じて提供されるアプリを開いて、開発時にプロジェクトをより速く実行できます。 と公式が言っているので、Expo Goを使いましょう。 iOSのApp Store や AndroidのPay Store からインストールしてください。 プロジェクトの作成 npx create-expo-app my-app でプロジェクトを作成しましょう。 my-app に移動して、プロジェクトを開始します。 cd my-app npx expo start QRコード の読み取り QRコード が表示されます。 Scan the QR code above with Expo Go (Android) or the Camera app (iOS) と言われるので、僕は、 iPhone のカメラで QRコード を読み込みました。Expo Goが立ち上がって、下記のようにアプリが表示されます。 Open up App.js to start working on your app! アプリの修正 my-app ディレクト リで、 VS Code を立ち上げます。 code . App.js のTextタグで囲まれている部分を適当に修正してください。アプリの表示もすぐ変わります(HOT Reloading)。 まとめ Expoは、Webアプリを開発しているような感覚で、Nativeアプリを開発できるというのは、本当だなと感じました。Expoはもう少し詳しく見ていきたいと思います。 仲間募集 私たちは同じグループで共に働いていただける仲間を募集しています。 現在、以下のような職種を募集しています。 ソリューションアーキテクト AIエンジニア 執筆: @higa ( Shodo で執筆されました )
アバター
こんにちは、X(クロス) イノベーション 本部 クラウド イノベーション センターの田村です。 普段は Microsoft が提供する クラウド サービスである Azure を活用した案件支援や、研究開発を担当しています。 本記事では、業務内容や 1 週間の過ごし方など、私の主な働き方についてざっくりとご紹介します。 IT 企業への就職を検討されている学生の方や、ISID にご興味をお持ちの方の参考になれば幸いです。 自己紹介 業務内容 案件支援 研究開発 その他 1 週間の過ごし方 最後に 自己紹介 タイトルにもありますが、2020 年に新卒入社した 4 年目社員です。 入社後に半年間の研修を経て、 クラウド イノベーション センターに配属となりました。 学生時代に クラウド をはじめとした IT 系の 経験がほぼなく、「絶対に クラウド に関する仕事がしたい」といった希望もなかったため意外ではありましたが、何かの縁だろうと仕事を続け今日に至ります。 業務内容 冒頭でご紹介した通り、 Microsoft Azure を活用した案件支援と研究開発が主な業務です。 Azure といっても多種多様なサービスがありますが、私の業務では主にデータ分析の領域を扱っています。 具体的に何をしているのかについては、個別でご紹介いたします。 案件支援 近年は IoT や ビッグデータ などのワードが普及し、企業においてもデータ分析のニーズが高まっています。 ISID に限らず、データ分析を中心に据えたプロジェクトは数多くありますが、私が参画する支援業務で求められるのは「お客様の抱える様々な潜在・顕在課題や要望に対して、Azure を活用したデータ分析による価値提供を行う」ことです。 実際にいただいたお客様からの要望にはこんなものがあります。 社内に散在している業務データを一元管理できるデータ分析基盤を構築してほしい オフィスビル 内の環境情報(温度/湿度/照度/空気状態など)を収集・分析し一目で把握したい オフィスビル のデジタルツインを作成する実証実験(PoC)を実施したい お客様の要望に応じて作業内容は異なりますが、大まかには ヒアリ ングを重ねて要件をすり合わせる、Azure および周辺システムの設計・構築を行う、分析結果を可視化するレポート画面の作成をする、といった業務を経験してきました。 現場ではデータ分析に限定しない Azure の幅広いサービスや 他の Microsoft 製品、場合によっては他社ソリューションに対する知識・スキルが要求されるので、 クラウド エンジニアという職種としてよい経験が積めていると感じています。 研究開発 Azure のデータ領域におけるアップデート内容の調査検証が中心です。 Azure をはじめとする クラウド サービスは一般的なパッケージ製品と比較してアップデートのスパンが短く、1 週間後には機能・仕様が変更されるというケースもあります。 そのような変化に追いついていくために、チーム内で Azure の新しいサービスや機能を共有し、「将来的に案件支援や社内ソリューションに適用できる見込みがある」と判断したものに対して調査検証を実施しています。 具体的な調査検証の内容については、以前に投稿した記事をご覧ください。 Azure Managed Grafana について調べてみた 調査検証の結果は下記の観点でまとめ、資料化して社内に展開しています。 また、インターネット上に同様の調査結果が報告されていない場合は、前述したようにこちらのテックブログや Qiita/ Twitter で社外発信する場合もあります。 どのようなアップデートなのか? できること、できないことは何か? 調査検証時点で考えられる具体的な使用例は何か? 類似・競合サービスとの差別化点は? どのくらいのコストが必要か? 上記の他にも、Azure を活用した社内ソリューション開発、Azure データ分析プロジェクトで要件定義から運用に必要なツールやドキュメントを網羅したテンプレートの作成、データ領域におけるトレンドの調査などを実施してきました。 研究開発の内容に関わらず、ノウハウを蓄積し案件支援に活かしていくというサイクルを大事にしています。 その他 ここまで記載したもの以外にも、経験してきた業務がいくつかあります。 新卒社員向けの システム開発 研究のサポート OJT サポート業務 新規事業開発・提案 ISID は、若い年次でも「やりたい」という仕事をアピールすればチャレンジできる土壌があると感じています。 1 週間の過ごし方 プロジェクトの状況によってまちまちですが、おおよそ下図の通りです。 毎日の始業時に朝会を実施し、チーム内で本日の業務内容と全体のタスク、事務連絡等を共有します。 その後は案件支援や研究開発に関する打ち合わせや個人作業の時間となり、空き時間は自己学習やこういった記事執筆などに充てています。 基本的にテレワークなので終業後は自宅で過ごすことが多いですが、週 1 程度で同期とフットサルをしています。 最後に X(クロス) イノベーション 本部 クラウド イノベーション センターでは、新卒・キャリア採用問わず共に働いてくれる仲間を探しています。 本記事で紹介した私の働き方や、 クラウド を中心とした業務にご興味をお持ちの方は、ぜひ採用ページよりご応募ください。 新卒採用の方: ISID 新卒採用サイト キャリア採用の方: ISID グループ キャリア採用サイト - クラウドアーキテクト 執筆: @tamura.kohei 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました )
アバター
こんにちは、X(クロス) イノベーション 本部 クラウド イノベーション センターの田村です。 普段は Microsoft が提供する クラウド サービスである Azure を活用した案件支援や、研究開発を担当しています。 本記事では、業務内容や 1 週間の過ごし方など、私の主な働き方についてざっくりとご紹介します。 IT 企業への就職を検討されている学生の方や、ISID にご興味をお持ちの方の参考になれば幸いです。 自己紹介 業務内容 案件支援 研究開発 その他 1 週間の過ごし方 最後に 自己紹介 タイトルにもありますが、2020 年に新卒入社した 4 年目社員です。 入社後に半年間の研修を経て、 クラウド イノベーション センターに配属となりました。 学生時代に クラウド をはじめとした IT 系の 経験がほぼなく、「絶対に クラウド に関する仕事がしたい」といった希望もなかったため意外ではありましたが、何かの縁だろうと仕事を続け今日に至ります。 業務内容 冒頭でご紹介した通り、 Microsoft Azure を活用した案件支援と研究開発が主な業務です。 Azure といっても多種多様なサービスがありますが、私の業務では主にデータ分析の領域を扱っています。 具体的に何をしているのかについては、個別でご紹介いたします。 案件支援 近年は IoT や ビッグデータ などのワードが普及し、企業においてもデータ分析のニーズが高まっています。 ISID に限らず、データ分析を中心に据えたプロジェクトは数多くありますが、私が参画する支援業務で求められるのは「お客様の抱える様々な潜在・顕在課題や要望に対して、Azure を活用したデータ分析による価値提供を行う」ことです。 実際にいただいたお客様からの要望にはこんなものがあります。 社内に散在している業務データを一元管理できるデータ分析基盤を構築してほしい オフィスビル 内の環境情報(温度/湿度/照度/空気状態など)を収集・分析し一目で把握したい オフィスビル のデジタルツインを作成する実証実験(PoC)を実施したい お客様の要望に応じて作業内容は異なりますが、大まかには ヒアリ ングを重ねて要件をすり合わせる、Azure および周辺システムの設計・構築を行う、分析結果を可視化するレポート画面の作成をする、といった業務を経験してきました。 現場ではデータ分析に限定しない Azure の幅広いサービスや 他の Microsoft 製品、場合によっては他社ソリューションに対する知識・スキルが要求されるので、 クラウド エンジニアという職種としてよい経験が積めていると感じています。 研究開発 Azure のデータ領域におけるアップデート内容の調査検証が中心です。 Azure をはじめとする クラウド サービスは一般的なパッケージ製品と比較してアップデートのスパンが短く、1 週間後には機能・仕様が変更されるというケースもあります。 そのような変化に追いついていくために、チーム内で Azure の新しいサービスや機能を共有し、「将来的に案件支援や社内ソリューションに適用できる見込みがある」と判断したものに対して調査検証を実施しています。 具体的な調査検証の内容については、以前に投稿した記事をご覧ください。 Azure Managed Grafana について調べてみた 調査検証の結果は下記の観点でまとめ、資料化して社内に展開しています。 また、インターネット上に同様の調査結果が報告されていない場合は、前述したようにこちらのテックブログや Qiita/ Twitter で社外発信する場合もあります。 どのようなアップデートなのか? できること、できないことは何か? 調査検証時点で考えられる具体的な使用例は何か? 類似・競合サービスとの差別化点は? どのくらいのコストが必要か? 上記の他にも、Azure を活用した社内ソリューション開発、Azure データ分析プロジェクトで要件定義から運用に必要なツールやドキュメントを網羅したテンプレートの作成、データ領域におけるトレンドの調査などを実施してきました。 研究開発の内容に関わらず、ノウハウを蓄積し案件支援に活かしていくというサイクルを大事にしています。 その他 ここまで記載したもの以外にも、経験してきた業務がいくつかあります。 新卒社員向けの システム開発 研究のサポート OJT サポート業務 新規事業開発・提案 ISID は、若い年次でも「やりたい」という仕事をアピールすればチャレンジできる土壌があると感じています。 1 週間の過ごし方 プロジェクトの状況によってまちまちですが、おおよそ下図の通りです。 毎日の始業時に朝会を実施し、チーム内で本日の業務内容と全体のタスク、事務連絡等を共有します。 その後は案件支援や研究開発に関する打ち合わせや個人作業の時間となり、空き時間は自己学習やこういった記事執筆などに充てています。 基本的にテレワークなので終業後は自宅で過ごすことが多いですが、週 1 程度で同期とフットサルをしています。 最後に X(クロス) イノベーション 本部 クラウド イノベーション センターでは、新卒・キャリア採用問わず共に働いてくれる仲間を探しています。 本記事で紹介した私の働き方や、 クラウド を中心とした業務にご興味をお持ちの方は、ぜひ採用ページよりご応募ください。 新卒採用の方: ISID 新卒採用サイト キャリア採用の方: ISID グループ キャリア採用サイト - クラウドアーキテクト 執筆: @tamura.kohei 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました )
アバター
こんにちは、ISID 金融ソリューション事業部の岡崎です。 今回はUE5で マルチプレイ に対応したエモート機能を作成する方法をご紹介します。 エモート機能とは、 マルチプレイ のゲームにおいて、各キャ ラク ターが感情を表現する為の機能です。 例えば Fortnite ではキャ ラク ターに様々な動きやダンスをさせることができます。 はじめに UE5では「ListenServer」と「DedicatedServer」の2種類のゲームサーバー方式が使用可能です。 各サーバーについては、こちらの 金融ソリューション事業部の山下さんの記事 で紹介されているので説明は割愛します。 今回は検証を簡易にするため「ListenServer」を使用して マルチプレイ でのエモート機能を作成しますが、 「DedicatedServer」でも同じ挙動をする実装方法となります。 検証環境/ツール Unreal Engine5.2.0 AWS EC2 Windows _Server-2022-English-Full-Base-2023.01.19 実装手順 エモート用WidgetBlueprintの作成 エモート用 Widget をCharacterBlueprintに付与 CharacterBlueprintの動作作成 マルチプレイ 用 レプリケーション 設定 1. エモート用WidgetBlueprintの作成 今回はThirdPersonテンプレートを利用したプロジェクトで進めていきます。 まず初めにエモート用 Widget に使用するWidgetBluePrintを作成します。 コンテンツドロワーより、WidgetBlueprintを選び「WBP_IconEmote」で作成します。 以前紹介した UE5 PixelStreamingで、マウスカーソルを別の画像に変更してクリックイベントを作成する記事 にて、 WidgetBlueprint内に任意の画像を取り込む方法があるので、同様にエモートに使用したい画像を取り込み「IconEmote」という名前をつけました。また前回同様「 Canvas Panel」を作成し、位置を中心に変更させます。 今回は別のBlueprintでもこの Widget を呼び出して使う予定なので、詳細タブの上部にある「Is Variable」にチェックを入れておきます。 2. エモート用 Widget をCharacterBlueprintに付与 まずはCharacterBlueprintを開きます。 ThirdPersonTemplateを使用して作成したプロジェクトの場合、 All>Content>ThirdPerson>Blueprints内に「BP_ThirdPersonCharacter」を見つけることができます。 「BP_ThirdPersonCharacter」のViewPortを開き、 Widget 用の コンポーネント を追加します。 ViewProt左上部の追加ボタンを押して Widget と検索し、クリックで選択します。 左側の コンポーネント 一覧に追加されるので、名前を「 Widget _IconEmote」と変更します。 次に追加した「 Widget _IconEmote」と、先ほど作成した「WBP_IconEmote」を連携させます。 右側の ユーザーインターフェース 内の「 Widget Class」のセレクトボックスで「WBP_IconEmote」を選択します。 連携すると下記画像のように追加したエモート画像がCharacterBlueprintに付与されます。 トランスフォーム欄から位置や大きさを動かすことで、エモート機能のようになってきました。 コンパイル 、保存を行い、レベルのViewPortで確認してみます。 キャ ラク ターの頭上にアイコンを出すことは出来ましたが、キャ ラク ターが横を向くとアイコンも横を向いてしまい画面から見えなくなってしまいました。 解決法として、ViewPortの ユーザーインターフェース 欄のSpaceのセレクトボックスを「World」から「画面」を選ぶことで、キャ ラク ターがどの向きを向いてもエモートアイコンが見えるように設定できます。 3. CharacterBlueprintの動作作成 今回は、キーボードの「5」を押した時に、2秒間エモートアイコンがキャ ラク ターの頭上に表示されるBlueprintを作成します。 今のままでは、アイコンが出続けてしまうのでまずゲームスタートとともにアイコンを隠す処理を行います。 まずは「BP_ThirdPersonCharacter」から「WBP_IconEmote」に接続できるように「Event BeginPlay」から「Cast To WBP_IconEmote」をピンでつなげます。 さらにObject属性に対して、「Get User Widget Object」ノードを追加し、ターゲットを「 Widget Icon Emote」にします。 これにより、「BP_ThirdPersonCharacter」から「WBP_IconEmote」に接続できるようになりました。 次に、アイコンを非表示にするために「Set Visibility」ノードを接続し、ターゲットを「Cast To WBP_IconEmote」の「As WBP Emote」に接続します。「In Visibility」の値を「非表示」にすることで、アイコンを非表示にできますが、今回は後述の マルチプレイ 用に、表示・非表示を司る変数を作成しておきます。 画面左下の変数欄からプラスを押し、「var_IconEmoteByte」という変数を作成します。タイプはByteを選択し、デフォルト値を「2」にします。 作成した「var_IconEmoteByte」を「Set Visibility」につなぎます。 ここで入力した「2」というのは、「In Visibility」の値の配列番号になり、「非表示」を意味しています。 ここまでで、キャ ラク ター頭上のアイコンは一旦非表示になっているはずです。 次にキーボードの「5」を押した時にアイコンを表示させる処理の説明を行います。 「Press 5」ノードを追加し、「Pressed」のピンに対して、「var_IconEmoteByte」をセットするためのノードを追加します。 変数の値を「0」(「In Visibility」の値の配列番号になり、「表示」の意)に書き換える処理の後に、先ほど作成した「Cast To WBP_IconEmote」の流れを複製します。 これにより、キーボードの「5」を押した時にアイコンを表示させることができます。 しかし、この状態ではまだ左右の画面( マルチプレイヤー 間)での同期は取れていないので、 次のステップで修正していきます。 4. マルチプレイ 用 レプリケーション 設定 UEで マルチプレイ を行う際は、ゲームサーバーがゲームクライアントに対して、情報をレプリケート(複製)することで、 各クライアント間(プレイヤー間)での差異が生じないようになります。 今回作った処理は、まだクライアントで行われているだけの処理なので、クライアント間では同期されません。 まずは先ほど作成した変数「var_IconEmoteByte」を レプリケーション する設定にします。 「var_IconEmoteByte」の詳細画面から レプリケーション の設定を「RepNotify」に設定します。 「RepNotify」とは、変数の値をウォッチしており、変数の値が変わった時に後続の関数「OnRep〜」関数を起動させます。 変数を「RepNotify」設定にすると、左側の関数欄に「OnRep_var_IconEmoteByte」という関数ができます。 次に、「Cast To WBP_IconEmote」から「Set Visibility」の処理をコピーし、「OnRep_var_IconEmoteByte」内で貼り付けます。 「OnRep_var_IconEmoteByte」内への移動方法は、左側の関数欄の「OnRep_var_IconEmoteByte」をダブルクリックすることで移動ができます。 貼り付けた処理を「On Rep Var Icon Emote Byte」ノードに繋ぎ、元あった場所の処理は消してしまいます。 これで、「var_IconEmoteByte」の値が書き換わった際に、後続の処理をゲームサーバーからゲームクライアントに同期してくれるようになります。 アイコンを表示させてから2秒後にアイコンを消す処理を追加するために、下のように「Delay」ノードと「var_IconEmoteByte」のセット用のノードを追加します。非表示にする必要があるので、「var_IconEmoteByte」の値は「2」にします。 実行すると下の動画のようになります。 左側の画面のプレイヤーのエモートアイコンは右側の画面に同期されているのに対し、右側の画面のエモートは左側に同期されていないことがわかります。 この挙動はリッスンサーバーで検証を行っているためのものです。 リッスンサーバーでは1人のプレイヤーがゲームサーバーとゲームクライアント両方の機能をもち、 その他のプレイヤーがゲームクライアントだけの機能を持ちます。 上の動画では左側がゲームサーバーを持っているクライアントで、右側がゲームクライアントだけの画面になります。 UEの レプリケーション 機能では、 ゲームサーバーが情報をレプリケート(複製)してゲームクライアントの情報を書き換え、同期することは出来ますが、 ゲームクライアントがゲームサーバーの情報を書き換えて同期することは出来ません。 また、クライアントがクライアントの情報を書き換えて同期することも出来ません。 まとめると下記のようになります。 ゲームサーバーでの情報変更 → ゲームサーバーの情報を複製して、ゲームクライアントの情報を書き換えることが可能 ゲームクライアントでの情報変更 → ゲームクライアントの情報を複製して、ゲームサーバーの情報を書き換えることは不可能 ゲームクライアントでの情報変更 → ゲームクライアントの情報を複製して、他のゲームクライアントの情報を書き換えることは不可能 上記の理由から、左側の行動はレプリケートされ、右側の行動はレプリケートされない処理になってしまっているので修正していきます。 まずはカスタムイベントを追加します。今回は「Press5sync」という名前のイベントにしました。 「Press5sync」を選択し、右側の詳細画面から複製欄で「サーバーで実行」を選択します。 次にキーボードの「5」を押して起動する処理を、今作った「Press5sync」に繋ぎ直し、キーボードの「5」の処理は「Press5sync」を起動させるためにつなぎます。 これにより、ゲームクライアント側で行われた処理も、ゲームサーバーで実行する形式をとるのでゲームサーバーとゲームクライアント間で同期が取れるようになります。 同様の手順で、TextタイプのWidgetBlueprintを追加することで、下記のようなエモートを追加することもできます。 以上が、 マルチプレイ に対応したエモート機能を作成する手順になります。 所感 今回のUE5で マルチプレイ に対応したエモート機能を作成する手順を調査するにあたり、 UE5でのWidgetBlueprintの使用方法や、 マルチプレイ のゲームサーバー、ゲームクライアント間の関係性などに詳しくなることが出来ました。 マルチプレイ のプロジェクトを作成するにあたり、プレイヤー間の情報の同期( レプリケーション )は必須事項になるので、今回の基礎的な知識をもとに、より複雑な レプリケーション の方法なども学習していきます。 現在ISIDは web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間を、是非お待ちしております! ISID採用ページ(Web3/メタバース/AI) 参考 https://docs.unrealengine.com/4.26/ja/InteractiveExperiences/Networking/HowTo/DedicatedServers/ https://docs.unrealengine.com/4.27/ja/Resources/ContentExamples/Networking/1_4/ https://qiita.com/Shibash/items/2408b653abe0549abe37 執筆: @okazaki.wataru 、レビュー: @wakamoto.ryosuke ( Shodo で執筆されました )
アバター
こんにちは、ISID 金融ソリューション事業部の岡崎です。 今回はUE5で マルチプレイ に対応したエモート機能を作成する方法をご紹介します。 エモート機能とは、 マルチプレイ のゲームにおいて、各キャ ラク ターが感情を表現する為の機能です。 例えば Fortnite ではキャ ラク ターに様々な動きやダンスをさせることができます。 はじめに UE5では「ListenServer」と「DedicatedServer」の2種類のゲームサーバー方式が使用可能です。 各サーバーについては、こちらの 金融ソリューション事業部の山下さんの記事 で紹介されているので説明は割愛します。 今回は検証を簡易にするため「ListenServer」を使用して マルチプレイ でのエモート機能を作成しますが、 「DedicatedServer」でも同じ挙動をする実装方法となります。 検証環境/ツール Unreal Engine5.2.0 AWS EC2 Windows _Server-2022-English-Full-Base-2023.01.19 実装手順 エモート用WidgetBlueprintの作成 エモート用 Widget をCharacterBlueprintに付与 CharacterBlueprintの動作作成 マルチプレイ 用 レプリケーション 設定 1. エモート用WidgetBlueprintの作成 今回はThirdPersonテンプレートを利用したプロジェクトで進めていきます。 まず初めにエモート用 Widget に使用するWidgetBluePrintを作成します。 コンテンツドロワーより、WidgetBlueprintを選び「WBP_IconEmote」で作成します。 以前紹介した UE5 PixelStreamingで、マウスカーソルを別の画像に変更してクリックイベントを作成する記事 にて、 WidgetBlueprint内に任意の画像を取り込む方法があるので、同様にエモートに使用したい画像を取り込み「IconEmote」という名前をつけました。また前回同様「 Canvas Panel」を作成し、位置を中心に変更させます。 今回は別のBlueprintでもこの Widget を呼び出して使う予定なので、詳細タブの上部にある「Is Variable」にチェックを入れておきます。 2. エモート用 Widget をCharacterBlueprintに付与 まずはCharacterBlueprintを開きます。 ThirdPersonTemplateを使用して作成したプロジェクトの場合、 All>Content>ThirdPerson>Blueprints内に「BP_ThirdPersonCharacter」を見つけることができます。 「BP_ThirdPersonCharacter」のViewPortを開き、 Widget 用の コンポーネント を追加します。 ViewProt左上部の追加ボタンを押して Widget と検索し、クリックで選択します。 左側の コンポーネント 一覧に追加されるので、名前を「 Widget _IconEmote」と変更します。 次に追加した「 Widget _IconEmote」と、先ほど作成した「WBP_IconEmote」を連携させます。 右側の ユーザーインターフェース 内の「 Widget Class」のセレクトボックスで「WBP_IconEmote」を選択します。 連携すると下記画像のように追加したエモート画像がCharacterBlueprintに付与されます。 トランスフォーム欄から位置や大きさを動かすことで、エモート機能のようになってきました。 コンパイル 、保存を行い、レベルのViewPortで確認してみます。 キャ ラク ターの頭上にアイコンを出すことは出来ましたが、キャ ラク ターが横を向くとアイコンも横を向いてしまい画面から見えなくなってしまいました。 解決法として、ViewPortの ユーザーインターフェース 欄のSpaceのセレクトボックスを「World」から「画面」を選ぶことで、キャ ラク ターがどの向きを向いてもエモートアイコンが見えるように設定できます。 3. CharacterBlueprintの動作作成 今回は、キーボードの「5」を押した時に、2秒間エモートアイコンがキャ ラク ターの頭上に表示されるBlueprintを作成します。 今のままでは、アイコンが出続けてしまうのでまずゲームスタートとともにアイコンを隠す処理を行います。 まずは「BP_ThirdPersonCharacter」から「WBP_IconEmote」に接続できるように「Event BeginPlay」から「Cast To WBP_IconEmote」をピンでつなげます。 さらにObject属性に対して、「Get User Widget Object」ノードを追加し、ターゲットを「 Widget Icon Emote」にします。 これにより、「BP_ThirdPersonCharacter」から「WBP_IconEmote」に接続できるようになりました。 次に、アイコンを非表示にするために「Set Visibility」ノードを接続し、ターゲットを「Cast To WBP_IconEmote」の「As WBP Emote」に接続します。「In Visibility」の値を「非表示」にすることで、アイコンを非表示にできますが、今回は後述の マルチプレイ 用に、表示・非表示を司る変数を作成しておきます。 画面左下の変数欄からプラスを押し、「var_IconEmoteByte」という変数を作成します。タイプはByteを選択し、デフォルト値を「2」にします。 作成した「var_IconEmoteByte」を「Set Visibility」につなぎます。 ここで入力した「2」というのは、「In Visibility」の値の配列番号になり、「非表示」を意味しています。 ここまでで、キャ ラク ター頭上のアイコンは一旦非表示になっているはずです。 次にキーボードの「5」を押した時にアイコンを表示させる処理の説明を行います。 「Press 5」ノードを追加し、「Pressed」のピンに対して、「var_IconEmoteByte」をセットするためのノードを追加します。 変数の値を「0」(「In Visibility」の値の配列番号になり、「表示」の意)に書き換える処理の後に、先ほど作成した「Cast To WBP_IconEmote」の流れを複製します。 これにより、キーボードの「5」を押した時にアイコンを表示させることができます。 しかし、この状態ではまだ左右の画面( マルチプレイヤー 間)での同期は取れていないので、 次のステップで修正していきます。 4. マルチプレイ 用 レプリケーション 設定 UEで マルチプレイ を行う際は、ゲームサーバーがゲームクライアントに対して、情報をレプリケート(複製)することで、 各クライアント間(プレイヤー間)での差異が生じないようになります。 今回作った処理は、まだクライアントで行われているだけの処理なので、クライアント間では同期されません。 まずは先ほど作成した変数「var_IconEmoteByte」を レプリケーション する設定にします。 「var_IconEmoteByte」の詳細画面から レプリケーション の設定を「RepNotify」に設定します。 「RepNotify」とは、変数の値をウォッチしており、変数の値が変わった時に後続の関数「OnRep〜」関数を起動させます。 変数を「RepNotify」設定にすると、左側の関数欄に「OnRep_var_IconEmoteByte」という関数ができます。 次に、「Cast To WBP_IconEmote」から「Set Visibility」の処理をコピーし、「OnRep_var_IconEmoteByte」内で貼り付けます。 「OnRep_var_IconEmoteByte」内への移動方法は、左側の関数欄の「OnRep_var_IconEmoteByte」をダブルクリックすることで移動ができます。 貼り付けた処理を「On Rep Var Icon Emote Byte」ノードに繋ぎ、元あった場所の処理は消してしまいます。 これで、「var_IconEmoteByte」の値が書き換わった際に、後続の処理をゲームサーバーからゲームクライアントに同期してくれるようになります。 アイコンを表示させてから2秒後にアイコンを消す処理を追加するために、下のように「Delay」ノードと「var_IconEmoteByte」のセット用のノードを追加します。非表示にする必要があるので、「var_IconEmoteByte」の値は「2」にします。 実行すると下の動画のようになります。 左側の画面のプレイヤーのエモートアイコンは右側の画面に同期されているのに対し、右側の画面のエモートは左側に同期されていないことがわかります。 この挙動はリッスンサーバーで検証を行っているためのものです。 リッスンサーバーでは1人のプレイヤーがゲームサーバーとゲームクライアント両方の機能をもち、 その他のプレイヤーがゲームクライアントだけの機能を持ちます。 上の動画では左側がゲームサーバーを持っているクライアントで、右側がゲームクライアントだけの画面になります。 UEの レプリケーション 機能では、 ゲームサーバーが情報をレプリケート(複製)してゲームクライアントの情報を書き換え、同期することは出来ますが、 ゲームクライアントがゲームサーバーの情報を書き換えて同期することは出来ません。 また、クライアントがクライアントの情報を書き換えて同期することも出来ません。 まとめると下記のようになります。 ゲームサーバーでの情報変更 → ゲームサーバーの情報を複製して、ゲームクライアントの情報を書き換えることが可能 ゲームクライアントでの情報変更 → ゲームクライアントの情報を複製して、ゲームサーバーの情報を書き換えることは不可能 ゲームクライアントでの情報変更 → ゲームクライアントの情報を複製して、他のゲームクライアントの情報を書き換えることは不可能 上記の理由から、左側の行動はレプリケートされ、右側の行動はレプリケートされない処理になってしまっているので修正していきます。 まずはカスタムイベントを追加します。今回は「Press5sync」という名前のイベントにしました。 「Press5sync」を選択し、右側の詳細画面から複製欄で「サーバーで実行」を選択します。 次にキーボードの「5」を押して起動する処理を、今作った「Press5sync」に繋ぎ直し、キーボードの「5」の処理は「Press5sync」を起動させるためにつなぎます。 これにより、ゲームクライアント側で行われた処理も、ゲームサーバーで実行する形式をとるのでゲームサーバーとゲームクライアント間で同期が取れるようになります。 同様の手順で、TextタイプのWidgetBlueprintを追加することで、下記のようなエモートを追加することもできます。 以上が、 マルチプレイ に対応したエモート機能を作成する手順になります。 所感 今回のUE5で マルチプレイ に対応したエモート機能を作成する手順を調査するにあたり、 UE5でのWidgetBlueprintの使用方法や、 マルチプレイ のゲームサーバー、ゲームクライアント間の関係性などに詳しくなることが出来ました。 マルチプレイ のプロジェクトを作成するにあたり、プレイヤー間の情報の同期( レプリケーション )は必須事項になるので、今回の基礎的な知識をもとに、より複雑な レプリケーション の方法なども学習していきます。 現在ISIDは web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間を、是非お待ちしております! ISID採用ページ(Web3/メタバース/AI) 参考 https://docs.unrealengine.com/4.26/ja/InteractiveExperiences/Networking/HowTo/DedicatedServers/ https://docs.unrealengine.com/4.27/ja/Resources/ContentExamples/Networking/1_4/ https://qiita.com/Shibash/items/2408b653abe0549abe37 執筆: @okazaki.wataru 、レビュー: @wakamoto.ryosuke ( Shodo で執筆されました )
アバター
皆さんこんにちは!ISID新卒入社7年目の池内です。現在はEIT事業部( エンタープライズ IT事業部)に所属しており、ISIDの自社開発製品である「BusinessSPECTRE」(ビジネ ススペ クトル)、「VisAP」(ヴィスエーピー)の提案、導入を担当しています。 このブログを通じ、私の仕事内容や1日の流れ、またISIDに少しでも興味を持ってもらえる就活生にとって役立つ情報を発信できればと思っています! 1. 自己紹介 それでは早速、簡単に自己紹介させてください。 大学、大学院を卒業し、2017年に新入社員としてISIDへ入社しました。大学在学中は、特に情報系(プログラムとか)の授業をなるべく避けてきましたので、IT リテラシー はほぼ0。大学、大学院では 統計学 を専攻していました。 当時、製薬会社のデータサイエンティストを志望し、就活に励んでいましたが、残念ながらどの会社からも最終面接へのチケットをもらえず。やっぱり薬学部に進学しないとだめなのかな~とか、自分って将来どこで何して働くんだろう~とか、色々考えながら日々を過ごしていたところ、ISIDに出会うことができ入社することを決めました。 入社後の配属先としては、主に顧客の基幹システム(会計、販売、在庫など、顧客の心臓となるシステム)周りのお仕事をしている部署に配属されることになりました。 年度ごとに組織変更があり、部署名が変わってばかりですが、仕事内容は変わらず基幹システムの周辺領域(BIやDWHとも呼ばれる)のソリューションを提案したり導入したりしています。 ※ISIDの自社開発製品「BusinessSPECTRE」(ビジネ ススペ クトル)、「VisAP」(ヴィスエーピー)については、こちらのサイト( https://erp.isid.co.jp/solution/sap-bi-businessspectre/ )に掲載されていますので興味のある方は是非! 2. 就活生の皆さんが気になるであろう質問に淡々と答えます Q1. どんなお仕事? A1. ISIDの自社開発製品「BusinessSPECTRE」、「VisAP」の提案や導入活動をしています。ドイツ製の基幹システム「SAP」を導入しているお客様をターゲットに、日々の業務データを蓄積→分析→可視化するようなシステムを提案しています。 Q2. どんな職場環境? A2. 上司や先輩とは、よくコミュニケーションを取ります。最近ではテレワークのため、社内打合せやチャットでのやり取りが主流ですが、仕事のことはもちろんプライベートなことでも気兼ねなく話できるメンバーばかりの環境だなと感じています。同期ともたまに連絡を取り合います。同期は宝物です。 Q3. 教育制度は? A3. 入社後は新人教育のカリキュラムが組まれているため、それに則って教育を受けることができます。ITに関する研修や、社会人としてのマナー研修など内容は様々で、どれもISIDで働いていく上で必要な知識です。配属後は社内研修制度を通じて専門分野について知識習得する機会があります。半年に一度申し込むことができ、実務をこなしながら自身の スキルアップ を図ることもできるので、有効活用しています! Q4. 働いていてやりがいを感じるときは? A4. 一番はお客様から感謝されるときや案件が無事完了したときですが、年次が上がると責任感も増しますし、上司や先輩からの期待も大きくなります。そういった期待に応えられたときや、励ましの言葉をもらったときにやりがいを感じることが多いです。 Q5. 入社前にすべきことはありますか? A5. 働く上で必要なことは入社してから学べるので、特にやっておくべきことはないです。逆に働いてから長期休暇を取りづらくなる(休暇は取れるけど色々調整するのが面倒)ので、海外旅行に行くとか、日ごろすぐにはできないことにチャレンジすることをオススメします! Q6. テレワークでの難しさは? A6. 出社時に比べて社内メンバーやお客様との雑談が極端に減ったように感じます。対面時は気にすることなくできていた雑談も、Web会議越しでは表情が見えないことで雑談しづらい気持ちになるのが正直なところです。お客様とのコミュニケーションでは雑談って結構大事なので、そのあたりのバランスが難しいですね。 Q7. ISIDに入って良かったことは?悪かったことは? A7. 良かったことは、何よりISIDの「人柄」です。本当にみんなユーモアがあって、やさしさがあって、それでいて頭が切れて面白くて!!仕事だけではなく、プライベートでも一緒に過ごしたいと思えるメンバーばかりです。悪かったことは1つもありません(本当ですよ?笑) Q8. ISIDに入社する人の共通点は? A8. あくまで個人的な意見ですが、、、 自分を持っていて、自分らしさを相手に伝えることができる 色んなことに興味を持っている すぐにチャレンジしたがる Q9. どんな後輩が欲しいですか? A9. 何事にもチャレンジしてくれる、手を挙げてくれる後輩は大歓迎です。何事もやってみないとわからない、と思うので、常に前向きにトライしてくれる後輩が入ってきてくれることを願っています! Q10 . 1日の流れは? Q10 . こんな感じです。 3. 最後に ISIDで一緒に働きましょう!私の所属する部は、新卒入社と中途入社の社員が半々くらいです。 男女比は男:女=8:2くらいでしょうか。 本記事でご紹介した内容や働きについて、また基幹システム周辺分野のシステム導入業務にご興味をお持ちの方は、ぜひ採用ページよりご応募ください! 私たちは一緒に働いてくれる仲間を募集しています! ISID 募集職種一覧 執筆: @ikeuchi.keisuke 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました )
アバター
皆さんこんにちは!ISID新卒入社7年目の池内です。現在はEIT事業部( エンタープライズ IT事業部)に所属しており、ISIDの自社開発製品である「BusinessSPECTRE」(ビジネ ススペ クトル)、「VisAP」(ヴィスエーピー)の提案、導入を担当しています。 このブログを通じ、私の仕事内容や1日の流れ、またISIDに少しでも興味を持ってもらえる就活生にとって役立つ情報を発信できればと思っています! 1. 自己紹介 それでは早速、簡単に自己紹介させてください。 大学、大学院を卒業し、2017年に新入社員としてISIDへ入社しました。大学在学中は、特に情報系(プログラムとか)の授業をなるべく避けてきましたので、IT リテラシー はほぼ0。大学、大学院では 統計学 を専攻していました。 当時、製薬会社のデータサイエンティストを志望し、就活に励んでいましたが、残念ながらどの会社からも最終面接へのチケットをもらえず。やっぱり薬学部に進学しないとだめなのかな~とか、自分って将来どこで何して働くんだろう~とか、色々考えながら日々を過ごしていたところ、ISIDに出会うことができ入社することを決めました。 入社後の配属先としては、主に顧客の基幹システム(会計、販売、在庫など、顧客の心臓となるシステム)周りのお仕事をしている部署に配属されることになりました。 年度ごとに組織変更があり、部署名が変わってばかりですが、仕事内容は変わらず基幹システムの周辺領域(BIやDWHとも呼ばれる)のソリューションを提案したり導入したりしています。 ※ISIDの自社開発製品「BusinessSPECTRE」(ビジネ ススペ クトル)、「VisAP」(ヴィスエーピー)については、こちらのサイト( https://erp.isid.co.jp/solution/sap-bi-businessspectre/ )に掲載されていますので興味のある方は是非! 2. 就活生の皆さんが気になるであろう質問に淡々と答えます Q1. どんなお仕事? A1. ISIDの自社開発製品「BusinessSPECTRE」、「VisAP」の提案や導入活動をしています。ドイツ製の基幹システム「SAP」を導入しているお客様をターゲットに、日々の業務データを蓄積→分析→可視化するようなシステムを提案しています。 Q2. どんな職場環境? A2. 上司や先輩とは、よくコミュニケーションを取ります。最近ではテレワークのため、社内打合せやチャットでのやり取りが主流ですが、仕事のことはもちろんプライベートなことでも気兼ねなく話できるメンバーばかりの環境だなと感じています。同期ともたまに連絡を取り合います。同期は宝物です。 Q3. 教育制度は? A3. 入社後は新人教育のカリキュラムが組まれているため、それに則って教育を受けることができます。ITに関する研修や、社会人としてのマナー研修など内容は様々で、どれもISIDで働いていく上で必要な知識です。配属後は社内研修制度を通じて専門分野について知識習得する機会があります。半年に一度申し込むことができ、実務をこなしながら自身の スキルアップ を図ることもできるので、有効活用しています! Q4. 働いていてやりがいを感じるときは? A4. 一番はお客様から感謝されるときや案件が無事完了したときですが、年次が上がると責任感も増しますし、上司や先輩からの期待も大きくなります。そういった期待に応えられたときや、励ましの言葉をもらったときにやりがいを感じることが多いです。 Q5. 入社前にすべきことはありますか? A5. 働く上で必要なことは入社してから学べるので、特にやっておくべきことはないです。逆に働いてから長期休暇を取りづらくなる(休暇は取れるけど色々調整するのが面倒)ので、海外旅行に行くとか、日ごろすぐにはできないことにチャレンジすることをオススメします! Q6. テレワークでの難しさは? A6. 出社時に比べて社内メンバーやお客様との雑談が極端に減ったように感じます。対面時は気にすることなくできていた雑談も、Web会議越しでは表情が見えないことで雑談しづらい気持ちになるのが正直なところです。お客様とのコミュニケーションでは雑談って結構大事なので、そのあたりのバランスが難しいですね。 Q7. ISIDに入って良かったことは?悪かったことは? A7. 良かったことは、何よりISIDの「人柄」です。本当にみんなユーモアがあって、やさしさがあって、それでいて頭が切れて面白くて!!仕事だけではなく、プライベートでも一緒に過ごしたいと思えるメンバーばかりです。悪かったことは1つもありません(本当ですよ?笑) Q8. ISIDに入社する人の共通点は? A8. あくまで個人的な意見ですが、、、 自分を持っていて、自分らしさを相手に伝えることができる 色んなことに興味を持っている すぐにチャレンジしたがる Q9. どんな後輩が欲しいですか? A9. 何事にもチャレンジしてくれる、手を挙げてくれる後輩は大歓迎です。何事もやってみないとわからない、と思うので、常に前向きにトライしてくれる後輩が入ってきてくれることを願っています! Q10 . 1日の流れは? Q10 . こんな感じです。 3. 最後に ISIDで一緒に働きましょう!私の所属する部は、新卒入社と中途入社の社員が半々くらいです。 男女比は男:女=8:2くらいでしょうか。 本記事でご紹介した内容や働きについて、また基幹システム周辺分野のシステム導入業務にご興味をお持ちの方は、ぜひ採用ページよりご応募ください! 私たちは一緒に働いてくれる仲間を募集しています! ISID 募集職種一覧 執筆: @ikeuchi.keisuke 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました )
アバター
こんにちは。X(クロス) イノベーション 本部 ソフトウェアデザインセンター セキュリティグループの耿です。 AWS Security Hubの コントロール には、「変更によってトリガーされるチェック」と「定期的なチェック」があります。 それぞれのチェックスケジュールについては こちら に記載があり、「定期的なチェック」は次のように書かれています。 定期的なチェックは、最後の実行から 12 時間または 24 時間以内に自動的に実行されます。周期は Security Hub によって決定され、変更はできません。定期的なコン トロール は、実行時の評価をキャプチャします。 すなわち、リソース作成・変更後にすぐにチェックが行われない場合があり、最大で24時間待たなければなりません。コン トロール の動きを調査をするときなどに不便だと感じていましたが、「定期的なチェック」に対してもすぐに実行する方法を見つけたのでご紹介します。 定期的なチェックをすぐに実行する方法 1. コントロールに対応する Config ルールを特定する 2. AWS Config コンソールでルールを見つける 3. 「アクション」>「再評価」を実行する コマンドラインでチェックをすぐに実行する方法 定期的なチェックをすぐに実行する方法 1. コン トロール に対応する Config ルールを特定する Security Hubのセキュリティチェックは AWS Config ルールを利用しており、ドキュメントにはそれぞれのコン トロール が利用している Config ルールが記載されています。 まずは AWS の公式ドキュメントから、すぐにチェックを実行したいコン トロール の Config ルールを特定しましょう。 https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-controls-reference.html 2. AWS Config コンソールでルールを見つける AWS Configのコンソールにて、該当するルールを見つけます。ルールによっては名前が少し異なる場合があるようです。 3. 「アクション」>「再評価」を実行する ルール右上の「アクション」>「再評価」をクリックすると、すぐにチェックを再実行してくれます。 しばらくしてリロードすると、最後に評価した日時とルールに非準拠なリソースが更新されました。 Security Hubのコンソールでも、すぐにチェックの結果が反映されていました。 コマンドライン でチェックをすぐに実行する方法 ルール名を特定した後の「再評価」操作は、 コマンドライン の start-config-rules-evaluation コマンド で実行することもできます。 aws configservice start-config-rules-evaluation --config-rule-name <ルール名> 私たちは同じチームで働いてくれる仲間を大募集しています!たくさんのご応募をお待ちしています。 セキュリティエンジニア(セキュリティ設計) 執筆: @kou.kinyo 、レビュー: @yamada.y ( Shodo で執筆されました )
アバター
こんにちは。X(クロス) イノベーション 本部 ソフトウェアデザインセンター セキュリティグループの耿です。 AWS Security Hubの コントロール には、「変更によってトリガーされるチェック」と「定期的なチェック」があります。 それぞれのチェックスケジュールについては こちら に記載があり、「定期的なチェック」は次のように書かれています。 定期的なチェックは、最後の実行から 12 時間または 24 時間以内に自動的に実行されます。周期は Security Hub によって決定され、変更はできません。定期的なコン トロール は、実行時の評価をキャプチャします。 すなわち、リソース作成・変更後にすぐにチェックが行われない場合があり、最大で24時間待たなければなりません。コン トロール の動きを調査をするときなどに不便だと感じていましたが、「定期的なチェック」に対してもすぐに実行する方法を見つけたのでご紹介します。 定期的なチェックをすぐに実行する方法 1. コントロールに対応する Config ルールを特定する 2. AWS Config コンソールでルールを見つける 3. 「アクション」>「再評価」を実行する コマンドラインでチェックをすぐに実行する方法 定期的なチェックをすぐに実行する方法 1. コン トロール に対応する Config ルールを特定する Security Hubのセキュリティチェックは AWS Config ルールを利用しており、ドキュメントにはそれぞれのコン トロール が利用している Config ルールが記載されています。 まずは AWS の公式ドキュメントから、すぐにチェックを実行したいコン トロール の Config ルールを特定しましょう。 https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-controls-reference.html 2. AWS Config コンソールでルールを見つける AWS Configのコンソールにて、該当するルールを見つけます。ルールによっては名前が少し異なる場合があるようです。 3. 「アクション」>「再評価」を実行する ルール右上の「アクション」>「再評価」をクリックすると、すぐにチェックを再実行してくれます。 しばらくしてリロードすると、最後に評価した日時とルールに非準拠なリソースが更新されました。 Security Hubのコンソールでも、すぐにチェックの結果が反映されていました。 コマンドライン でチェックをすぐに実行する方法 ルール名を特定した後の「再評価」操作は、 コマンドライン の start-config-rules-evaluation コマンド で実行することもできます。 aws configservice start-config-rules-evaluation --config-rule-name <ルール名> 私たちは同じチームで働いてくれる仲間を大募集しています!たくさんのご応募をお待ちしています。 セキュリティエンジニア(セキュリティ設計) 執筆: @kou.kinyo 、レビュー: @yamada.y ( Shodo で執筆されました )
アバター
こんにちは。X(クロス) イノベーション 本部 ソフトウェアデザインセンター セキュリティグループの耿です。 IAM の Permissions Boundary(アクセス許可境界) についてもやもやしていました。効果はわかるものの、どうして IAM ポリシーだけではダメで Permissions Boundary が必要なのかよくわかりませんでした。この記事では IAM のポリシードキュメントと API の仕様から、 Permissions Boundary が導入された本質的な理由を考えてみます。 結論から先に述べると、Permissions Boundary を使うことで特定の権限を超えて IAM ユーザー/ロールが作成されるのを防ぐ効果があり、これは IAM ポリシーだけでは実現できません。Permissions Boundary は、特定のユーザーが IAM ユーザー/ロールを作成するのを許可しつつ、権限昇格を防止する目的などに使用できます。 権限昇格の例 Permissions Boundary とは 権限昇格を防ぐ例 本質1: IAM ポリシードキュメントに iam:PermissionsBoundary 条件キーが使える 本質2: Permissions Boundary は CreateUser / CreateRole 時に追加できる さいごに 権限昇格の例 まずは IAM の権限昇格を簡単な例で見てみます。 以下の IAM ポリシーを持つ IAM ユーザーがあるとします。 iam:CreateRole (IAM ロールを作成する権限) と iam:PutRolePolicy (IAM ロールにインラインポリシーを追加する権限)、さらには sts:AssumeRole が許可されています。他の権限については省略します。 { " Version ": " 2012-10-17 ", " Statement ": [ { " Effect ": " Allow ", " Action ": [ " iam:CreateRole ", " iam:PutRolePolicy " ] , " Resource ": " * " } , { " Effect ": " Allow ", " Action ": [ " sts:AssumeRole " ] , " Resource ": " * " } ] } iam:CreateRole が許可されているので、以下の信頼ポリシーを持つ IAM ロールを作ることができます。(同じアカウント内の プリンシパル であれば、 AssumeRole を許可) { " Version ": " 2012-10-17 ", " Statement ": [ { " Effect ": " Allow ", " Principal ": { " AWS ": " arn:aws:iam::000000000000:root " } , " Action ": " sts:AssumeRole " } ] } 先の IAM ユーザーは iam:PutRolePolicy が許可されているので、作ったロールに任意のインラインポリシーを追加できます。例えば以下のような全てを許可するポリシーをエラーなく追加できます。 { " Version ": " 2012-10-17 ", " Statement ": [ { " Effect ": " Allow ", " Action ": " * ", " Resource ": " * " } ] } 先の IAM ユーザーは sts:AssumeRole が許可されているので、作ったロールを AssumeRole し、アクセスキーID、シークレットアクセスキー、セッション トーク ンを獲得することで、全ての操作が許可される権限を手に入れることができます。元のユーザーにはできなかった操作ができるようになるので、権限昇格されています。 (以上の例は「IAM ユーザー」が「IAM ロールを経由して」権限昇格する例でしたが、権限昇格する主体が「IAM ロール」の場合や、「IAM ユーザーを経由して」権限昇格する場合もあります。) Permissions Boundary とは Permissions Boundary の実態は IAM 管理ポリシーです。他の IAM 管理ポリシーと同じように作成します。 一つの IAM ユーザー/ロールには最大で1つの IAM 管理ポリシーを、 Permissions Boundary として追加できます。また、Permissions Boundary にインラインポリシーを指定することはできません。 IAM ユーザー/ロールに Permissions Boundary が追加されている場合、そのユーザー/ロールに許可される権限は「 アイデンティティ ベースのポリシー」と「Permissions Boundary」の AND 条件になります。Permissions Boundary で明示的に許可されていない権限は、 アイデンティティ ベースのポリシーで許可されていても最終的にユーザー/ロールには許可されません。 ( https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies_boundaries.html より) 権限昇格を防ぐ例 Permissions Boundary を使うことで、どのように権限昇格を防ぐことができるのか見てみます。 以下の IAM 管理ポリシーを my-permissions-boundary という名前で作成します。 iam:CreateRole iam:PutRolePolicy sts:AssumeRole の3つの権限しか許可していません。 { " Version ": " 2012-10-17 ", " Statement ": [ { " Effect ": " Allow ", " Action ": [ " iam:CreateRole ", " iam:PutRolePolicy ", " sts:AssumeRole " ] , " Resource ": " * " } ] } 対象の IAM ユーザーに作成した my-permissions-boundary を Permissions Boundary として追加します。 対象の IAM ユーザーのポリシーを以下のように変更します。 Condition 句を追加し、Permissions Boundary として my-permissions-boudary が指定された場合のみ iam:CreateRole iam:PutRolePolicy できるようにしています。(この例では自身のポリシーを変更する権限を持っていないこともポイントです。) { " Version ": " 2012-10-17 ", " Statement ": [ { " Effect ": " Allow ", " Action ": [ " iam:CreateRole ", " iam:PutRolePolicy " ] , " Resource ": " * ", " Condition ": { " StringEquals ": { " iam:PermissionsBoundary ": " arn:aws:iam::000000000000:policy/my-permissions-boudary " } } } , { " Effect ": " Allow ", " Action ": [ " sts:AssumeRole " ] , " Resource ": " * " } ] } 以上が準備段階で、この状態で IAM ロールを経由して権限昇格を試みても次のような結果になります。 my-permissions-boudary を付与しないと、IAM ロールを作ることに失敗します。 my-permissions-boudary を付与すれば、IAM ロールを作成できます。 Admin 権限相当のインラインポリシーを作成した IAM ロールにつけ、AssumeRole をすることはできますが、Permissions Boundary で明示的に許可された以上の権限を持ちません。 以上はよくある Permissions Boundary の説明でした。このように権限昇格の防止を実現できるのは、2つの仕様上の本質があるためだと考えています。 本質1: IAM ポリシードキュメントに iam:PermissionsBoundary 条件キーが使える 権限昇格を防ぎたい IAM ユーザー/ロールのポリシーに iam:PermissionsBoundary 条件キーが使える のが第一のポイントです。これによって、Permissions Boundary に特定のポリシーが存在する場合に限って特定の操作を許す、といった書き方ができるようになりました。 " Condition ": { " StringEquals ": { " iam:PermissionsBoundary ": " arn:aws:iam::000000000000:policy/my-permissions-boudary " } } 本質2: Permissions Boundary は CreateUser / CreateRole 時に追加できる こちらはより重要です。 CreateUser と CreateRole の API 仕様を確認すると、これらの API を呼びだす時のパラメータで Permissions Boundary を追加できることがわかります。 一方で、通常のポリシーについては CreateUser と CreateRole の呼び出し時に追加することはできず、後から AttachUserPolicy 、 PutUserPolicy 、 AttachRolePolicy 、 PutRolePolicy など別 API で付与しなければなりません。すなわち、 IAM ユーザー/ロールを作成した瞬間にはポリシーが何もついていない状態にどうしてもなってしまい 、最初から特定の IAM ポリシーを持つように制限できません。Permissions Boundary であれば作成と同時に付与できるので、 iam:PermissionsBoundary 条件キーと併用することで特定の Permissions Boundary を持つ場合に限って ユーザー/ロールの作成を許可する、といった書き方ができます。 推測ですが、作成時からポリシーを付与できるように従来の CreateUser / CreateRole の API 仕様を変更するよりも、新しく Permissions Boundary という機能を追加した方が望ましいと判断したのではないかと思います。 さいごに 理解していても IAM の権限は複雑で、Permissions Boundary を使いこなすのは慎重な設定が必要な印象です。 公式ドキュメントの例 にも目を通すと、さらに理解の助けになるのではないかと思います。 お読みいただいてありがとうございました。 私たちは同じチームで働いてくれる仲間を大募集しています!たくさんのご応募をお待ちしています。 セキュリティエンジニア(セキュリティ設計) 執筆: @kou.kinyo 、レビュー: @nakamura.toshihiro ( Shodo で執筆されました )
アバター
こんにちは。X(クロス) イノベーション 本部 ソフトウェアデザインセンター セキュリティグループの耿です。 IAM の Permissions Boundary(アクセス許可境界) についてやもやしていました。効果はわかるものの、どうして IAM ポリシーだけではダメで Permissions Boundary が必要なのかよくわかりませんでした。この記事では IAM のポリシードキュメントと API の仕様から、 Permissions Boundary が導入された本質的な理由を考えてみます。 結論から先に述べると、Permissions Boundary を使うことで特定の権限を超えて IAM ユーザー/ロールが作成されるのを防ぐ効果があり、これは IAM ポリシーだけでは実現できません。Permissions Boundary は、特定のユーザーが IAM ユーザー/ロールを作成するのを許可しつつ、権限昇格を防止する目的などに使用できます。 権限昇格の例 Permissions Boundary とは 権限昇格を防ぐ例 本質1: IAM ポリシードキュメントに iam:PermissionsBoundary 条件キーが使える 本質2: Permissions Boundary は CreateUser / CreateRole 時に追加できる さいごに 権限昇格の例 まずは IAM の権限昇格を簡単な例で見てみます。 以下の IAM ポリシーを持つ IAM ユーザーがあるとします。 iam:CreateRole (IAM ロールを作成する権限) と iam:PutRolePolicy (IAM ロールにインラインポリシーを追加する権限)、さらには sts:AssumeRole が許可されています。他の権限については省略します。 { " Version ": " 2012-10-17 ", " Statement ": [ { " Effect ": " Allow ", " Action ": [ " iam:CreateRole ", " iam:PutRolePolicy " ] , " Resource ": " * " } , { " Effect ": " Allow ", " Action ": [ " sts:AssumeRole " ] , " Resource ": " * " } ] } iam:CreateRole が許可されているので、以下の信頼ポリシーを持つ IAM ロールを作ることができます。(同じアカウント内の プリンシパル であれば、 AssumeRole を許可) { " Version ": " 2012-10-17 ", " Statement ": [ { " Effect ": " Allow ", " Principal ": { " AWS ": " arn:aws:iam::000000000000:root " } , " Action ": " sts:AssumeRole " } ] } 先の IAM ユーザーは iam:PutRolePolicy が許可されているので、作ったロールに任意のインラインポリシーを追加できます。例えば以下のような全てを許可するポリシーをエラーなく追加できます。 { " Version ": " 2012-10-17 ", " Statement ": [ { " Effect ": " Allow ", " Action ": " * ", " Resource ": " * " } ] } 先の IAM ユーザーは sts:AssumeRole が許可されているので、作ったロールを AssumeRole し、アクセスキーID、シークレットアクセスキー、セッション トーク ンを獲得することで、全ての操作が許可される権限を手に入れることができます。元のユーザーにはできなかった操作ができるようになるので、権限昇格されています。 (以上の例は「IAM ユーザー」が「IAM ロールを経由して」権限昇格する例でしたが、権限昇格する主体が「IAM ロール」の場合や、「IAM ユーザーを経由して」権限昇格する場合もあります。) Permissions Boundary とは Permissions Boundary の実態は IAM 管理ポリシーです。他の IAM 管理ポリシーと同じように作成します。 一つの IAM ユーザー/ロールには最大で1つの IAM 管理ポリシーを、 Permissions Boundary として追加できます。また、Permissions Boundary にインラインポリシーを指定することはできません。 IAM ユーザー/ロールに Permissions Boundary が追加されている場合、そのユーザー/ロールに許可される権限は「 アイデンティティ ベースのポリシー」と「Permissions Boundary」の AND 条件になります。Permissions Boundary で明示的に許可されていない権限は、 アイデンティティ ベースのポリシーで許可されていても最終的にユーザー/ロールには許可されません。 ( https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies_boundaries.html より) 権限昇格を防ぐ例 Permissions Boundary を使うことで、どのように権限昇格を防ぐことができるのか見てみます。 以下の IAM 管理ポリシーを my-permissions-boundary という名前で作成します。 iam:CreateRole iam:PutRolePolicy sts:AssumeRole の3つの権限しか許可していません。 { " Version ": " 2012-10-17 ", " Statement ": [ { " Effect ": " Allow ", " Action ": [ " iam:CreateRole ", " iam:PutRolePolicy ", " sts:AssumeRole " ] , " Resource ": " * " } ] } 対象の IAM ユーザーに作成した my-permissions-boundary を Permissions Boundary として追加します。 対象の IAM ユーザーのポリシーを以下のように変更します。 Condition 句を追加し、Permissions Boundary として my-permissions-boudary が指定された場合のみ iam:CreateRole iam:PutRolePolicy できるようにしています。(この例では自身のポリシーを変更する権限を持っていないこともポイントです。) { " Version ": " 2012-10-17 ", " Statement ": [ { " Effect ": " Allow ", " Action ": [ " iam:CreateRole ", " iam:PutRolePolicy " ] , " Resource ": " * ", " Condition ": { " StringEquals ": { " iam:PermissionsBoundary ": " arn:aws:iam::000000000000:policy/my-permissions-boudary " } } } , { " Effect ": " Allow ", " Action ": [ " sts:AssumeRole " ] , " Resource ": " * " } ] } 以上が準備段階で、この状態で IAM ロールを経由して権限昇格を試みても次のような結果になります。 my-permissions-boudary を付与しないと、IAM ロールを作ることに失敗します。 my-permissions-boudary を付与すれば、IAM ロールを作成できます。 Admin 権限相当のインラインポリシーを作成した IAM ロールにつけ、AssumeRole をすることはできますが、Permissions Boundary で明示的に許可された以上の権限を持ちません。 以上はよくある Permissions Boundary の説明でした。このように権限昇格の防止を実現できるのは、2つの仕様上の本質があるためだと考えています。 本質1: IAM ポリシードキュメントに iam:PermissionsBoundary 条件キーが使える 権限昇格を防ぎたい IAM ユーザー/ロールのポリシーに iam:PermissionsBoundary 条件キーが使える のが第一のポイントです。これによって、Permissions Boundary に特定のポリシーが存在する場合に限って特定の操作を許す、といった書き方ができるようになりました。 " Condition ": { " StringEquals ": { " iam:PermissionsBoundary ": " arn:aws:iam::000000000000:policy/my-permissions-boudary " } } 本質2: Permissions Boundary は CreateUser / CreateRole 時に追加できる こちらはより重要です。 CreateUser と CreateRole の API 仕様を確認すると、これらの API を呼びだす時のパラメータで Permissions Boundary を追加できることがわかります。 一方で、通常のポリシーについては CreateUser と CreateRole の呼び出し時に追加することはできず、後から AttachUserPolicy 、 PutUserPolicy 、 AttachRolePolicy 、 PutRolePolicy など別 API で付与しなければなりません。すなわち、 IAM ユーザー/ロールを作成した瞬間にはポリシーが何もついていない状態にどうしてもなってしまい 、最初から特定の IAM ポリシーを持つように制限できません。Permissions Boundary であれば作成と同時に付与できるので、 iam:PermissionsBoundary 条件キーと併用することで特定の Permissions Boundary を持つ場合に限って ユーザー/ロールの作成を許可する、といった書き方ができます。 推測ですが、作成時からポリシーを付与できるように従来の CreateUser / CreateRole の API 仕様を変更するよりも、新しく Permissions Boundary という機能を追加した方が望ましいと判断したのではないかと思います。 さいごに 理解していても IAM の権限は複雑で、Permissions Boundary を使いこなすのは慎重な設定が必要な印象です。 公式ドキュメントの例 にも目を通すと、さらに理解の助けになるのではないかと思います。 お読みいただいてありがとうございました。 私たちは同じチームで働いてくれる仲間を大募集しています!たくさんのご応募をお待ちしています。 セキュリティエンジニア(セキュリティ設計) 執筆: @kou.kinyo 、レビュー: @nakamura.toshihiro ( Shodo で執筆されました )
アバター
みなさんこんにちは、X イノベーション 本部ソフトウェアデザインセンターの徳山です。 いきなりなのですが、「ちょっとした」プレゼン資料の作成って意外と難しくないでしょうか。 特にプレゼンの機会がこれまであまりないと「構成や見た目、中身をどの程度のものを作ろうかな」と漠然とした不安に襲われないでしょうか(僕は襲われます)。 現在私のチームでは既存サービスのリプレイス開発に取り組んでおり、社内向けに今の取り組みを発表する機会がありました。 今回はプレゼン資料の見た目や構成をサクッと作れるノウハウを共有したいと思います。 本記事について 対象者 対象ではない人 事前準備 利用までのステップ スライドの作成手順 1. 作ってほしいスライドの内容をChatGPTに入力 2. 出力されたMarkdownのコードを貼り付ける 3. プレビューを表示する 4. スタイルを変更する 4. PowerPointとして出力する まとめ 本記事について 対象者 ちょっとしたプレゼン(社内向けやLTなど)の下書きをできるだけ短時間でいい感じに作成したい方 Markdown での文書を書くことに抵抗がない方 ChatGPTを利用できる環境にある方 対象ではない人 独自性あふれる資料を作りたい 図や文章をスライドにふんだんに盛り込みたい NOTE ChatGPTを業務で利用する際にはセキュリティ等を考慮することが重要です。特に業務情報を取り扱うケースでは、自社の ガイドライン やポリシーに従って適切な対応を行ってください。ISIDでは、AIの活用のために ガイドライン を策定し、安全な業務利用ができるようサポートしています。 事前準備 今回は下記の3つのツールおよびサービスを利用します。 Visual Studio Code ChatGPT Marp 利用までのステップ Visual Studio Code (以後、 VS Code )をダウンロード後、 Marp for VS Code の 拡張機能 をインストールする ChatGPTのアカウントを作成して利用できる状態にする スライドの作成手順 1. 作ってほしいスライドの内容をChatGPTに入力 まずはChatGPTにスライドの下書き内容を出力してもらいましょう。 例えば下記のような内容を指定してみます。 あなたは熟練のエンジニアです。社内向けサービスのリプレイスを実施するプロジェクトに携わっています。 今回、その開発中のプロダクトについてプレゼンテーションを行うことになりました。下記の条件を考慮した下書きを書いていただけますか。 ## 条件 - Marp for VS Codeを使用したMarkdown形式のコードで出力してください - 10分程度の発表時間となるような分量で作成してください - 新サービスの紹介、背景はマストで盛り込み、加えてオーディエンスに技術者が多いため開発の詳細などの技術的な項目も盛り込みたい - fontは「Noto Sans JP, sans-serif」の2つを指定してください 発表タイトルは「新サービス「New Service」について」としてください ここでのポイントとしては下記の2つです。 どのように振る舞ってほしいかを記入する 今回だと「熟練のエンジニア」「優れたプレゼンテーター」などを冒頭の役割として与える できるだけ具体的に盛り込んで欲しい内容を書く Marp for VS Code を利用している旨を書く コピー&ペーストできる Markdown コードを出力してくれるため、ステップ2の操作が楽になります この記事はChatGPTの記事ではないので詳細は割愛しますが、役割と詳細な条件を与えるとより望ましい内容を出力してもらえる傾向があるようです。 ChatGPTに与えるプロンプトについて詳細を知りたい方は下記をぜひ一読してみてください。 Prompt Engineering Guide 上記の指示で出力されたコードは下記の通りです。 --- marp: true theme: default paginate: true size: 16:9 style: | font-family: 'Noto Sans JP', sans-serif; --- # 新サービス「New Service」について --- ## 目次 1. 新サービスの概要 2. 背景 3. 技術的な詳細 4. 開発の進捗 5. 今後の展望 --- ## 1. 新サービスの概要 - 社内向けの新サービス「New Service」 - 既存のサービスをリプレイス - 効率化、利便性の向上を目指す --- ## 2. 背景 ### 2.1 既存サービスの課題 - 時代遅れの技術 - 機能の不足 - スケーラビリティの問題 ### 2.2 リプレイスの目的 - 最新技術の導入 - 新たな機能の追加 - スケーラビリティの向上 --- ## 3. 技術的な詳細 ### 3.1 技術スタック - バックエンド: Node.js, Express - フロントエンド: React, Redux - データベース: PostgreSQL - インフラ: AWS, Docker ### 3.2 開発手法 - アジャイル開発 - CI/CDの導入 - コードレビュー、テスト自動化 --- ## 4. 開発の進捗 ### 4.1 バージョン管理 - Git, GitHubを使用 - 開発ブランチ、リリースブランチで管理 ### 4.2 開発環境 - VSCode, Marp for VS Code - 開発者同士のコミュニケーションはSlack, Teams ### 4.3 現状の進捗 - システム設計完了 - プロトタイプ開発中 - テストケースの作成 --- ## 5. 今後の展望 ### 5.1 プロジェクトの目標 - 新サービスのリリース - 既存サービスからのスムーズな移行 - 社内利用者の満足度向上 ### 5.2 開発チームの成長 - 新技術の習得 - より効率的な開発手法の模索 - 社内コミュニケーションの強化 --- ## まとめ - 社内向け新サービス「New Service」を開発中 - 既存サービスのリプレイスを実施 希望の内容が出力されない場合は、再生成や条件をより具体的に追加するなどの操作を行ってみてください。 2. 出力された Markdown のコードを貼り付ける VS Code で presentation_slide.md など Markdown 用のファイルを作成し、そこに出力された Markdown のコードを貼り付けます。 3. プレビューを表示する アクションペインを呼び出し、 Markdown: Open Preview to the Side を選択します。 すると貼り付けた Markdown のプレビューが表示されます。 Marpで良い感じのスタイルを適用してくれている為、それなりに整ったスライドが表示されているかと思います。 4. スタイルを変更する 現在のスライドでもいい感じですが、さすがにテキストだけのスライドは寂しいので画像も追加してみましょう。 例えば目次のスライドの右に画像を追加してみます。 --- ## 目次 1. 新サービスの概要 2. 背景 3. 技術的な詳細 4. 開発の進捗 5. 今後の展望 ![bg right](https://picsum.photos/866?image=3) --- 画像リンクと一緒に bg right と追加するだけで簡単に画像を追加できました。 また、特定のスライドにだけスタイルを適用することも簡単にできます。 例えば背景色を黒、文字色を白色に変更する場合は下記のように コメントアウト を追加します。 <!-- _backgroundColor: black _color: white --> ## 目次 1. 新サービスの概要 2. 背景 3. 技術的な詳細 4. 開発の進捗 5. 今後の展望 ![bg right](https://picsum.photos/866?image=3) 個別ページだけでなくページ全体に一括でスタイルを当てたり、フッターやヘッダーに共通したサブタイトルを表示させることもできますので気になる方は CSSについてのページ をご覧ください。 4. PowerPoint として出力する 最後に、ここまで作成したコードを PowerPoint として出力してみます。 VS Code の画面に表示される下記赤い枠のアイコンをクリックします。 その後、 Export Slide Deck... を選択 すると、出力形式を選択できるモーダルが立ち上がるので、 PowerPoint document を選択します。 最後に、 Export ボタンをクリックするとPowerpPointの画像が出力されます。 出力形式の選択時にも表示されていましたが、 PowerPoint の他、PDFやHTMLとしても出力ができます。 PowerPoint として出力する場合はスライドが全て画像となります。そのため、テキスト等の修正を行う場合は再度 VS Code より修正した上で再出力を行ってください。 Note Marpで選択したthemeやfontによっては、英数字と日本語の文字の太さが違うように出力される場合があります。その場合はスライド全体に当てるfont-familyを変更するなどの方法で対応してみてください。 まとめ 今回紹介したMarpとChatGPTを利用することで内容の吟味に集中できるので、スタイルの調整や構成を考えることに苦手意識のある方はぜひ利用していただきたいです。 また2023年3月には Office製品にAIを導入する という発表もあり、今後より自動化が進んでいきそうです。 私たちは同じチームで働いてくれる仲間を探しています。 フロントエンドやバックエンドと特定の領域にとらわれず幅広い技術領域に挑戦してみたい方がいらっしゃいましたら、ぜひご応募ください! ソリューションアーキテクト 執筆: @tokuyama 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました )
アバター
みなさんこんにちは、X イノベーション 本部ソフトウェアデザインセンターの徳山です。 いきなりなのですが、「ちょっとした」プレゼン資料の作成って意外と難しくないでしょうか。 特にプレゼンの機会がこれまであまりないと「構成や見た目、中身をどの程度のものを作ろうかな」と漠然とした不安に襲われないでしょうか(僕は襲われます)。 現在私のチームでは既存サービスのリプレイス開発に取り組んでおり、社内向けに今の取り組みを発表する機会がありました。 今回はプレゼン資料の見た目や構成をサクッと作れるノウハウを共有したいと思います。 本記事について 対象者 対象ではない人 事前準備 利用までのステップ スライドの作成手順 1. 作ってほしいスライドの内容をChatGPTに入力 2. 出力されたMarkdownのコードを貼り付ける 3. プレビューを表示する 4. スタイルを変更する 4. PowerPointとして出力する まとめ 本記事について 対象者 ちょっとしたプレゼン(社内向けやLTなど)の下書きをできるだけ短時間でいい感じに作成したい方 Markdown での文書を書くことに抵抗がない方 ChatGPTを利用できる環境にある方 対象ではない人 独自性あふれる資料を作りたい 図や文章をスライドにふんだんに盛り込みたい NOTE ChatGPTを業務で利用する際にはセキュリティ等を考慮することが重要です。特に業務情報を取り扱うケースでは、自社の ガイドライン やポリシーに従って適切な対応を行ってください。ISIDでは、AIの活用のために ガイドライン を策定し、安全な業務利用ができるようサポートしています。 事前準備 今回は下記の3つのツールおよびサービスを利用します。 Visual Studio Code ChatGPT Marp 利用までのステップ Visual Studio Code (以後、 VS Code )をダウンロード後、 Marp for VS Code の 拡張機能 をインストールする ChatGPTのアカウントを作成して利用できる状態にする スライドの作成手順 1. 作ってほしいスライドの内容をChatGPTに入力 まずはChatGPTにスライドの下書き内容を出力してもらいましょう。 例えば下記のような内容を指定してみます。 あなたは熟練のエンジニアです。社内向けサービスのリプレイスを実施するプロジェクトに携わっています。 今回、その開発中のプロダクトについてプレゼンテーションを行うことになりました。下記の条件を考慮した下書きを書いていただけますか。 ## 条件 - Marp for VS Codeを使用したMarkdown形式のコードで出力してください - 10分程度の発表時間となるような分量で作成してください - 新サービスの紹介、背景はマストで盛り込み、加えてオーディエンスに技術者が多いため開発の詳細などの技術的な項目も盛り込みたい - fontは「Noto Sans JP, sans-serif」の2つを指定してください 発表タイトルは「新サービス「New Service」について」としてください ここでのポイントとしては下記の2つです。 どのように振る舞ってほしいかを記入する 今回だと「熟練のエンジニア」「優れたプレゼンテーター」などを冒頭の役割として与える できるだけ具体的に盛り込んで欲しい内容を書く Marp for VS Code を利用している旨を書く コピー&ペーストできる Markdown コードを出力してくれるため、ステップ2の操作が楽になります この記事はChatGPTの記事ではないので詳細は割愛しますが、役割と詳細な条件を与えるとより望ましい内容を出力してもらえる傾向があるようです。 ChatGPTに与えるプロンプトについて詳細を知りたい方は下記をぜひ一読してみてください。 Prompt Engineering Guide 上記の指示で出力されたコードは下記の通りです。 --- marp: true theme: default paginate: true size: 16:9 style: | font-family: 'Noto Sans JP', sans-serif; --- # 新サービス「New Service」について --- ## 目次 1. 新サービスの概要 2. 背景 3. 技術的な詳細 4. 開発の進捗 5. 今後の展望 --- ## 1. 新サービスの概要 - 社内向けの新サービス「New Service」 - 既存のサービスをリプレイス - 効率化、利便性の向上を目指す --- ## 2. 背景 ### 2.1 既存サービスの課題 - 時代遅れの技術 - 機能の不足 - スケーラビリティの問題 ### 2.2 リプレイスの目的 - 最新技術の導入 - 新たな機能の追加 - スケーラビリティの向上 --- ## 3. 技術的な詳細 ### 3.1 技術スタック - バックエンド: Node.js, Express - フロントエンド: React, Redux - データベース: PostgreSQL - インフラ: AWS, Docker ### 3.2 開発手法 - アジャイル開発 - CI/CDの導入 - コードレビュー、テスト自動化 --- ## 4. 開発の進捗 ### 4.1 バージョン管理 - Git, GitHubを使用 - 開発ブランチ、リリースブランチで管理 ### 4.2 開発環境 - VSCode, Marp for VS Code - 開発者同士のコミュニケーションはSlack, Teams ### 4.3 現状の進捗 - システム設計完了 - プロトタイプ開発中 - テストケースの作成 --- ## 5. 今後の展望 ### 5.1 プロジェクトの目標 - 新サービスのリリース - 既存サービスからのスムーズな移行 - 社内利用者の満足度向上 ### 5.2 開発チームの成長 - 新技術の習得 - より効率的な開発手法の模索 - 社内コミュニケーションの強化 --- ## まとめ - 社内向け新サービス「New Service」を開発中 - 既存サービスのリプレイスを実施 希望の内容が出力されない場合は、再生成や条件をより具体的に追加するなどの操作を行ってみてください。 2. 出力された Markdown のコードを貼り付ける VS Code で presentation_slide.md など Markdown 用のファイルを作成し、そこに出力された Markdown のコードを貼り付けます。 3. プレビューを表示する アクションペインを呼び出し、 Markdown: Open Preview to the Side を選択します。 すると貼り付けた Markdown のプレビューが表示されます。 Marpで良い感じのスタイルを適用してくれている為、それなりに整ったスライドが表示されているかと思います。 4. スタイルを変更する 現在のスライドでもいい感じですが、さすがにテキストだけのスライドは寂しいので画像も追加してみましょう。 例えば目次のスライドの右に画像を追加してみます。 --- ## 目次 1. 新サービスの概要 2. 背景 3. 技術的な詳細 4. 開発の進捗 5. 今後の展望 ![bg right](https://picsum.photos/866?image=3) --- 画像リンクと一緒に bg right と追加するだけで簡単に画像を追加できました。 また、特定のスライドにだけスタイルを適用することも簡単にできます。 例えば背景色を黒、文字色を白色に変更する場合は下記のように コメントアウト を追加します。 <!-- _backgroundColor: black _color: white --> ## 目次 1. 新サービスの概要 2. 背景 3. 技術的な詳細 4. 開発の進捗 5. 今後の展望 ![bg right](https://picsum.photos/866?image=3) 個別ページだけでなくページ全体に一括でスタイルを当てたり、フッターやヘッダーに共通したサブタイトルを表示させることもできますので気になる方は CSSについてのページ をご覧ください。 4. PowerPoint として出力する 最後に、ここまで作成したコードを PowerPoint として出力してみます。 VS Code の画面に表示される下記赤い枠のアイコンをクリックします。 その後、 Export Slide Deck... を選択 すると、出力形式を選択できるモーダルが立ち上がるので、 PowerPoint document を選択します。 最後に、 Export ボタンをクリックするとPowerpPointの画像が出力されます。 出力形式の選択時にも表示されていましたが、 PowerPoint の他、PDFやHTMLとしても出力ができます。 PowerPoint として出力する場合はスライドが全て画像となります。そのため、テキスト等の修正を行う場合は再度 VS Code より修正した上で再出力を行ってください。 Note Marpで選択したthemeやfontによっては、英数字と日本語の文字の太さが違うように出力される場合があります。その場合はスライド全体に当てるfont-familyを変更するなどの方法で対応してみてください。 まとめ 今回紹介したMarpとChatGPTを利用することで内容の吟味に集中できるので、スタイルの調整や構成を考えることに苦手意識のある方はぜひ利用していただきたいです。 また2023年3月には Office製品にAIを導入する という発表もあり、今後より自動化が進んでいきそうです。 私たちは同じチームで働いてくれる仲間を探しています。 フロントエンドやバックエンドと特定の領域にとらわれず幅広い技術領域に挑戦してみたい方がいらっしゃいましたら、ぜひご応募ください! ソリューションアーキテクト 執筆: @tokuyama 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました )
アバター
みなさんこんにちは、 電通国際情報サービス (ISID)X イノベーション 本部ソフトウェアデザインセンターの佐藤太一です。 この記事では、 VS Code のDev Containerを使ってOSに依存しない Python の開発環境を構築する方法をステップ バイス テップで丁寧に説明します。 VS Code の利用経験があり、また Python によるアプリケーション開発に興味のある方を想定読者として記述しています。 Python の初心者から中級者向けを意識して書いていますので、意図して冗長な説明をしています。 すでに Python によるアプリケーション開発に十分に詳しい方は、まずはまとめだけ読んでみてください。私自身それほど Python のエコシステムに詳しいわけではありませんので、知識の抜け漏れは恐らくあるでしょう。そういった事に気が付いたら、Xなどの SNS でこの記事のURLを付けてコメントをしていただけると幸いです。 はじめに 事前の準備 最小限のDev Container Dev Containerの起動 devcontainer.jsonを編集する環境の構築 最小限のPython用VS Code拡張 Poetryの導入 Python仮想環境の構築 プロジェクト構成ファイルの作成 コンテナ作成時に動作するシェルスクリプトの追加 Pythonの仮想環境用ボリュームのマウント プロジェクトローカルに仮想環境を作る さぁ、Pythonを動かそう フォーマッタとLinterの導入 pytestの導入 テストコードの追加 テストをターミナルから動かす テストをGUIから動かす テストをデバッガから動かす テストカバレッジを計測する pytest-covの導入 テストカバレッジの微調整 実行時オプションの調整 カバレッジ除外の調整 VS Codeにカバレッジレポートを統合する VS Codeにおけるカバレッジレポートの確認方法 タスクランナーの導入 まとめ この記事で紹介している開発環境の構成ファイル .devcontainer/devcontainer.json .devcontainer/postCreateCommand.sh .gitignore pyproject.toml はじめに ソフトウェア開発をチームで行うにあたって、もっとも困難な課題の一つは開発環境の再現性を担保することです。 開発チームのメンバーは、それぞれが固有の経験と知識を持っていますし、プロジェクトに参画する際の契約が異なることも多いでしょう。全てのメンバーが、単一のプロジェクトに使いうる全ての 工数 を使ってプロジェクトに貢献できるわけではありません。人によっては、複数のプロジェクトを掛け持ちしていることはあります。 ある開発メンバーは慣れている Mac を使いたいと考える時、違うメンバーは会社から標準的に貸与される Windows で開発したいと考えるかもしれません。しかし、アプリケーションのデプロイ先は Ubuntu や Debian といった Linux だったりします。 こういった状況では、特定のメンバーでのみ発生する不具合が存在したり、または特定のメンバーのローカル環境でしかアプリケーションが動作しないといった事が起こります。 原因が明らかになれば、単にPATH 環境変数 の違いのような簡単なことかもしれませんが、その過程は往々にして困難なものになります。そういった細かい環境差異を原因とする問題の調査はシニアなメンバーにしかできないことが多いのです。 しかし、その調査の時間は明らかに無駄ですし、ほぼ何の価値もありません。 付加価値の高いシニアなメンバーの 工数 を、そういった調査で浪費することはプロジェクトにとって望ましくないでしょう。 この記事で紹介する手法では、Dockerベースのコンテナ技術を使うことで、メンバー毎の環境差分をできるだけ小さくできます。ハードウェアスペックやネットワークに起因するもの以外は差分が全く存在しなくなると言っても良いでしょう。つまり、開発メンバーのなかで誰かのマシンで起きた問題は、メンバー全員のマシンで再現します。 気になってきましたか?それでは、Dev Containerを使った開発環境構築について説明を始めます。 事前の準備 この記事が前提とする環境について軽く説明します。 まず、 VS Code を事前にインストールしておいてください。 次に、 Docker Desktop をインストールして動作する状態にしてください。基本的には単に インストーラ を実行すれば動作する状態になります。 そして、 VS Code に Dev Containers 拡張をインストールしておいてください。 最後に、作業用のプロジェクト ディレクト リを作成してください。ここでは、 devcontainer-python という ディレクト リを作成してプロジェクトのルート ディレクト リとしています。 最小限のDev Container まずは、Dev Containerで公式に提供されている Python の開発環境を導入してみましょう。 プロジェクトのルート ディレクト リに、 .devcontainer という ディレクト リを作って、その中に devcontainer.json というファイル名で以下の内容を保存します。 { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] } name の値は、分かりやすい名前なら何でもいいです。ここでは、devcontainer- python としています。 image の値は、mcr. microsoft .com/devcontainers/ python :3.12-bookworm としています。これは、公式のイメージ名です。 ベースイメージや Python ランタイムのバージョンを別なものにしたい場合には、 https://github.com/microsoft/vscode-dev-containers/tree/main/containers/python-3 から探してください。 containerEnv の値は、コンテナ内で参照される 環境変数 です。ここでは タイムゾーン が Asia/Tokyo になるよう設定しています。時刻に起因する問題の調査は難しいので、ここで明示的に設定しています。 runArgs の値として --init を渡すことで、Dockerが /dev/init というシグナルハンドリング用のプロセスを起動してくれます。これによってコンテナを安定的にシャットダウンできるようになります。 Dev Containerの起動 それでは、作ったDev Containerを起動してみましょう。 プロジェクトのルート ディレクト リを VS Code で開いた上で画面左端のアイコンをクリックしてREMOTE EXPLORER を表示します。 reopen the current folder in a container のリンクをクリックするとDev Containerの起動が始まります。 画面右下に、Dev Containerの起動が始まったことを通知するダイアログが数秒間だけ表示されるので、サッとクリックしましょう。 クリックすると起動ログが流れていく様子を観察できます。 起動ログの流れが落ち着いたら、ターミナルを起動してみましょう。ログの右上あたりにある + ボタンです。Ctrlキーと@キーを同時に押しても構いません。 以下のようにターミナルが表示されますね。 コンテナ内では vscode というユーザーで、 workspace/devcontainer-python という ディレクト リをカレント ディレクト リにしています。 ディレクト リパスの devcontainer-python 部分はプロジェクトのルート ディレクト リと同じになっているはずです。 devcontainer. json を編集する環境の構築 ここから、devcontainer. json を編集しながら開発環境を構築していくので、まずは快適に json ファイルを編集できるようにしましょう。 devcontainer. json には、Dev Containerとして起動した VS Code を構成するための設定項目がありますので、それらを編集します。 { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] , " customizations ": { " vscode ": { " settings ": { " editor.renderWhitespace ": " all ", " [json][jsonc] ": { " editor.defaultFormatter ": " esbenp.prettier-vscode ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": true } } } , " extensions ": [ " esbenp.prettier-vscode " ] } } } customizations というキーがDev Containerの構成を行うための設定項目です。この中に vscode という項目がありますね。 settings の中では、 VS Code の設定項目を管理します。 editor.renderWhitespace の値として、 all を設定しているのは、ファイルの中に紛れ込んだ全角スペースを見つけやすくするためです。私たちが IME を使っている以上、意図しない場所に全角スペースが入り込んでしまい、それによって理解が困難なエラーメッセージを読むことになるのは避けられません。全角スペースが見えていれば、そういったドハマりから抜け出しやすくなります。 [json][jsonc] の値として、いくつか設定しています。ちなみに、jsoncは、 JSON with commentsの略称です。 editor.defaultFormatter の値として、esbenp.prettier- vscode を設定しています。これによってprettierを使ったフォーマットが行われます。 editor.formatOnSave の値として、trueを設定することでファイル保存時にフォーマットが行われるようにしています。 editor.codeActionsOnSave の値として、source.fixAll を有効化することで自動的に補正できるフォーマットエラーをprettierが積極的に補正してくれます。 extensions の中では、Dev Containerとして起動された VS Code にインストールされる VS Code 拡張を列挙します。ここでは、 JSON を自動フォーマットするための esbenp.prettier-vscode を設定しています。 最小限の Python 用 VS Code 拡張 次は、 Python 用の VS Code 拡張をいくつか追加していきましょう。 おすすめの拡張は、 Python Python Indent autoDocstring の三つです。他にも便利なものは多くありますが、特に議論の余地なく導入できるものはこれらです。 devcontainer. json のextensionsにこれらの拡張を追加すると、以下のようになります。 { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] , " customizations ": { " vscode ": { " settings ": { " editor.renderWhitespace ": " all ", " [json][jsonc] ": { " editor.defaultFormatter ": " esbenp.prettier-vscode ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": true } } } , " extensions ": [ " esbenp.prettier-vscode ", " ms-python.python ", " njpwerner.autodocstring ", " KevinRose.vsc-python-indent " ] } } } devcontainer. json を修正したら、忘れずにDev Containerをリビルドしましょう。 リビルドするには、REMOTE EXPLORER を表示して動作しているコンテナを右クリックします。 ここで表示される コンテキストメニュー から Rebuild Container を選択します。 これで、 VS Code を Python 用のエディタとして使うための準備は整ったと言えます。 しかしながら、アプリケーションの開発環境と呼ぶには、まだまだ不足がありますので順次整えていきましょう。 Poetryの導入 Python でアプリケーション開発を行うなら、標準ライブラリを使うだけでなく巨大なコミュニティ内で提供されるモジュールを利用して、その恩恵にあずかりましょう。 pipコマンドだけで OSS のモジュールをインストールするという ストロングス タイルも良いものですが、私が推奨するのはPoetryを使ったモジュール管理です。ここでは、Poetry自体の是非については特に議論しません。 Dev Containerには、featuresという機能がありdevcontainer. json を少し書き加えるだけでPoetryを使えます。 { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] , " features ": { " ghcr.io/devcontainers-contrib/features/poetry:2 ": {} } , " customizations ": { " vscode ": { " settings ": { " editor.renderWhitespace ": " all ", " [json][jsonc] ": { " editor.defaultFormatter ": " esbenp.prettier-vscode ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": true } } } , " extensions ": [ " esbenp.prettier-vscode ", " ms-python.python ", " njpwerner.autodocstring ", " KevinRose.vsc-python-indent " ] } } } features の値として、 "ghcr.io/devcontainers-contrib/features/poetry:2": {} が記述されていますね。 こうすることで、Dev Container起動時にPoetryがコンテナ内のゲストOSにグローバルインストールされるのです。 devcontainer. json を書き換えたらDev Containerをリビルドしましょう。 Python 仮想環境の構築 Dev Containerのリビルドから戻ってきたら、Poetryが使うプロジェクト構成ファイルを作りましょう。 プロジェクト構成ファイルの作成 プロジェクトのルート ディレクト リに、pyproject.toml というファイル名で以下の内容を保存します。 [tool.poetry] name = "mymodule" version = "0.1.0" description = "" authors = ["sato taichi <sato.taichi@example.com>"] readme = "README.md" [tool.poetry.dependencies] python = "^3.12" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" このファイルを作る方法は色々ありますので、詳細を知りたい方はPoetryのドキュメントを参考にしてください。 Basic usage コンテナ作成時に動作する シェルスクリプト の追加 次は、コンテナをビルドした直後だけ動作する シェルスクリプト を追加します。 この シェルスクリプト を工夫するとコンテナ内で色んな作業をして、混乱状況になってもリビルドするだけで全てを元に戻せます。 まずは、簡単な シェルスクリプト から始めましょう。.devcontainer ディレクト リにpostCreateCommand.shというファイル名で以下の内容を保存します。このファイルの改行コードはLFにてください。 #!/bin/sh # postCreateCommand.sh echo "START Install" sudo chown -R vscode:vscode . echo "FINISH Install" 内容としては、プロジェクトのルート ディレクト リ以下にあるファイルや ディレクト リのオーナー権限を全て vscode ユーザーおよび vscode グループにするというものです。 以下のコマンドをターミナルで実行して実行権限を付与して下さい。 chmod +x .devcontainer/postCreateCommand.sh Dev Containerでは、ホストOS上にあるプロジェクトのルート ディレクト リを自動的にbindマウントしています。つまり、ゲストOSであるコンテナから見える既存のファイルや ディレクト リの権限がrootになってしまいます。Dev Container内で使うユーザーをrootにしても良いのですが、個人的には例えコンテナ内であったとしても普段使いするユーザーとしてrootを使いたくはありません。このような習慣を持つことで例えば、何か悪意のあるモジュールを誤ってインストールしてしまった時の被害を少しだけ低減できます。 便利な事にDev Containerが公式に提供しているコンテナイメージでは、 vscode ユーザーをsudoersとして登録しています。参考: common-debian.sh#L209-L213 この シェルスクリプト を動かすには、devcontainer. json にpostCreateCommandというキーで シェルスクリプト の ワークスペース からの 相対パス を設定します。 { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] , " features ": { " ghcr.io/devcontainers-contrib/features/poetry:2 ": {} } , " postCreateCommand ": " ./.devcontainer/postCreateCommand.sh ", " customizations ": { " vscode ": { " settings ": { " editor.renderWhitespace ": " all ", " [json][jsonc] ": { " editor.defaultFormatter ": " esbenp.prettier-vscode ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": true } } } , " extensions ": [ " esbenp.prettier-vscode ", " ms-python.python ", " njpwerner.autodocstring ", " KevinRose.vsc-python-indent " ] } } } devcontainer. json を書き換えたのでDev Containerをリビルドしましょう。 コンテナ作成時に、postCreateCommand.shが動作するのを確認できます。 これは作成時しか動作しないので、例えば単に VS Code を再起動しても動作しません。つまり少々コストの高い処理を記述しても待つのは一度だけになります。 Python の仮想環境用ボリュームのマウント 次は、Poetryが作る Python の仮想環境について考えてみましょう。 要はプロジェクトのルート ディレクト リ以下に、作成される .venv ディレクト リをどう扱うかということです。 取りうる選択肢として最初の候補は特に気にせず .gitignore ファイルへ .venv ディレクト リを追加する、というやり方です。プロジェクトのルート ディレクト リは、Dev Containerによって既にbindマウントされているのだから、そのままにしておいてもそれほど大きな問題はありません。とはいえ、ホストOSでは実行 不能 な実行バイナリが直接 ファイルシステム 上に現れるのは、あまり気持ちよくはありません。 次の選択肢は、 .venv ディレクト リを特別扱いしてvolumeマウントすることです。これによって、ホストOS上に Python の仮想環境が直接現れなくなります。加えて、volumeマウントはbindマウントするよりもI/Oのパフォーマンスが少しだけ改善します。また、gitなどの構成管理ツールから明示的に除外しなくていいのも利点です。 volumeマウントをDev Containerに追加するには、devcontainer. json にmountsという項目の設定を追加します。 { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] , " features ": { " ghcr.io/devcontainers-contrib/features/poetry:2 ": {} } , " postCreateCommand ": " ./.devcontainer/postCreateCommand.sh ", " mounts ": [ " source=venv-${devcontainerId},target=${containerWorkspaceFolder}/.venv,type=volume " ] , " customizations ": { " vscode ": { " settings ": { " editor.renderWhitespace ": " all ", " [json][jsonc] ": { " editor.defaultFormatter ": " esbenp.prettier-vscode ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": true } } } , " extensions ": [ " esbenp.prettier-vscode ", " ms-python.python ", " njpwerner.autodocstring ", " KevinRose.vsc-python-indent " ] } } } devcontainer. json では、設定値の中に ${ で始まり } で終わる部分があると、その中を変数として特別扱いします。 mountsの値だけを取り出してきたのがこれです。 "source=venv-${devcontainerId},target=${containerWorkspaceFolder}/.venv,type=volume" ここでは、 devcontainerId と containerWorkspaceFolder という変数が展開されてDockerの起動オプションに渡されます。それぞれにどんな値が入っているのかは、公式のマニュアルを確認してください。 https://containers.dev/implementors/json_reference/#variables-in-devcontainerjson プロジェクトローカルに仮想環境を作る 次は、いよいよ Python 仮想環境の構築です。と言ってもPoetryを使っているので極めて簡単です。 先ほど作った、postCreateCommand.sh にPoetry用のコマンドを2行を追加するだけです。 #!/bin/sh # postCreateCommand.sh echo "START Install" sudo chown -R vscode:vscode . poetry config virtualenvs.in-project true poetry install echo "FINISH Install" グローバルにインストールされているPoetryの設定を変えるコマンドは poetry config です。ここでは、 virtualenvs.in-project を有効化しています。 その後、 poetry install コマンドを実行することで仮想環境が ワークスペース 直下の .venv ディレクト リに作成されます。 あわせて、 ワークスペース のルート ディレクト リにREADME.mdというファイルを作ります。中身は何でもいいのですが、一旦以下のようにすると良いでしょう。 # devcontainer-python 動作を確認するために、 シェルスクリプト の変更が終わったらDev Containerをリビルドしましょう。 さぁ、 Python を動かそう ここからは、いよいよ Python のコードを動かします。 ワークスペース のルート ディレクト リに mymoduleという ディレクト リを作って、その中にmain.pyというファイル名で以下の内容を保存します。 #!/usr/bin/env python if __name__ == "__main__" : print ( "Hello, World" ) 特別さのないコードですね。このファイルを開いた状態で VS Code の右下あたりに注目してください。 このような表示になっているなら、 Python の仮想環境に配置されている インタープリタ ーが使われています。 そうでない場合は赤く囲った内側の青い部分をクリックしてください。そうすると、 インタープリタ ーを選択するダイアログが表示されるので、 .venv/bin/python というパスの インタープリタ ーをクリックすることで選択してください。 プロジェクト直下の.venv ディレクト リが VS Code に正しく認識された状態になると、ターミナルを起動した際、自動的にactivate スクリプト を実行してくれます。 これでPoetryで管理しているモジュールや実行バイナリが実行されるようになりました。 この状態を維持するために、devcontainer. json に python.defaultInterpreterPath という設定に".venv/bin/ python "を追加します。 設定追加後のdevcontainer. json は以下のようになります。 { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] , " features ": { " ghcr.io/devcontainers-contrib/features/poetry:2 ": {} } , " postCreateCommand ": " ./.devcontainer/postCreateCommand.sh ", " mounts ": [ " source=venv-${devcontainerId},target=${containerWorkspaceFolder}/.venv,type=volume " ] , " customizations ": { " vscode ": { " settings ": { " editor.renderWhitespace ": " all ", " python.defaultInterpreterPath ": " .venv/bin/python ", " [json][jsonc] ": { " editor.defaultFormatter ": " esbenp.prettier-vscode ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": true } } } , " extensions ": [ " esbenp.prettier-vscode ", " ms-python.python ", " njpwerner.autodocstring ", " KevinRose.vsc-python-indent " ] } } } devcontainer. json を書き換えたらDev Containerをリビルドしましょう。 フォーマッタとLinterの導入 コードを実行できるようになったので、次はフォーマッタとLinterを導入しましょう。ターミナルを VS Code から起動して以下のコマンドを実行します。 poetry add --group dev ruff これによって、 Python 用のコードフォーマッタかつ、LinterであるRuffがインストールされます。 https://docs.astral.sh/ruff/ これらを VS Code と連携するための設定と拡張を追加しましょう。 { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] , " features ": { " ghcr.io/devcontainers-contrib/features/poetry:2 ": {} } , " postCreateCommand ": " ./.devcontainer/postCreateCommand.sh ", " mounts ": [ " source=venv-${devcontainerId},target=${containerWorkspaceFolder}/.venv,type=volume " ] , " customizations ": { " vscode ": { " settings ": { " editor.renderWhitespace ": " all ", " python.defaultInterpreterPath ": " .venv/bin/python ", " [python] ": { " editor.defaultFormatter ": " charliermarsh.ruff ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": true , " source.organizeImports ": true } } , " [json][jsonc] ": { " editor.defaultFormatter ": " esbenp.prettier-vscode ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": true } } } , " extensions ": [ " esbenp.prettier-vscode ", " ms-python.python ", " njpwerner.autodocstring ", " KevinRose.vsc-python-indent ", " charliermarsh.ruff " ] } } } ここでは、 以下のような変更を加えています。 [python] に設定を記述することでファイル保存時にフォーマットやLint、それに伴う自動補正が行われるようにしました。 charliermarsh.ruff を VS Code 拡張として追加しました。 RuffはBlackとの互換性のためにコードを折り返す際の基準とする文字数が 88 と異様に小さいのでここだけは設定を変更します。 Ruffの設定は、pyproject.tomlに記載します。 [tool.poetry] name = "mymodule" version = "0.1.0" description = "" authors = ["sato taichi <sato.taichi@example.com>"] readme = "README.md" [tool.poetry.dependencies] python = "^3.12" [tool.poetry.group.dev.dependencies] ruff = "^0.1.4" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" [tool.ruff] line-length = 200 devcontainer. json を書き換えたのでDev Containerをリビルドですよね。 pytestの導入 コードを快適に書けるようになってきたので、次はテスティング フレームワーク の導入です。 Python には多くのテスティング フレームワーク がありますが、私が一番気に入っているのはpytestです。 Poetryを使ってpytestを導入しましょう。以下のコマンドを実行します。 poetry add --group dev pytest モジュールを追加したら VS Code の設定も変更します。 { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] , " features ": { " ghcr.io/devcontainers-contrib/features/poetry:2 ": {} } , " postCreateCommand ": " ./.devcontainer/postCreateCommand.sh ", " mounts ": [ " source=venv-${devcontainerId},target=${containerWorkspaceFolder}/.venv,type=volume " ] , " customizations ": { " vscode ": { " settings ": { " editor.renderWhitespace ": " all ", " python.defaultInterpreterPath ": " .venv/bin/python ", " python.testing.pytestArgs ": [ " tests ", " --capture=tee-sys ", " -vv " ] , " python.testing.pytestEnabled ": true , " [python] ": { " editor.defaultFormatter ": " charliermarsh.ruff ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": true , " source.organizeImports ": true } } , " [json][jsonc] ": { " editor.defaultFormatter ": " esbenp.prettier-vscode ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": true } } } , " extensions ": [ " esbenp.prettier-vscode ", " ms-python.python ", " njpwerner.autodocstring ", " KevinRose.vsc-python-indent ", " charliermarsh.ruff " ] } } } ここで追加したのは、以下の二つです。 python.testing.pytestEnabled を trueにすることで VS Code がpytestを使ってテストコードを検索します。 python.testing.pytestArgs にはpytest起動時のオプションを三つ設定しています。 最初の tests はこの ディレクト リ内にあるテストコードを実行するという意味です。 次の --capture=tee-sys は、テストコード内で標準出力された内容をpytestがキャプチャしてターミナルに出力してくれます。 最後の -vv を付けることで、pytestがキャプチャした出力を途中で切らずに全て出力します。 テストコードの追加 テストコードを追加して動かしてみましょう。 ワークスペース のルート ディレクト リに tests という ディレクト リを作って、その中にtest_sample.pyというファイル名で以下の内容を保存します。 # content of test_sample.py def inc (x): return x + 1 def test_answer (): assert inc( 3 ) == 5 与えられた数字に1を加算する関数と、それをテストする関数です。 テストをターミナルから動かす まずは、テストをターミナルで動かしてみましょう。以下のコマンドを実行します。 pytest 案の定 アサーション が正しくないのでテストは失敗します。 テストを GUI から動かす 次は、 VS Code からテストを動かしてみましょう。 左側のメニューからフラスコのようなアイコンをクリックしてTESTINGビューを表示した上で右向きの三角をクリックするとテストを実行できます。もしくは、単にテスト関数の近くにある右向き三角でも構いません。 予想通りテストは失敗します。 テストをデバッガから動かす 次はテストを デバッグ 実行しましょう。コードを見てもどうしてテストが失敗するのか分からない時は、デバッガを使うと便利です。 まずは、 ブレークポイント を設定します。エディタのガッター部分をクリックすると赤い〇が付いて、そこが ブレークポイント になります。 TESTINGビューの虫アイコンがついたボタンを押して実行するとデバッガが動作します。 設定された ブレークポイント で止まると変数の中身や スタックトレース が確認できますね。 これで快適にテストが実行できるようになったので、ソフトウェア開発環境としては十分だと言えるかもしれません。 高品質なソフトウェアを作るために、もうひと踏ん張りしてみましょう。 テスト カバレッジ を計測する テスト カバレッジ を取ることで、テストコードが意図したとおりにアプリケーションコードをテストできているか確認できるようにしましょう。 テスト カバレッジ は100%を目指して ホワイトボックステスト するのに使うと極めて不毛な時間を過ごすことになります。 しかし、大体75%~85%を目途に意図したとおりにアプリケーションコードが動作しているかを確認するのに使うと非常に便利です。自分は仕様を完全に把握しているのだと思っても抜け漏れは少なからずあるものです。 pytest- cov の導入 pytestには、 Coverage.py を使ってテスト カバレッジ をとれる プラグイン があるので、それを導入しましょう。以下のコマンドを実行します。 poetry add --group dev pytest- cov これでpytestを実行する際に カバレッジ を取得するオプションが使えます。例えば、以下のコマンドで カバレッジ を取得できます。 pytest -- cov =. -- cov -report html このコマンドを実行後はプロジェクトのルート ディレクト リに htmlcov という ディレクト リが作成されて、その中にhtmlで作成された カバレッジ レポートが格納されています。 HTMLでそれなりにきれいな表示がされていて、ソフトウェア開発が主たる業務でない人にとっては十分なレポートだと言えます。 テスト カバレッジ の微調整 テスト カバレッジ を取り始めると、細かい調整が必要になっていきます。 私自身、それほど Python に詳しいわけではありませんが、実案件での利用を通じて発生した微調整をいくつかご紹介します。 実行時オプションの調整 pyproject.tomlに [tool.coverage.run] という項目を追加します。 [tool.poetry] name = "mymodule" version = "0.1.0" description = "" authors = ["sato taichi <sato.taichi@example.com>"] readme = "README.md" [tool.poetry.dependencies] python = "^3.12" [tool.poetry.group.dev.dependencies] ruff = "^0.1.4" pytest = "^7.4.3" pytest-cov = "^4.1.0" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" [tool.ruff] line-length = 200 [tool.coverage.run] branch = true source = ["mymodule", "tests"] omit = ["tests/fixtures/*"] data_file = ".pytest_cache/.coverage" 設定項目は四つです。 branch を有効化することでブランチ カバレッジ を取得するようにしています。これによって カバレッジ の計測コストが若干上がります。 source に カバレッジ の計測対象となるファイルが格納されている ディレクト リを指定しています。 omit では、逆に カバレッジ の計測対象としないファイルが格納されている ディレクト リを指定しています。 data_file では、 カバレッジ 計測データのバイナリファイルを格納する ディレクト リをプロジェクトのルート ディレクト リから.pytest_cache ディレクト リ内に移動することで、普段はその存在を気にしないで済むようにしています。 カバレッジ 除外の調整 ここでは、pyproject.tomlに [tool.coverage.report] という項目を追加して細粒度の構文レベルで カバレッジ 取得対象から ソースコード を除外しています。 [tool.poetry] name = "mymodule" version = "0.1.0" description = "" authors = ["sato taichi <sato.taichi@example.com>"] readme = "README.md" [tool.poetry.dependencies] python = "^3.12" [tool.poetry.group.dev.dependencies] ruff = "^0.1.4" pytest = "^7.4.3" pytest-cov = "^4.1.0" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" [tool.ruff] line-length = 200 [tool.coverage.run] branch = true source = ["mymodule", "tests"] omit = ["tests/fixtures/*"] data_file = ".pytest_cache/.coverage" [tool.coverage.report] exclude_lines = [ "pragma: no cover", "def __repr__", "def __str__", "raise AssertionError", "raise NotImplementedError", "if __name__ == .__main__.:", "if TYPE_CHECKING:", "if typing.TYPE_CHECKING:", ] それぞれの詳細については、ここでは説明しません。 VS Code に カバレッジ レポートを統合する コードを書いている プログラマー としては、 カバレッジ レポートは普段使っているエディタ上に表示されてほしいものです。レポートを見るためだけにウィンドウを切り替えるのはわずらわしいですからね。 というわけで、拡張の導入と設定です。コード カバレッジ を表示する VS Code 拡張はいくつかあるのですが、私が試した範囲内では、 Coverage Gutters が最も期待通りに動作しました。 Coverage Guttersは、Coverage.pyが出力した XML のレポートを入力情報として使いますので、pyproject.tomlにレポートの出力先を設定します。 [tool.poetry] name = "mymodule" version = "0.1.0" description = "" authors = ["sato taichi <sato.taichi@example.com>"] readme = "README.md" [tool.poetry.dependencies] python = "^3.12" [tool.poetry.group.dev.dependencies] ruff = "^0.1.4" pytest = "^7.4.3" pytest-cov = "^4.1.0" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" [tool.ruff] line-length = 200 [tool.coverage.run] branch = true source = ["mymodule", "tests"] omit = ["tests/fixtures/*"] data_file = ".pytest_cache/.coverage" [tool.coverage.report] exclude_lines = [ "pragma: no cover", "def __repr__", "def __str__", "raise AssertionError", "raise NotImplementedError", "if __name__ == .__main__.:", "if TYPE_CHECKING:", "if typing.TYPE_CHECKING:", ] [tool.coverage.xml] output = ".pytest_cache/coverage.xml" 最後の二行が追加した項目です。これによって、出力レポートのタイプとして XML を指定した際に、.pytest_cache/coverage. xml へファイルが出力されます。 次は、devcontainer. json を修正します。 { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] , " features ": { " ghcr.io/devcontainers-contrib/features/poetry:2 ": {} } , " postCreateCommand ": " ./.devcontainer/postCreateCommand.sh ", " mounts ": [ " source=venv-${devcontainerId},target=${containerWorkspaceFolder}/.venv,type=volume " ] , " customizations ": { " vscode ": { " settings ": { " editor.renderWhitespace ": " all ", " python.defaultInterpreterPath ": " .venv/bin/python ", " python.testing.pytestArgs ": [ " tests ", " --capture=tee-sys ", " -vv " ] , " python.testing.pytestEnabled ": true , " [python] ": { " editor.defaultFormatter ": " charliermarsh.ruff ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": true , " source.organizeImports ": true } } , " coverage-gutters.showLineCoverage ": true , " coverage-gutters.showRulerCoverage ": true , " coverage-gutters.coverageFileNames ": [ " .pytest_cache/coverage.xml " ] , " [json][jsonc] ": { " editor.defaultFormatter ": " esbenp.prettier-vscode ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": true } } } , " extensions ": [ " esbenp.prettier-vscode ", " ms-python.python ", " njpwerner.autodocstring ", " KevinRose.vsc-python-indent ", " charliermarsh.ruff ", " ryanluker.vscode-coverage-gutters " ] } } } ここでは、三つの設定項目を追加すると共にインストールする拡張として ryanluker.vscode-coverage-gutters を追加しています。 coverage-gutters.showLineCoverage を有効化することで、行全体に色が付くようになります。 coverage-gutters.showRulerCoverage を有効化することで、行の左側にある目盛り部分に色が付くようになります。 coverage-gutters.coverageFileNames に設定しているパスと、pyproject.tomlが一致していることで、 カバレッジ レポートの結果を ryanluker.vscode-coverage-gutters が正しく処理できます。 devcontainer. json を書き換えたのでDev Containerをリビルドしましょう。 VS Code における カバレッジ レポートの確認方法 まずは、以下のコマンドを実行して カバレッジ レポートを作成します。 pytest -- cov =. -- cov -report xml 相変わらずテストは失敗していますね。しかし、 .pytest_cache/coverage.xml というファイルは出力されているはずです。これを使って カバレッジ を確認していきましょう。 VS Code の左下あたりに注目してください。 〇Watch という表示があるはずです。これをクリックすると カバレッジ レポートの表示が有効化されます。 カバレッジ レポートがエディタ上に表示されるとこのようになります。 これで、 カバレッジ レポートを確認しながらコードを書けるようになりました。 そろそろこの記事も終盤に差し掛かってきています。もう少しだけお付き合いください。 タ スクラン ナーの導入 最後は、プロジェクト構成ファイルであるpyproject.tomlに定型化された作業をタスクとして記述する方法を説明します。 長いコマンドでも構成ファイル内に書いてあればコマンドの実行ミスは無くなります。また、 GitHub ActionsのようなCIワークフローを構成する際にも、すでにタスクが定義されていれば非常に少ない 工数 で実現できます。 様々なタスク定義ツールがありますが、私が気に入って使っているのは、 Poe the Poet です。以下のコマンドを実行してインストールしましょう。 poetry add --group dev poethepoet インストールが終わったら、pyproject.tomlにここまで構成してきたタスクをいくつか書いてみましょう。 [tool.poetry] name = "mymodule" version = "0.1.0" description = "" authors = ["sato taichi <sato.taichi@example.com>"] readme = "README.md" [tool.poetry.dependencies] python = "^3.12" [tool.poetry.group.dev.dependencies] ruff = "^0.1.4" pytest = "^7.4.3" pytest-cov = "^4.1.0" poethepoet = "^0.24.2" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" [tool.ruff] line-length = 200 [tool.coverage.run] branch = true source = ["mymodule", "tests"] omit = ["tests/fixtures/*"] data_file = ".pytest_cache/.coverage" [tool.coverage.report] exclude_lines = [ "pragma: no cover", "def __repr__", "def __str__", "raise AssertionError", "raise NotImplementedError", "if __name__ == .__main__.:", "if TYPE_CHECKING:", "if typing.TYPE_CHECKING:", ] [tool.coverage.xml] output = ".pytest_cache/coverage.xml" [tool.poe.tasks] lint = "ruff check mymodule" test = "pytest" cover = "pytest --cov=mymodule --cov-report xml" fmt = "black mymodule --check" build = ["fmt", "lint", "test"] [tool.poe.tasks] 以下に書かれているものが実行可能なタスクです。ここでは、五つのタスクを定義しています。 lint タスクでは、 Ruffによるコードの検査を実行します。 testタスクでは、pytestを実行します。 coverタスクでは、コード カバレッジ を取得しながらpytestを実行します。 fmtタスクでは、Ruffによるコードの整形を実行します。 buildタスクでは、 fmtタスクを実行した後にlintタスクを実行し最後にtestタスクを実行します。 これらのタスクは、 poe コマンドから実行できます。例えば、lintタスクを実行する際には、以下のようなコマンドを実行します。 poe lint 非常に簡単ですね。testタスクのように内部的にはコマンドを引数なしで実行しているだけでもタスクとして定義しているのは、ツールの移行コストを下げるためです。 例えば、今回はlinterとしてRuffを使っていますが、使い込む過程で回避しようのない不具合が見つかりFlake8のような実績のあるツールに切り戻すことはありえます。そういった時にCIやCDのワークフローに対する影響をできるかぎり減らして移行できるようにするには、タ スクラン ナーによるコマンドの抽象化が有効です。 まとめ ここまで、Dev Containerで Python アプリケーションの開発環境を構築する方法について説明してきました。 プロジェクトメンバーができるかぎり同じ環境でアプリケーション開発を行うことは、浪費される 工数 を減らしプロジェクトとして価値のある作業に集中するために必要な事です。 この記事では Python 開発環境を扱いましたが、同様の考え方でTypeScriptや、Rust、 Ruby 、 Java といった他の言語の開発環境を構築できます。 また、 GitHub Codespacesのような クラウド 開発環境の利用も難なくできます。 作っているアプリケーションの種類や、プロジェクトチーム内での役割次第ではブラウザ一つ動く環境さえあればソフトウェア開発できるというのは、非常に魅力的ですよね。 ここまで読んでいただいた皆さん、本当にお疲れさまでした。この記事を読んだ皆さんが、利便性の高い開発環境で本来のソフトウェア開発に集中できることを願って記事の結びとします。 この記事で紹介している開発環境の構成ファイル 最後に作った構成ファイルをまとめて紹介します。 .devcontainer/devcontainer. json { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] , " features ": { " ghcr.io/devcontainers-contrib/features/poetry:2 ": {} } , " postCreateCommand ": " ./.devcontainer/postCreateCommand.sh ", " mounts ": [ " source=venv-${devcontainerId},target=${containerWorkspaceFolder}/.venv,type=volume " ] , " customizations ": { " vscode ": { " settings ": { " editor.renderWhitespace ": " all ", " python.defaultInterpreterPath ": " .venv/bin/python ", " python.testing.pytestArgs ": [ " tests ", " --capture=tee-sys ", " -vv " ] , " python.testing.pytestEnabled ": true , " [python] ": { " editor.defaultFormatter ": " charliermarsh.ruff ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": true , " source.organizeImports ": true } } , " coverage-gutters.showLineCoverage ": true , " coverage-gutters.showRulerCoverage ": true , " coverage-gutters.coverageFileNames ": [ " .pytest_cache/coverage.xml " ] , " [json][jsonc] ": { " editor.defaultFormatter ": " esbenp.prettier-vscode ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": true } } } , " extensions ": [ " esbenp.prettier-vscode ", " ms-python.python ", " njpwerner.autodocstring ", " KevinRose.vsc-python-indent ", " charliermarsh.ruff ", " ryanluker.vscode-coverage-gutters " ] } } } .devcontainer/postCreateCommand.sh 改行コードはLFです。実行権限の付与を忘れずに。 #!/bin/sh # postCreateCommand.sh echo "START Install" sudo chown -R vscode:vscode . poetry config virtualenvs.in-project true poetry install echo "FINISH Install" .gitignore *.pyc *_cache pyproject.toml [tool.poetry] name = "mymodule" version = "0.1.0" description = "" authors = ["sato taichi <sato.taichi@example.com>"] readme = "README.md" [tool.poetry.dependencies] python = "^3.12" [tool.poetry.group.dev.dependencies] ruff = "^0.1.4" pytest = "^7.4.3" pytest-cov = "^4.1.0" poethepoet = "^0.24.2" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" [tool.ruff] line-length = 200 [tool.coverage.run] branch = true source = ["mymodule", "tests"] omit = ["tests/fixtures/*"] data_file = ".pytest_cache/.coverage" [tool.coverage.report] exclude_lines = [ "pragma: no cover", "def __repr__", "def __str__", "raise AssertionError", "raise NotImplementedError", "if __name__ == .__main__.:", "if TYPE_CHECKING:", "if typing.TYPE_CHECKING:", ] [tool.coverage.xml] output = ".pytest_cache/coverage.xml" [tool.poe.tasks] lint = "ruff check mymodule" test = "pytest" cover = "pytest --cov=mymodule --cov-report xml" fmt = "ruff format ." build = ["fmt", "lint", "test"] 執筆: @sato.taichi 、レビュー: @mizuno.kazuhiro ( Shodo で執筆されました )
アバター
みなさんこんにちは、 電通 総研コーポーレート本部システム推進部の佐藤太一です。 この記事では、 VS Code のDev Containerを使ってOSに依存しない Python の開発環境を構築する方法をステップ バイス テップで丁寧に説明します。 VS Code の利用経験があり、また Python によるアプリケーション開発に興味のある方を想定読者として記述しています。 Python の初心者から中級者向けを意識して書いていますので、意図して冗長な説明をしています。 すでに Python によるアプリケーション開発に十分に詳しい方は、まずはまとめだけ読んでみてください。私自身それほど Python のエコシステムに詳しいわけではありませんので、知識の抜け漏れは恐らくあるでしょう。そういった事に気が付いたら、Xなどの SNS でこの記事のURLを付けてコメントをしていただけると幸いです。 はじめに 事前の準備 最小限のDev Container Dev Containerの起動 devcontainer.jsonを編集する環境の構築 最小限のPython用VS Code拡張 uvの導入 Python仮想環境の構築 プロジェクト構成ファイルの作成 コンテナ作成時に動作するシェルスクリプトの追加 Pythonの仮想環境用ボリュームのマウント プロジェクトローカルに仮想環境を作る さぁ、Pythonを動かそう フォーマッタとLinterの導入 pytestの導入 テストコードの追加 テストをターミナルから動かす テストをGUIから動かす テストをデバッガから動かす テストカバレッジを計測する pytest-covの導入 テストカバレッジの微調整 実行時オプションの調整 カバレッジ除外の調整 VS Codeにカバレッジレポートを統合する VS Codeにおけるカバレッジレポートの確認方法 タスクランナーの導入 uvでのタスクランナー まとめ この記事で紹介している開発環境の構成ファイル .devcontainer/devcontainer.json .devcontainer/postCreateCommand.sh .gitignore pyproject.toml はじめに ソフトウェア開発をチームで行うにあたって、もっとも困難な課題の一つは開発環境の再現性を担保することです。 開発チームのメンバーは、それぞれが固有の経験と知識を持っていますし、プロジェクトに参画する際の契約が異なることも多いでしょう。全てのメンバーが、単一のプロジェクトに使いうる全ての 工数 を使ってプロジェクトに貢献できるわけではありません。人によっては、複数のプロジェクトを掛け持ちしていることはあります。 ある開発メンバーは慣れている Mac を使いたいと考える時、違うメンバーは会社から標準的に貸与される Windows で開発したいと考えるかもしれません。しかし、アプリケーションのデプロイ先は Ubuntu や Debian といった Linux だったりします。 こういった状況では、特定のメンバーでのみ発生する不具合が存在したり、または特定のメンバーのローカル環境でしかアプリケーションが動作しないといった事が起こります。 原因が明らかになれば、単にPATH 環境変数 の違いのような簡単なことかもしれませんが、その過程は往々にして困難なものになります。そういった細かい環境差異を原因とする問題の調査はシニアなメンバーにしかできないことが多いのです。 しかし、その調査の時間は明らかに無駄ですし、ほぼ何の価値もありません。 付加価値の高いシニアなメンバーの 工数 を、そういった調査で浪費することはプロジェクトにとって望ましくないでしょう。 この記事で紹介する手法では、Dockerベースのコンテナ技術を使うことで、メンバー毎の環境差分をできるだけ小さくできます。ハードウェアスペックやネットワークに起因するもの以外は差分が全く存在しなくなると言っても良いでしょう。つまり、開発メンバーのなかで誰かのマシンで起きた問題は、メンバー全員のマシンで再現します。 気になってきましたか?それでは、Dev Containerを使った開発環境構築について説明を始めます。 事前の準備 この記事が前提とする環境について軽く説明します。 まず、 VS Code を事前にインストールしておいてください。 次に、 Docker Desktop をインストールして動作する状態にしてください。基本的には単に インストーラ を実行すれば動作する状態になります。 そして、 VS Code に Dev Containers 拡張をインストールしておいてください。 最後に、作業用のプロジェクト ディレクト リを作成してください。ここでは、 devcontainer-python という ディレクト リを作成してプロジェクトのルート ディレクト リとしています。 最小限のDev Container まずは、Dev Containerで公式に提供されている Python の開発環境を導入してみましょう。 プロジェクトのルート ディレクト リに、 .devcontainer という ディレクト リを作って、その中に devcontainer.json というファイル名で以下の内容を保存します。 { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] } name の値は、分かりやすい名前なら何でもいいです。ここでは、devcontainer- python としています。 image の値は、mcr. microsoft .com/devcontainers/ python :3.12-bookworm としています。これは、公式のイメージ名です。 ベースイメージや Python ランタイムのバージョンを別なものにしたい場合には、 https://github.com/microsoft/vscode-dev-containers/tree/main/containers/python-3 から探してください。 containerEnv の値は、コンテナ内で参照される 環境変数 です。ここでは タイムゾーン が Asia/Tokyo になるよう設定しています。時刻に起因する問題の調査は難しいので、ここで明示的に設定しています。 runArgs の値として --init を渡すことで、Dockerが /dev/init というシグナルハンドリング用のプロセスを起動してくれます。これによってコンテナを安定的にシャットダウンできるようになります。 Dev Containerの起動 それでは、作ったDev Containerを起動してみましょう。 プロジェクトのルート ディレクト リを VS Code で開いた上で画面左端のアイコンをクリックしてREMOTE EXPLORER を表示します。 reopen the current folder in a container のリンクをクリックするとDev Containerの起動が始まります。 画面右下に、Dev Containerの起動が始まったことを通知するダイアログが数秒間だけ表示されるので、サッとクリックしましょう。 クリックすると起動ログが流れていく様子を観察できます。 起動ログの流れが落ち着いたら、ターミナルを起動してみましょう。ログの右上あたりにある + ボタンです。Ctrlキーと@キーを同時に押しても構いません。 以下のようにターミナルが表示されますね。 コンテナ内では vscode というユーザーで、 workspace/devcontainer-python という ディレクト リをカレント ディレクト リにしています。 ディレクト リパスの devcontainer-python 部分はプロジェクトのルート ディレクト リと同じになっているはずです。 devcontainer. json を編集する環境の構築 ここから、devcontainer. json を編集しながら開発環境を構築していくので、まずは快適に json ファイルを編集できるようにしましょう。 devcontainer. json には、Dev Containerとして起動した VS Code を構成するための設定項目がありますので、それらを編集します。 { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] , " customizations ": { " vscode ": { " settings ": { " editor.renderWhitespace ": " all ", " [json][jsonc] ": { " editor.defaultFormatter ": " esbenp.prettier-vscode ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": " explicit " } } } , " extensions ": [ " esbenp.prettier-vscode " ] } } } customizations というキーがDev Containerの構成を行うための設定項目です。この中に vscode という項目がありますね。 settings の中では、 VS Code の設定項目を管理します。 editor.renderWhitespace の値として、 all を設定しているのは、ファイルの中に紛れ込んだ全角スペースを見つけやすくするためです。私たちが IME を使っている以上、意図しない場所に全角スペースが入り込んでしまい、それによって理解が困難なエラーメッセージを読むことになるのは避けられません。全角スペースが見えていれば、そういったドハマりから抜け出しやすくなります。 [json][jsonc] の値として、いくつか設定しています。ちなみに、jsoncは、 JSON with commentsの略称です。 editor.defaultFormatter の値として、esbenp.prettier- vscode を設定しています。これによってprettierを使ったフォーマットが行われます。 editor.formatOnSave の値として、trueを設定することでファイル保存時にフォーマットが行われるようにしています。 editor.codeActionsOnSave の値として、source.fixAll に"explicit"を指定することで自動的に補正できるフォーマットエラーをprettierが積極的に補正してくれます。 extensions の中では、Dev Containerとして起動された VS Code にインストールされる VS Code 拡張を列挙します。ここでは、 JSON を自動フォーマットするための esbenp.prettier-vscode を設定しています。 最小限の Python 用 VS Code 拡張 次は、 Python 用の VS Code 拡張をいくつか追加していきましょう。 おすすめの拡張は、 Python Python Indent autoDocstring の三つです。他にも便利なものは多くありますが、特に議論の余地なく導入できるものはこれらです。 devcontainer. json のextensionsにこれらの拡張を追加すると、以下のようになります。 { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] , " customizations ": { " vscode ": { " settings ": { " editor.renderWhitespace ": " all ", " [json][jsonc] ": { " editor.defaultFormatter ": " esbenp.prettier-vscode ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": " explicit " } } } , " extensions ": [ " esbenp.prettier-vscode ", " ms-python.python ", " njpwerner.autodocstring ", " KevinRose.vsc-python-indent " ] } } } devcontainer. json を修正したら、忘れずにDev Containerをリビルドしましょう。 リビルドするには、REMOTE EXPLORER を表示して動作しているコンテナを右クリックします。 ここで表示される コンテキストメニュー から Rebuild Container を選択します。 これで、 VS Code を Python 用のエディタとして使うための準備は整ったと言えます。 しかしながら、アプリケーションの開発環境と呼ぶには、まだまだ不足がありますので順次整えていきましょう。 uvの導入 Python でアプリケーション開発を行うなら、標準ライブラリを使うだけでなく巨大なコミュニティ内で提供されるモジュールを利用して、その恩恵にあずかりましょう。 pipコマンドだけで OSS のモジュールをインストールするという ストロングス タイルも良いものですが、私が推奨するのはuvを使ったモジュール管理です。以前はPoetryを推奨していましたが、今はRustで実装されていて高速に動作するuvをお勧めしています。 Dev Containerには、featuresという機能がありdevcontainer. json を少し書き加えるだけでuvを使えます。 { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] , " features ": { " ghcr.io/jsburckhardt/devcontainer-features/uv:1 ": {} } , " customizations ": { " vscode ": { " settings ": { " editor.renderWhitespace ": " all ", " [json][jsonc] ": { " editor.defaultFormatter ": " esbenp.prettier-vscode ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": " explicit " } } } , " extensions ": [ " esbenp.prettier-vscode ", " ms-python.python ", " njpwerner.autodocstring ", " KevinRose.vsc-python-indent " ] } } } features の値として、 "ghcr.io/jsburckhardt/devcontainer-features/uv:1": {} が記述されていますね。 こうすることで、Dev Container起動時にuvがコンテナ内のゲストOSにグローバルインストールされるのです。 devcontainer. json を書き換えたらDev Containerをリビルドしましょう。 Python 仮想環境の構築 Dev Containerのリビルドから戻ってきたら、uvが使うプロジェクト構成ファイルを作りましょう。 プロジェクト構成ファイルの作成 プロジェクトのルート ディレクト リで、 uv init コマンドを実行するといくつかのファイルが作成されます。 特に重要なpyproject.tomlだけ抜粋します。 [project] name = "devcontainer-python" version = "0.1.0" description = "Add your description here" readme = "README.md" requires-python = ">=3.12" dependencies = [] このファイルを作る方法は色々ありますので、詳細を知りたい方はuvのドキュメントを参考にしてください。 Working on projects コンテナ作成時に動作する シェルスクリプト の追加 次は、コンテナをビルドした直後だけ動作する シェルスクリプト を追加します。 この シェルスクリプト を工夫するとコンテナ内で色んな作業をして、混乱状況になってもリビルドするだけで全てを元に戻せます。 まずは、簡単な シェルスクリプト から始めましょう。.devcontainer ディレクト リにpostCreateCommand.shというファイル名で以下の内容を保存します。このファイルの改行コードはLFにてください。 #!/bin/sh # postCreateCommand.sh echo "START Install" sudo chown -R vscode:vscode . echo "FINISH Install" 内容としては、プロジェクトのルート ディレクト リ以下にあるファイルや ディレクト リのオーナー権限を全て vscode ユーザーおよび vscode グループにするというものです。 以下のコマンドをターミナルで実行して実行権限を付与して下さい。 chmod +x .devcontainer/postCreateCommand.sh Dev Containerでは、ホストOS上にあるプロジェクトのルート ディレクト リを自動的にbindマウントしています。つまり、ゲストOSであるコンテナから見える既存のファイルや ディレクト リの権限がrootになってしまいます。Dev Container内で使うユーザーをrootにしても良いのですが、個人的には例えコンテナ内であったとしても普段使いするユーザーとしてrootを使いたくはありません。このような習慣を持つことで例えば、何か悪意のあるモジュールを誤ってインストールしてしまった時の被害を少しだけ低減できます。 便利な事にDev Containerが公式に提供しているコンテナイメージでは、 vscode ユーザーをsudoersとして登録しています。参考: common-debian.sh#L209-L213 この シェルスクリプト を動かすには、devcontainer. json にpostCreateCommandというキーで シェルスクリプト の ワークスペース からの 相対パス を設定します。 { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] , " features ": { " ghcr.io/jsburckhardt/devcontainer-features/uv:1 ": {} } , " postCreateCommand ": " ./.devcontainer/postCreateCommand.sh ", " customizations ": { " vscode ": { " settings ": { " editor.renderWhitespace ": " all ", " [json][jsonc] ": { " editor.defaultFormatter ": " esbenp.prettier-vscode ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": " explicit " } } } , " extensions ": [ " esbenp.prettier-vscode ", " ms-python.python ", " njpwerner.autodocstring ", " KevinRose.vsc-python-indent " ] } } } devcontainer. json を書き換えたのでDev Containerをリビルドしましょう。 コンテナ作成時に、postCreateCommand.shが動作するのを確認できます。 これは作成時しか動作しないので、例えば単に VS Code を再起動しても動作しません。つまり少々コストの高い処理を記述しても待つのは一度だけになります。 Python の仮想環境用ボリュームのマウント 次は、uvが作る Python の仮想環境について考えてみましょう。 要はプロジェクトのルート ディレクト リ以下に、作成される .venv ディレクト リをどう扱うかということです。 取りうる選択肢として最初の候補は特に気にせず .gitignore ファイルへ .venv ディレクト リを追加する、というやり方です。プロジェクトのルート ディレクト リは、Dev Containerによって既にbindマウントされているのだから、そのままにしておいてもそれほど大きな問題はありません。とはいえ、ホストOSでは実行 不能 な実行バイナリが直接 ファイルシステム 上に現れるのは、あまり気持ちよくはありません。 次の選択肢は、 .venv ディレクト リを特別扱いしてvolumeマウントすることです。これによって、ホストOS上に Python の仮想環境が直接現れなくなります。加えて、volumeマウントはbindマウントするよりもI/Oのパフォーマンスが少しだけ改善します。また、gitなどの構成管理ツールから明示的に除外しなくていいのも利点です。 volumeマウントをDev Containerに追加するには、devcontainer. json にmountsという項目の設定を追加します。 { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] , " features ": { " ghcr.io/jsburckhardt/devcontainer-features/uv:1 ": {} } , " postCreateCommand ": " ./.devcontainer/postCreateCommand.sh ", " mounts ": [ " source=venv-${devcontainerId},target=${containerWorkspaceFolder}/.venv,type=volume " ] , " customizations ": { " vscode ": { " settings ": { " editor.renderWhitespace ": " all ", " [json][jsonc] ": { " editor.defaultFormatter ": " esbenp.prettier-vscode ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": " explicit " } } } , " extensions ": [ " esbenp.prettier-vscode ", " ms-python.python ", " njpwerner.autodocstring ", " KevinRose.vsc-python-indent " ] } } } devcontainer. json では、設定値の中に ${ で始まり } で終わる部分があると、その中を変数として特別扱いします。 mountsの値だけを取り出してきたのがこれです。 "source=venv-${devcontainerId},target=${containerWorkspaceFolder}/.venv,type=volume" ここでは、 devcontainerId と containerWorkspaceFolder という変数が展開されてDockerの起動オプションに渡されます。それぞれにどんな値が入っているのかは、公式のマニュアルを確認してください。 https://containers.dev/implementors/json_reference/#variables-in-devcontainerjson プロジェクトローカルに仮想環境を作る 次は、いよいよ Python 仮想環境の構築です。と言ってもuvを使っているので極めて簡単です。 先ほど作った、postCreateCommand.sh にuv用のコマンドを2行を追加するだけです。 #!/bin/sh # postCreateCommand.sh echo "START Install" sudo chown -R vscode:vscode . uv venv --allow-existing uv sync echo "FINISH Install" まず、 uv venv --allow-existing コマンドを実行して仮想環境を作ります。 --allow-existing は既に.venv ディレクト リが存在する場合には、そのまま使うようにするオプションです。 uv venv コマンドが実行された時に既存の.venv ディレクト リが存在すると削除して再生成しようとするのですが、今回は .venv ディレクト リはボリュームマウントしているので削除できずにエラーになります。 もしここで uv venv --allow-existing --python 3.11 のように既にインストール済みの Python とは違ったバージョンの Python を指定すると自動的に実行バイナリをダウンロードしてきてくれます。 次の、 uv sync コマンドを実行するとpyproject.tomlに基づいて必要なライブラリやツールを自動的にインターネットからダウンロードしてくれます。 動作を確認するために、 シェルスクリプト の変更が終わったらDev Containerをリビルドしましょう。 さぁ、 Python を動かそう ここからは、いよいよ Python のコードを動かします。 ワークスペース のルート ディレクト リには uv init が作成した hello.py というファイルがあるはずです。 def main (): print ( "Hello from devcontainer-python!" ) if __name__ == "__main__" : main() 特別さのないコードですね。このファイルを開いた状態で VS Code の右下あたりに注目してください。 このような表示になっているなら、 Python の仮想環境に配置されている インタープリタ ーが使われています。 そうでない場合は赤く囲った内側をクリックしてください。そうすると、 インタープリタ ーを選択するダイアログが表示されるので、 .venv/bin/python というパスの インタープリタ ーをクリックすることで選択してください。 プロジェクト直下の.venv ディレクト リが VS Code に正しく認識された状態になると、ターミナルを起動した際、自動的にactivate スクリプト を実行してくれます。 これでuvで管理しているモジュールや実行バイナリが実行されるようになりました。 この状態を維持するために、devcontainer. json に python.defaultInterpreterPath という設定に ".venv/bin/python" を追加します。 設定追加後のdevcontainer. json は以下のようになります。 { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] , " features ": { " ghcr.io/jsburckhardt/devcontainer-features/uv:1 ": {} } , " postCreateCommand ": " ./.devcontainer/postCreateCommand.sh ", " mounts ": [ " source=venv-${devcontainerId},target=${containerWorkspaceFolder}/.venv,type=volume " ] , " customizations ": { " vscode ": { " settings ": { " editor.renderWhitespace ": " all ", " python.defaultInterpreterPath ": " .venv/bin/python ", " [json][jsonc] ": { " editor.defaultFormatter ": " esbenp.prettier-vscode ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": " explicit " } } } , " extensions ": [ " esbenp.prettier-vscode ", " ms-python.python ", " njpwerner.autodocstring ", " KevinRose.vsc-python-indent " ] } } } devcontainer. json を書き換えたらDev Containerをリビルドしましょう。 フォーマッタとLinterの導入 コードを実行できるようになったので、次はフォーマッタとLinterを導入しましょう。ターミナルを VS Code から起動して以下のコマンドを実行します。 uv add ruff --dev これによって、 Python 用のコードフォーマッタかつ、LinterであるRuffがインストールされます。 ruff これらを VS Code と連携するための設定と拡張を追加しましょう。 { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] , " features ": { " ghcr.io/jsburckhardt/devcontainer-features/uv:1 ": {} } , " postCreateCommand ": " ./.devcontainer/postCreateCommand.sh ", " mounts ": [ " source=venv-${devcontainerId},target=${containerWorkspaceFolder}/.venv,type=volume " ] , " customizations ": { " vscode ": { " settings ": { " editor.renderWhitespace ": " all ", " python.defaultInterpreterPath ": " .venv/bin/python ", " [python] ": { " editor.defaultFormatter ": " charliermarsh.ruff ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": " explicit ", " source.organizeImports ": " explicit " } } , " [json][jsonc] ": { " editor.defaultFormatter ": " esbenp.prettier-vscode ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": " explicit " } } } , " extensions ": [ " esbenp.prettier-vscode ", " ms-python.python ", " njpwerner.autodocstring ", " KevinRose.vsc-python-indent ", " charliermarsh.ruff " ] } } } ここでは、 以下のような変更を加えています。 [python] に設定を記述することでファイル保存時にフォーマットやLint、それに伴う自動補正が行われるようにしました。 charliermarsh.ruff を VS Code 拡張として追加しました。 RuffはBlackとの互換性のためにコードを折り返す際の基準とする文字数が 88 と異様に小さいのでここだけは設定を変更します。 Ruffの設定は、pyproject.tomlに記載します。 [project] name = "devcontainer-python" version = "0.1.0" description = "Add your description here" readme = "README.md" requires-python = ">=3.12" dependencies = [] [dependency-groups] dev = [ "ruff>=0.7.1", ] [tool.ruff] line-length = 200 ruffの設定を細かく調整することは少ないと思いますが、マニュアルはこちらです。 Configuring Ruff devcontainer. json を書き換えたのでDev Containerをリビルドですよね。 pytestの導入 コードを快適に書けるようになってきたので、次はテスティング フレームワーク の導入です。 Python には多くのテスティング フレームワーク がありますが、私が一番気に入っているのはpytestです。 uvを使ってpytestを導入しましょう。以下のコマンドを実行します。 uv add pytest --dev モジュールを追加したら VS Code の設定も変更します。 { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] , " features ": { " ghcr.io/jsburckhardt/devcontainer-features/uv:1 ": {} } , " postCreateCommand ": " ./.devcontainer/postCreateCommand.sh ", " mounts ": [ " source=venv-${devcontainerId},target=${containerWorkspaceFolder}/.venv,type=volume " ] , " customizations ": { " vscode ": { " settings ": { " editor.renderWhitespace ": " all ", " python.defaultInterpreterPath ": " .venv/bin/python ", " python.testing.pytestArgs ": [ " tests ", " --capture=tee-sys ", " -vv " ] , " python.testing.pytestEnabled ": true , " [python] ": { " editor.defaultFormatter ": " charliermarsh.ruff ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": " explicit ", " source.organizeImports ": " explicit " } } , " [json][jsonc] ": { " editor.defaultFormatter ": " esbenp.prettier-vscode ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": " explicit " } } } , " extensions ": [ " esbenp.prettier-vscode ", " ms-python.python ", " njpwerner.autodocstring ", " KevinRose.vsc-python-indent ", " charliermarsh.ruff " ] } } } ここで追加したのは、以下の二つです。 python.testing.pytestEnabled を trueにすることで VS Code がpytestを使ってテストコードを検索します。 python.testing.pytestArgs にはpytest起動時のオプションを三つ設定しています。 最初の tests はこの ディレクト リ内にあるテストコードを実行するという意味です。 次の --capture=tee-sys は、テストコード内で標準出力された内容をpytestがキャプチャしてターミナルに出力してくれます。 最後の -vv を付けることで、pytestがキャプチャした出力を途中で切らずに全て出力します。 テストコードの追加 テストコードを追加して動かしてみましょう。 ワークスペース のルート ディレクト リに tests という ディレクト リを作って、その中にtest_sample.pyというファイル名で以下の内容を保存します。 # content of test_sample.py def inc (x): return x + 1 def test_answer (): assert inc( 3 ) == 5 与えられた数字に1を加算する関数と、それをテストする関数です。 テストをターミナルから動かす まずは、テストをターミナルで動かしてみましょう。以下のコマンドを実行します。 pytest 案の定 アサーション が正しくないのでテストは失敗します。 テストを GUI から動かす 次は、 VS Code からテストを動かしてみましょう。 左側のメニューからフラスコのようなアイコンをクリックしてTESTINGビューを表示した上で右向きの三角をクリックするとテストを実行できます。もしくは、単にテスト関数の近くにある右向き三角でも構いません。 予想通りテストは失敗します。 テストをデバッガから動かす 次はテストを デバッグ 実行しましょう。コードを見てもどうしてテストが失敗するのか分からない時は、デバッガを使うと便利です。 まずは、 ブレークポイント を設定します。エディタのガッター部分をクリックすると赤い〇が付いて、そこが ブレークポイント になります。 TESTINGビューの虫アイコンがついたボタンを押して実行するとデバッガが動作します。 設定された ブレークポイント で止まると変数の中身や スタックトレース が確認できますね。 これで快適にテストが実行できるようになったので、ソフトウェア開発環境としては十分だと言えるかもしれません。 高品質なソフトウェアを作るために、もうひと踏ん張りしてみましょう。 テスト カバレッジ を計測する テスト カバレッジ を取ることで、テストコードが意図したとおりにアプリケーションコードをテストできているか確認できるようにしましょう。 テスト カバレッジ は100%を目指して ホワイトボックステスト するのに使うと極めて不毛な時間を過ごすことになります。 しかし、大体75%~85%を目途に意図したとおりにアプリケーションコードが動作しているかを確認するのに使うと非常に便利です。自分は仕様を完全に把握しているのだと思っても抜け漏れは少なからずあるものです。 pytest- cov の導入 pytestには、 Coverage.py を使ってテスト カバレッジ をとれる プラグイン があるので、それを導入しましょう。以下のコマンドを実行します。 uv add pytest- cov --dev これでpytestを実行する際に カバレッジ を取得するオプションが使えます。例えば、以下のコマンドで カバレッジ を取得できます。 pytest -- cov =. -- cov -report html このコマンドを実行後はプロジェクトのルート ディレクト リに htmlcov という ディレクト リが作成されて、その中にhtmlで作成された カバレッジ レポートが格納されています。 HTMLでそれなりにきれいな表示がされていて、ソフトウェア開発が主たる業務でない人にとっては十分なレポートだと言えます。 テスト カバレッジ の微調整 テスト カバレッジ を取り始めると、細かい調整が必要になっていきます。 私自身、それほど Python に詳しいわけではありませんが、実案件での利用を通じて発生した微調整をいくつかご紹介します。 実行時オプションの調整 pyproject.tomlに [tool.coverage.run] という項目を追加します。 [project] name = "devcontainer-python" version = "0.1.0" description = "Add your description here" readme = "README.md" requires-python = ">=3.12" dependencies = [] [dependency-groups] dev = [ "pytest-cov>=5.0.0", "pytest>=8.3.3", "ruff>=0.7.1", ] [tool.ruff] line-length = 200 [tool.coverage.run] branch = true source = ["tests"] omit = ["tests/fixtures/*"] data_file = ".pytest_cache/.coverage" 設定項目は四つです。 branch を有効化することでブランチ カバレッジ を取得するようにしています。これによって カバレッジ の計測コストが若干上がります。 source に カバレッジ の計測対象となるファイルが格納されている ディレクト リを指定しています。 omit では、逆に カバレッジ の計測対象としないファイルが格納されている ディレクト リを指定しています。 data_file では、 カバレッジ 計測データのバイナリファイルを格納する ディレクト リをプロジェクトのルート ディレクト リから.pytest_cache ディレクト リ内に移動することで、普段はその存在を気にしないで済むようにしています。 カバレッジ 除外の調整 ここでは、pyproject.tomlに [tool.coverage.report] という項目を追加して細粒度の構文レベルで カバレッジ 取得対象から ソースコード を除外しています。 [project] name = "devcontainer-python" version = "0.1.0" description = "Add your description here" readme = "README.md" requires-python = ">=3.12" dependencies = [] [dependency-groups] dev = [ "pytest-cov>=5.0.0", "pytest>=8.3.3", "ruff>=0.7.1", ] [tool.ruff] line-length = 200 [tool.coverage.run] branch = true source = ["tests"] omit = ["tests/fixtures/*"] data_file = ".pytest_cache/.coverage" [tool.coverage.report] exclude_lines = [ "pragma: no cover", "def __repr__", "def __str__", "raise AssertionError", "raise NotImplementedError", "if __name__ == .__main__.:", "if TYPE_CHECKING:", "if typing.TYPE_CHECKING:", ] それぞれの詳細については、ここでは説明しません。 VS Code に カバレッジ レポートを統合する コードを書いている プログラマー としては、 カバレッジ レポートは普段使っているエディタ上に表示されてほしいものです。レポートを見るためだけにウィンドウを切り替えるのはわずらわしいですからね。 というわけで、拡張の導入と設定です。コード カバレッジ を表示する VS Code 拡張はいくつかあるのですが、私が試した範囲内では、 Coverage Gutters が最も期待通りに動作しました。 Coverage Guttersは、Coverage.pyが出力した XML のレポートを入力情報として使いますので、pyproject.tomlにレポートの出力先を設定します。 [project] name = "devcontainer-python" version = "0.1.0" description = "Add your description here" readme = "README.md" requires-python = ">=3.12" dependencies = [] [dependency-groups] dev = [ "pytest-cov>=5.0.0", "pytest>=8.3.3", "ruff>=0.7.1", ] [tool.ruff] line-length = 200 [tool.coverage.run] branch = true source = ["tests"] omit = ["tests/fixtures/*"] data_file = ".pytest_cache/.coverage" [tool.coverage.report] exclude_lines = [ "pragma: no cover", "def __repr__", "def __str__", "raise AssertionError", "raise NotImplementedError", "if __name__ == .__main__.:", "if TYPE_CHECKING:", "if typing.TYPE_CHECKING:", ] [tool.coverage.xml] output = ".pytest_cache/coverage.xml" 最後の二行が追加した項目です。これによって、出力レポートのタイプとして XML を指定した際に、.pytest_cache/coverage. xml へファイルが出力されます。 次は、devcontainer. json を修正します。 { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] , " features ": { " ghcr.io/jsburckhardt/devcontainer-features/uv:1 ": {} } , " postCreateCommand ": " ./.devcontainer/postCreateCommand.sh ", " mounts ": [ " source=venv-${devcontainerId},target=${containerWorkspaceFolder}/.venv,type=volume " ] , " customizations ": { " vscode ": { " settings ": { " editor.renderWhitespace ": " all ", " python.defaultInterpreterPath ": " .venv/bin/python ", " python.testing.pytestArgs ": [ " tests ", " --capture=tee-sys ", " -vv " ] , " python.testing.pytestEnabled ": true , " [python] ": { " editor.defaultFormatter ": " charliermarsh.ruff ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": " explicit ", " source.organizeImports ": " explicit " } } , " coverage-gutters.showLineCoverage ": true , " coverage-gutters.showRulerCoverage ": true , " coverage-gutters.coverageFileNames ": [ " .pytest_cache/coverage.xml " ] , " [json][jsonc] ": { " editor.defaultFormatter ": " esbenp.prettier-vscode ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": " explicit " } } } , " extensions ": [ " esbenp.prettier-vscode ", " ms-python.python ", " njpwerner.autodocstring ", " KevinRose.vsc-python-indent ", " charliermarsh.ruff ", " ryanluker.vscode-coverage-gutters " ] } } } ここでは、三つの設定項目を追加すると共にインストールする拡張として ryanluker.vscode-coverage-gutters を追加しています。 coverage-gutters.showLineCoverage を有効化することで、行全体に色が付くようになります。 coverage-gutters.showRulerCoverage を有効化することで、行の左側にある目盛り部分に色が付くようになります。 coverage-gutters.coverageFileNames に設定しているパスと、pyproject.tomlが一致していることで、 カバレッジ レポートの結果を ryanluker.vscode-coverage-gutters が正しく処理できます。 devcontainer. json を書き換えたのでDev Containerをリビルドしましょう。 VS Code における カバレッジ レポートの確認方法 まずは、以下のコマンドを実行して カバレッジ レポートを作成します。 pytest -- cov =. -- cov -report xml 相変わらずテストは失敗していますね。しかし、 .pytest_cache/coverage.xml というファイルは出力されているはずです。これを使って カバレッジ を確認していきましょう。 VS Code の左下あたりに注目してください。 〇Watch という表示があるはずです。これをクリックすると カバレッジ レポートの表示が有効化されます。 カバレッジ レポートがエディタ上に表示されるとこのようになります。 これで、 カバレッジ レポートを確認しながらコードを書けるようになりました。 そろそろこの記事も終盤に差し掛かってきています。もう少しだけお付き合いください。 タ スクラン ナーの導入 最後は、プロジェクト構成ファイルであるpyproject.tomlに定型化された作業をタスクとして記述する方法を説明します。 長いコマンドでも構成ファイル内に書いてあればコマンドの実行ミスは無くなります。また、 GitHub ActionsのようなCIワークフローを構成する際にも、すでにタスクが定義されていれば非常に少ない 工数 で実現できます。 様々なタスク定義ツールがありますが、私が気に入って使っているのは、 Poe the Poet です。以下のコマンドを実行してインストールしましょう。 uv add poethepoet --dev インストールが終わったら、pyproject.tomlにここまで構成してきたタスクをいくつか書いてみましょう。 [project] name = "devcontainer-python" version = "0.1.0" description = "Add your description here" readme = "README.md" requires-python = ">=3.12" dependencies = [] [dependency-groups] dev = [ "poethepoet>=0.29.0", "pytest-cov>=5.0.0", "pytest>=8.3.3", "ruff>=0.7.1", ] [tool.ruff] line-length = 200 [tool.coverage.run] branch = true source = ["tests"] omit = ["tests/fixtures/*"] data_file = ".pytest_cache/.coverage" [tool.coverage.report] exclude_lines = [ "pragma: no cover", "def __repr__", "def __str__", "raise AssertionError", "raise NotImplementedError", "if __name__ == .__main__.:", "if TYPE_CHECKING:", "if typing.TYPE_CHECKING:", ] [tool.coverage.xml] output = ".pytest_cache/coverage.xml" [tool.poe.tasks] lint = "ruff check ." test = "pytest" cover = "pytest --cov=. --cov-report xml" fmt = "ruff format . --check" build = ["fmt", "lint", "test"] [tool.poe.tasks] 以下に書かれているものが実行可能なタスクです。ここでは、五つのタスクを定義しています。 lint タスクでは、 Ruffによるコードの検査を実行します。 testタスクでは、pytestを実行します。 coverタスクでは、コード カバレッジ を取得しながらpytestを実行します。 fmtタスクでは、Ruffによるコードの整形を実行します。 buildタスクでは、 fmtタスクを実行した後にlintタスクを実行し最後にtestタスクを実行します。 これらのタスクは、 poe コマンドから実行できます。例えば、lintタスクを実行する際には、以下のようなコマンドを実行します。 poe lint 非常に簡単ですね。testタスクのように内部的にはコマンドを引数なしで実行しているだけでもタスクとして定義しているのは、ツールの移行コストを下げるためです。 例えば、今回はlinterとしてRuffを使っていますが、使い込む過程で回避しようのない不具合が見つかりFlake8のような実績のあるツールに切り戻すことはありえます。そういった時にCIやCDのワークフローに対する影響をできるかぎり減らして移行できるようにするには、タ スクラン ナーによるコマンドの抽象化が有効です。 uvでのタ スクラン ナー poethepoetのような追加のライブラリ無しにuvだけで動作するタ スクラン ナーについて議論しているチケットがあります。 Using uv run as a task runner これが実装されれば、poethepoet のインストールは不要になるかもしれませんね。 まとめ ここまで、Dev Containerで Python アプリケーションの開発環境を構築する方法について説明してきました。 プロジェクトメンバーができるかぎり同じ環境でアプリケーション開発を行うことは、浪費される 工数 を減らしプロジェクトとして価値のある作業に集中するために必要な事です。 この記事では Python 開発環境を扱いましたが、同様の考え方でTypeScriptや、Rust、 Ruby 、 Java といった他の言語の開発環境を構築できます。 また、 GitHub Codespacesのような クラウド 開発環境の利用も難なくできます。 作っているアプリケーションの種類や、プロジェクトチーム内での役割次第ではブラウザ一つ動く環境さえあればソフトウェア開発できるというのは、非常に魅力的ですよね。 ここまで読んでいただいた皆さん、本当にお疲れさまでした。この記事を読んだ皆さんが、利便性の高い開発環境で本来のソフトウェア開発に集中できることを願って記事の結びとします。 この記事で紹介している開発環境の構成ファイル 最後に作った構成ファイルをまとめて紹介します。 .devcontainer/devcontainer. json { " name ": " devcontainer-python ", " image ": " mcr.microsoft.com/devcontainers/python:3.12-bookworm ", " containerEnv ": { " TZ ": " Asia/Tokyo " } , " runArgs ": [ " --init " ] , " features ": { " ghcr.io/jsburckhardt/devcontainer-features/uv:1 ": {} } , " postCreateCommand ": " ./.devcontainer/postCreateCommand.sh ", " mounts ": [ " source=venv-${devcontainerId},target=${containerWorkspaceFolder}/.venv,type=volume " ] , " customizations ": { " vscode ": { " settings ": { " editor.renderWhitespace ": " all ", " python.defaultInterpreterPath ": " .venv/bin/python ", " python.testing.pytestArgs ": [ " tests ", " --capture=tee-sys ", " -vv " ] , " python.testing.pytestEnabled ": true , " [python] ": { " editor.defaultFormatter ": " charliermarsh.ruff ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": " explicit ", " source.organizeImports ": " explicit " } } , " coverage-gutters.showLineCoverage ": true , " coverage-gutters.showRulerCoverage ": true , " coverage-gutters.coverageFileNames ": [ " .pytest_cache/coverage.xml " ] , " [json][jsonc] ": { " editor.defaultFormatter ": " esbenp.prettier-vscode ", " editor.formatOnSave ": true , " editor.codeActionsOnSave ": { " source.fixAll ": " explicit " } } } , " extensions ": [ " esbenp.prettier-vscode ", " ms-python.python ", " njpwerner.autodocstring ", " KevinRose.vsc-python-indent ", " charliermarsh.ruff ", " ryanluker.vscode-coverage-gutters " ] } } } .devcontainer/postCreateCommand.sh 改行コードはLFです。実行権限の付与を忘れずに。 #!/bin/sh # postCreateCommand.sh echo "START Install" sudo chown -R vscode:vscode . uv venv --allow-existing uv sync echo "FINISH Install" .gitignore 改行コードはLFです。 # Python-generated files __pycache__/ *.py[oc] build/ dist/ wheels/ *.egg-info # Virtual environments .venv *_cache pyproject.toml [project] name = "devcontainer-python" version = "0.1.0" description = "Add your description here" readme = "README.md" requires-python = ">=3.12" dependencies = [] [dependency-groups] dev = [ "poethepoet>=0.29.0", "pytest-cov>=5.0.0", "pytest>=8.3.3", "ruff>=0.7.1", ] [tool.ruff] line-length = 200 [tool.coverage.run] branch = true source = ["tests"] omit = ["tests/fixtures/*"] data_file = ".pytest_cache/.coverage" [tool.coverage.report] exclude_lines = [ "pragma: no cover", "def __repr__", "def __str__", "raise AssertionError", "raise NotImplementedError", "if __name__ == .__main__.:", "if TYPE_CHECKING:", "if typing.TYPE_CHECKING:", ] [tool.coverage.xml] output = ".pytest_cache/coverage.xml" [tool.poe.tasks] lint = "ruff check ." test = "pytest" cover = "pytest --cov=. --cov-report xml" fmt = "ruff format . --check" build = ["fmt", "lint", "test"] 執筆: @sato.taichi 、レビュー: @mizuno.kazuhiro ( Shodo で執筆されました )
アバター