📘

devcontainer内からCDKを使ってECRにコンテナPushしたときにハマったこと

2023/02/23に公開

概要

VSCodeのdevcontainerからDockerfileをBuildしたImageをECRにPushするときに以下のエラーがでました。

vscode@localhost:~/cdk-handson$ cdk deploy --all

✨  Synthesis time: 4.11s

CdkHandsonStack: building assets...

[0%] start: Building b8a1e2e11f10eeafcbf21867255bfd40ead35f9ea3d06e98b24bb50fdb411ff7:current_account-ap-northeast-1
[0%] start: Building 4f8e17a6a5361072081d3ad7b48a1dd5c030fc1d17582cb5bf1f33e76b346129:current_account-ap-northeast-1
[50%] success: Built b8a1e2e11f10eeafcbf21867255bfd40ead35f9ea3d06e98b24bb50fdb411ff7:current_account-ap-northeast-1
[100%] fail: docker login --username AWS --password-stdin https://xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com exited with error code 1: Error saving credentials: error storing credentials - err: exit status 255, out: ``

 ❌ Building assets failed: Error: Building Assets Failed: Error: Failed to build one or more assets. See the error messages above for more information.
    at buildAllStackAssets (/usr/lib/node_modules/aws-cdk/lib/index.js:347:116743)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async CdkToolkit.deploy (/usr/lib/node_modules/aws-cdk/lib/index.js:347:142824)
    at async exec4 (/usr/lib/node_modules/aws-cdk/lib/index.js:402:51795)

Building Assets Failed: Error: Failed to build one or more assets. See the error messages above for more information.

エラーとしてはError saving credentials: error storing credentials - err: exit status 255, out: `` の部分ですが、status 255, で探してもなかなか見つからなかったので調べた事残します。

さきに結論

~/.docker/config.jsonをファイルごと削除すれば解決しました。

環境

  • VSCode
  • devcontainer (ubuntu:20.04)
  • AWS CLI (aws-cli/2.10.1 Python/3.9.11 Linux/5.15.0-60-generic exe/x86_64.ubuntu.20 prompt/off)
  • AWS CDK (2.66.0 (build c96c17d))

やろうとしてたこと

CDKハンズオン中に作成したAPIをDockerfileでImageにしてECRにPushするコードを書きました。
こちらがそのコードです。

cdk-handson-stack.ts
export class CdkHandsonStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // DockerImageAssetを使って、DockerイメージをビルドしてECRにプッシュする
    const imageAsset = new DockerImageAsset(this, "ImageAsset", {
      directory: path.join(__dirname, "../api"),
    });
  }
}

../apiと書いてある所にdocker-compose.ymlDockerfileが置いてありCDKのコマンドを実行すると、
DockerfileがBuildされてImageになりECRへのPushまでをしてくれます。
その途中で概要に記載したエラーが発生しました。

原因

結局はこれでした。
https://qiita.com/P2eFR6RU/items/180d6de4c52f36b7adc0

エラーのステータスが違うしメッセージも違ったので、statsuが255のケースがないか探したのですが見つからず。
試しにこちらの対応方法同様に~/.docker/config.jsonを消してみたらECRへのPushがされました。

~/.docker/config.jsonの中身はこんな感じで、devcontainerをImageからビルドすると最初からあるファイルでした。

config.json
{
        "credsStore": "dev-containers-29b859a36c8babaa3cdadfe9c3a7592a6694bfe8"
}

credsStoreは外部の証明書保存先を指定できますが、devcontainerが作った保存先なので実在しません。
ですが設定があると、指定先を見に行ってなければエラーにしてしまいます。
なので、今回は対応として~/.docker/config.jsonを削除しました。

削除してから再度デプロイ

削除後にcdk deploy CdkHandsonStackを実行した結果が以下のとおりです。

vscode@localhost:~/cdk-handson$ rm ~/.docker/config.json
vscode@localhost:~/cdk-handson$ cdk deploy CdkHandsonStack

✨  Synthesis time: 5.8s

CdkHandsonStack: building assets...

[0%] start: Building 82a2352830029b80d8d977b338d860d89b19c26b250c5681623da0855cc41a14:current_account-ap-northeast-1
[0%] start: Building 4f8e17a6a5361072081d3ad7b48a1dd5c030fc1d17582cb5bf1f33e76b346129:current_account-ap-northeast-1
[50%] success: Built 82a2352830029b80d8d977b338d860d89b19c26b250c5681623da0855cc41a14:current_account-ap-northeast-1
#1 [internal] load build definition from Dockerfile
#1 sha256:b474dd9816429f08e4d05e9ac8be5f1445844008bc2c276598e0d606b593a49e
#1 transferring dockerfile: 357B done
#1 DONE 0.0s

#2 [internal] load .dockerignore
#2 sha256:1517c87842490e024d74913086479c3957d524af47af35f19031a6394a25ac72
#2 transferring context: 2B done
#2 DONE 0.0s

#3 [internal] load metadata for docker.io/library/python:3.10
#3 sha256:c787ec5cc33e1cbee663ba2529b5d51f0293f2c277b40d9bd37129383a68d5ac
#3 DONE 2.8s

#7 [internal] load build context
#7 sha256:972950c4798ae5be1929b177a9fbfa9fa29d282b8ff4d66c05161ba960b4330e
#7 transferring context: 2.13kB done
#7 DONE 0.0s

~~~~~~~~~~~~~

0b6859e9fff1: Pushed
4f8e17a6a5361072081d3ad7b48a1dd5c030fc1d17582cb5bf1f33e76b346129: digest: sha256:cc5378767efb44addf6dc0d5792004bee93f3cd14f7d26f5778d5df93541ca67 size: 3469
[100%] success: Published 4f8e17a6a5361072081d3ad7b48a1dd5c030fc1d17582cb5bf1f33e76b346129:current_account-ap-northeast-1
CdkHandsonStack: creating CloudFormation changeset...

 ✅  CdkHandsonStack

✨  Deployment time: 59.96s

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxxxx:stack/CdkHandsonStack/2cc24550-b2d9-11ed-aad6-0a43227e7817

✨  Total time: 65.76s

無事、ECRへのPushが出来ました!
Push後の~/.docker/config.jsonは以下のように、ECRへの認証情報を持つようになりました。

config.json
{
        "auths": {
                "xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com": {
                        "auth": "QVdTOmV5SndZWGxzYjJGa0lqb2ljVzlMYUZCMmVuRkVaa3hNVDAxRGVFcHFWMUZqVUVoSlp6STFOeXR~~~~~~~"
                }
        }
}

まとめ

今回はたまたまECRでしたが、Docker login時の認証情報をどこに見に行くかの問題なのでECRだけの問題ではないかもですね。
試してはいないですがDocker Hubとかでも同じ問題は起きるかも知れないです。

devcontainerからDockerが使えるようになるDocker in DockerDocker outside of Dockerが簡単にできるようになったため、
はじめてdevcontainer内でDockerfileをBuildしてContainer ImageをPushする機会が出来たので遭遇したハマりポイントでした!

参考記事

https://qiita.com/P2eFR6RU/items/180d6de4c52f36b7adc0

Discussion