WSl2 UbuntuでDockerを使うときにfailed to fetch metadataなるエラーが出る

問題

こんなエラーに遭遇。

failed to fetch metadata: fork/exec /usr/local/lib/docker/cli-plugins/docker-buildx: no such file or directory

DEPRECATED: The legacy builder is deprecated and will be removed in a future release.
            Install the buildx component to build images with BuildKit:
            https://docs.docker.com/go/buildx/

解決

おすすめのサイトからダウンロードページに飛び https://github.com/docker/buildx/releases 、環境にあったバイナリを取得して、/home/[自分のユーザー名]/.docker/cli-plugins/docker-buildxとして配置してやることで解決した。

mkdir ~/.docker/cli-plugins/
cd ~/.docker/cli-plugins/
wget https://github.com/docker/buildx/releases/download/v0.11.1/buildx-v0.11.1.linux-amd64
mv buildx-v0.11.1.linux-amd64 docker-buildx
chmod 755 docker-buildx

ChatGPT(4.0)にGithubActionsのワークフローを書いてもらった

Github Actionsのワークフローを一から作るの面倒くさい・・・AIに頼むか!」

というわけで頼んでみた。

Generate Github action workflow code. Specifications are as follows.

1. Build a Docker container from a Dockerfile (./docker/Dockerfile).
2. Push the container to AWS ECR. The repository that pushed container is `XXXXXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/development-mybook-api`.
3. Update AWS services to use containers stored in ECR repository

実際はXXXXXXXXXXXXXXXにAWSのアカウントIDを入れているのだが、さすがに公開するのはアレなのでマスクしている。 そして出力されたのがこちら。

name: Build and Push Docker image to AWS ECR and Update Services

on:
  push:
    branches:
      - master # Or the branch you want

env:
  AWS_REGION: ap-northeast-1
  ECR_REPOSITORY: XXXXXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/development-mybook-api

jobs:
  build-push:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v2

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ${{ env.AWS_REGION }}

    - name: Login to Amazon ECR
      id: login-ecr
      uses: aws-actions/amazon-ecr-login@v1

    - name: Build, tag, and push image to Amazon ECR
      id: build-image
      env:
        ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
        IMAGE_TAG: ${{ github.sha }}
      run: |
        docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG -f ./docker/Dockerfile .
        docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
        echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"

    - name: Fill in the new image ID in the Amazon ECS task definition
      id: task-def
      uses: aws-actions/amazon-ecs-render-task-definition@v1
      with:
        task-definition: task-definition.json
        container-name: mybook-api
        image: ${{ steps.build-image.outputs.image }}

    - name: Deploy Amazon ECS task definition
      uses: aws-actions/amazon-ecs-deploy-task-definition@v1
      with:
        task-definition: ${{ steps.task-def.outputs.task-definition }}
        service: mybook-api-service
        cluster: mybook-api-cluster
        force-new-deployment: true

そして提示された説明がこちら。「当然わかるよね」「とりあえずダミーを入れておいてくれればいいよ」的にこちらが飛ばした指定についても見事に補完してくれている。 欲を言えばactionが最新版だったりOIDCを使ってくれていたりすると尚よかったが、それは望みすぎだろう。

The workflow above does the following:

Checks out your repository.
Configures AWS credentials.
Logs in to ECR.
Builds the Docker image, tags it, and pushes it to your ECR repository.
Updates the ECS task definition with the new image ID.
Deploys the updated task definition.


Please replace task-definition.json, mybook-api-service, and mybook-api-cluster with your actual task definition, service, and cluster.

You also need to add your AWS credentials (AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY) to your GitHub repository secrets.

Remember to replace the event trigger and branches (on.push.branches) with the appropriate ones for your use case. In the example, the workflow is triggered when a push is made to the master branch.

Please ensure the GitHub Actions for AWS (aws-actions) are still supported and actively maintained as the Actions ecosystem evolves.

そのまま使うわけではなく、いくらか手を加えるものの、これをベースにして作業を進められるだけでも作業効率が段違いである。非常に助かる。

ChatGPTに栄養剤について記事を書いてもらった

ChatGPTの有料プランに加入したので、ものは試しに栄養剤について記事を書いてもらってみた。質問が次の通りで

栄養剤に関する記事を書いて

得られたのが下記の記事である。

タイトル: 栄養剤の利点と注意点:バランスの取れた食事との関係性を考える

イントロダクション:
現代の忙しいライフスタイルにおいて、栄養剤は多くの人々にとって便利な健康補助品となっています。栄養剤は、不足しがちな栄養素を補充し、健康維持や特定の健康目標の達成に役立つことが期待されています。しかし、栄養剤の利点と注意点を理解することは重要です。本記事では、栄養剤の利点や注意点について考えながら、バランスの取れた食事との関係性について探っていきます。

栄養剤の利点:
栄養素の補充: 繁忙な日常生活や特定の食事制限により、十分な栄養素を摂取することが難しい場合があります。栄養剤は、不足しがちなビタミン、ミネラル、タンパク質などの栄養素を手軽に補充する手段となります。
特定の健康目標の達成: スポーツパフォーマンスの向上、免疫力の強化、髪や爪の健康促進など、特定の健康目標に向けた栄養剤の摂取は有効です。特定の栄養素や成分が目的の達成に役立つ場合があります。
バランスの取れた食事との関係性:
栄養剤は補完的な役割を果たすべき: 栄養剤はバランスの取れた食事の代わりになるものではありません。食品から摂取できる多様な栄養素や食品の組み合わせによる相互作用は、健康に重要な要素です。栄養剤は食事の補完として摂取することが重要です。
過剰摂取に注意: 栄養剤は一度に大量に摂取することができますが、過剰摂取は健康リスクを引き起こす可能性があります。特に脂溶性ビタミンやミネラルの過剰摂取は中毒症状を引き起こすことがあります。適切な用量と指示に従うことが重要です。
栄養剤の選択と信頼性:
品質と信頼性の確認: 栄養剤の市場には様々な製品が存在しますが、品質や信頼性には差があります。信頼できる製造元や規制された製造プロセスを持つ製品を選ぶことが重要です。信頼できる情報源や専門家の助言を活用しましょう。
個別のニーズに合わせて選択: 個々の健康状態やニーズに基づいて栄養剤を選択することが重要です。特定の栄養素や成分が必要かどうか、アレルギーのリスクがあるかどうか、既存の薬との相互作用があるかどうかを考慮しましょう。
結論:
栄養剤は忙しい現代の生活において便利な健康補助品として利用されていますが、バランスの取れた食事との関係性を忘れずに考えることが重要です。栄養剤は食事の補完として摂取し、適切な用量と指示に従うことが必要です。信頼できる製品を選び、個々の健康状態やニーズに合わせた摂取を心がけましょう。最終的には、バランスの取れた食事と適度な運動が健康を維持するために重要な要素であることを忘れないでください。

見事なご卓見である。ここまで語れるのは人間でもなかなかいまい。

これが数秒で出てくるのだからコスパは人間の比ではない。もはやよほどの信頼性や専門性、新規性がないと、AIに比肩する価値を生み出すことは難しいのではないだろうか。

Stable Diffusion をインストールしてみた

Stable Diffusionをつかえば画像生成を自分のローカルPCでもできると知り、さっそく入れてみた。OSはWindows11。

# 手動でgitをインストール(まだないなら)
# 手動でpythonをインストール(3.10.x)
# git clone
git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git
# install
webui-user.bat

なんのカスタマイズもしていないが、それでも"Treasure Chest"で生成してみたら、なかなかの結果が出た。下図は実際の出力である。

20230710005001

雰囲気は十分出ている。悪くない。いや悪くないどころか、縮小すればゲームのアイコン素材にそのまま利用できるのではなかろうか。細かくみればツッコミを入れることはできるのだが、縮小すればわからなくなるだろう。

これが数秒でパッと出るのだからすごい。つくづくAIは便利だ。実に素晴らしい。

AWS構成図をAIに書かせてみた(PlantUML)

ChatGPTでAWSの構成図を作成するよう頼んでみた。

依頼文はまずこちら。 日本語にも対応すると聞くが、この手のものは拙くとも英語で聞いておくほうがよいと思うので、英語で書いた。日本語で書いてうまくいかなかったら、英語でないのがダメなのか、内容がダメなのか、どっちなのかわからなくなるので切り分けが面倒くさい。

Create an AWS diagram of `VPC network` using `Plantuml` with the following content.
- region is ap-northeast 1
- 3 az
- use s3 vpc endpoint
- using igw

そして生成されたのがこちら。

@startuml AWS Diagram - VPC Network

!define AWSPUML https://raw.githubusercontent.com/awslabs/aws-icons-for-plantuml/v14.0/dist

!define Region(ap-northeast-1, Asia Pacific (Tokyo))

!define AZ1(AZ1, Availability Zone 1)
!define AZ2(AZ2, Availability Zone 2)
!define AZ3(AZ3, Availability Zone 3)

!define IGW(IGW, Internet Gateway)

!define SubnetA(SubnetA, Subnet A)
!define SubnetB(SubnetB, Subnet B)
!define SubnetC(SubnetC, Subnet C)

!define EC2(EC2, EC2 Instance)

!define S3Endpoint(S3Endpoint, S3 VPC Endpoint)

!define Internet(Internet, Internet)

!define dashedline(linetype,direction) 
   skinparam linetype<<linetype>> dashed
   skinparam linetype<<linetype>><<direction>> false

!define linetype(linetype) 
   skinparam linetype<<linetype>> solid

!define direction(direction) 
   skinparam linetype<<linetype>><<direction>> true

!define showLink(link) 
   link <<link>>

!define endpointVisibility(visible) 
   hide circle
   hide stereotype

!define Network(network) 
   network <<Network>>

!define EC2Instance(ec2) 
   ec2 <<EC2Instance>>

!define AZGroup(group) 
   group <<AZGroup>>

!define Subnet(subnet) 
   subnet <<Subnet>>

!define SecurityGroup(securityGroup) 
   securityGroup <<SecurityGroup>>

!define Gateway(gateway) 
   gateway <<Gateway>>

!define Database(database) 
   database <<Database>>

!define Resource(resource) 
   resource <<Resource>>

!define User(user) 
   user <<User>>

!define loadIcon(alias,url) 
!define <<alias>>(<<alias>>)
!define ![[<<alias>>]](<<alias>>) 
   !define ![[<<alias>>]](alias) 
      skinparam componentStyle strictuml 
      sprite ${{alias}} $url 

!loadIcon(Region, AWSPUML/AWSCommon/Region)
!loadIcon(AZ1, AWSPUML/AWSCommon/AZ)
!loadIcon(AZ2, AWSPUML/AWSCommon/AZ)
!loadIcon(AZ3, AWSPUML/AWSCommon/AZ)
!loadIcon(IGW, AWSPUML/AWSNetworkingSecurity/InternetGateway)
!loadIcon(SubnetA, AWSPUML/AWSNetworkingSecurity/Subnet)
!loadIcon(SubnetB, AWSPUML/AWSNetworkingSecurity/Subnet)
!loadIcon(SubnetC, AWSPUML/AWSNetworkingSecurity/Subnet)
!loadIcon(EC2, AWSPUML/Compute/AmazonEC2Instance)
!loadIcon(S3Endpoint, AWSPUML/General/S3)

!define InternetEndpoint(InternetEndpoint, Internet Endpoint)
!define dashedline(dashed) 
!define linetype(solid) 
!define direction(undeclared) 
!define endpointVisibility(visible) 
!define showLink(link) 
!define Network(Network) 
!define EC2Instance(EC2Instance) 
!define AZGroup(AZGroup) 
!define Subnet(Subnet) 
!define SecurityGroup(SecurityGroup) 
!define Gateway(Gateway) 
!define Database(Database) 
!define Resource(Resource) 
!define User(User) 

Network(Network)

Region(ap-northeast-1) as APNE1 <<Region(ap-northeast-1)>> 
AZGroup(AZ1) as Zone1 <<AZGroup(AZ1)>> 
AZGroup(AZ2) as Zone2 <<AZGroup(AZ2)>> 
AZGroup(AZ3) as Zone3 <<AZGroup(AZ3)>> 

Internet(Internet) as Internet <<Internet>>

Gateway(IGW) as IGW <<Gateway(IGW)>>

Subnet(SubnetA) as ASubnet <<Subnet(SubnetA)>> 
Subnet(SubnetB) as BSubnet <<Subnet(SubnetB)>> 
Subnet(SubnetC) as CSubnet <<Subnet(SubnetC)>> 

EC2Instance(EC2) as InstanceA <<EC2Instance(EC2)>> 
EC2Instance(EC2) as InstanceB <<EC2Instance(EC2)>> 
EC2Instance(EC2) as InstanceC <<EC2Instance(EC2)>> 

Resource(S3Endpoint) as EndpointA <<Resource(S3Endpoint)>> 
Resource(S3Endpoint) as EndpointB <<Resource(S3Endpoint)>> 
Resource(S3Endpoint) as EndpointC <<Resource(S3Endpoint)>> 

APNE1 -- Zone1 
APNE1 -- Zone2 
APNE1 -- Zone3 

Zone1 -- IGW : <<IGW>>

Zone2 -- IGW : <<IGW>>

Zone3 -- IGW : <<IGW>>

Zone1 -- ASubnet : <<Subnet>>
Zone2 -- BSubnet : <<Subnet>>
Zone3 -- CSubnet : <<Subnet>>

ASubnet -- InstanceA : <<EC2Instance>>
BSubnet -- InstanceB : <<EC2Instance>>
CSubnet -- InstanceC : <<EC2Instance>>

ASubnet -- EndpointA : <<Resource>>
BSubnet -- EndpointB : <<Resource>>
CSubnet -- EndpointC : <<Resource>>

@enduml

自分が本当に必要だったもの


@startuml AWS Diagram

top to bottom direction
title AWS Diagram - VPC Network

!define AWSPuml https://raw.githubusercontent.com/awslabs/aws-icons-for-plantuml/v15.0/dist
' https://github.com/awslabs/aws-icons-for-plantuml/blob/main/AWSSymbols.md
!include AWSPuml/AWSCommon.puml
!include AWSPuml/Groups/AWSCloud.puml
!include AWSPuml/Groups/VPC.puml
!include AWSPuml/Groups/PublicSubnet.puml
!include AWSPuml/Groups/PrivateSubnet.puml
!include AWSPuml/Groups/AvailabilityZone.puml
!include AWSPuml/GroupIcons/Region.puml
!include AWSPuml/GroupIcons/VPCSubnetPrivate.puml
!include AWSPuml/NetworkingContentDelivery/VPCNATGateway.puml
!include AWSPuml/NetworkingContentDelivery/VPCInternetGateway.puml
!include AWSPuml/NetworkingContentDelivery/VPCEndpoints.puml

!include AWSPuml/AWSSimplified.puml


AWSCloudGroup(cloud) {
   Region("AWSRegion", "ap-northeast-1", "region") {
      VPCGroup(vpc, "VPC") {
         VPCInternetGateway(internet_gateway, "Internet gateway", "")
         VPCEndpoints(s3_endpoint, "S3 VPC Endpoint", "")

         AvailabilityZoneGroup("AZ1", "ap-northeast-1a") {
            PublicSubnetGroup(az_1_public, "Public subnet") {
               VPCNATGateway(az_1_nat_gateway, "NAT gateway", "")
            }

            PrivateSubnetGroup(az_1_private, "Private subnet") {
            }
         }

         AvailabilityZoneGroup("AZ2", "ap-northeast-1c") {
            PublicSubnetGroup(az_2_public, "Public subnet") {
            }
            PrivateSubnetGroup(az_2_private, "Private subnet") {
            }
         }

         AvailabilityZoneGroup("AZ3", "ap-northeast-1d") {
            PublicSubnetGroup(az_3_public, "Public subnet") {
            }

            PrivateSubnetGroup(az_3_private, "Private subnet") {
            }
         }
      }
   }
}

@enduml

残念ながらたたき台にもならなかった。PlantUMLでAWS構成図を書くのはマイナーすぎたのかもしれない。

しかし、うまくいくときはかなり素晴らしいたたき台を作ってくれるのがChatGPTだ。懲りずにどんどん試していこうと思う。

【terraform】Data Sourceを使うならModuleではなく呼び出し元で

Summary - 要旨

terraformのData Sourceを使うと外部リソースを参照できるためとても便利である。

が、moduleの中で直接呼ぶよりは、呼び出し元で呼ぶほうが使いまわしやすくてよさそうだ。

Detail - なんのこっちゃ

Data Sourceをmoduleの中で呼ぶと、それに依存したコードを書くことになると思う。

たとえばmoduleの中で以下のようにしていると

  1. dataで最新のAmazon Linux AMIのIDを得る
  2. そのAMIでEC2を立てる
data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]
  (省略)

}

resource "aws_instance" "example" {
  ami           = data.aws_ami.amazon_linux.id
  (省略)
}

後になって一部AmazonLinux以外を使いたいと思ったらmoduleを書き直さないといけなくなる。

が、variableで渡されていればmoduleをそのまま使いまわすことができる。

variable "ami_id" {}

resource "aws_instance" "example" {
  ami           = var.ami_id
  (省略)
}

Module内でData Sourceを呼ぶと外部に強く依存してしまうので、依存性の注入のようにvariableで渡したほうがモジュールの独立性が高まっていい、ということ。

MalformedPolicyDocumentが出たら記述の順番を厳正に守る

TerraformでIAM Policyを作っていたら、以下のエラーが出た。

MalformedPolicyDocument: The policy failed legacy parsing

なんのこっちゃと思ったら、Policyの記述順序が違っているのが原因だった。

どういうことか

まずは正しい例から示す。これが正しい順番。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AccessToLogBucket",
      "Action": "sts:AssumeRole",
      "Effect": "Allow",
      "Resource": "arn:aws:iam::${log_archive_account_id}:role/${log_backet_name}"
    }
  ]
}

そしてこれがダメな順番。何が違うかと言うと、EffectのほうがActionよりさきに来ている。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AccessToLogBucket",
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": "arn:aws:iam::${log_archive_account_id}:role/${log_backet_name}"
    }
  ]
}

jsonは順番など特に関係しないはずだが、IAM Policyはそうではないらしく、順番が違うとエラーを起こすことがあるようだ。初めて遭遇した。

しかもどういうわけかTerraformから実行するとダメで、コンソールから実行すると通るという謎の現象が起きていた。だから余計に原因が探りづらく頭を抱えたのである(そして頭を抱える羽目になったからわざわざ記事にしたのである)。

"MalformedPolicyDocument: The policy failed legacy parsing"が出たら、そんな馬鹿なと思っても、記述の順番を厳正に守ってみるといいかもしれない。