ARM64のDockerイメージのビルドでyarn installがエラーになる

AWSのFargateがGraviton2に対応したので、dockerコンテナイメージをARM64プラットフォーム版でビルドしてみたら失敗したので調査してみました。


現象

  • Dockerfile内でyarn installするアプリケーションコンテナで、マルチアーキテクチャ対応イメージをARM64用にビルドをするとエラーになる。


前提

  • x86_64上でビルドする。
  • 普段はx86_64用にビルドをしているものをARM64用にビルドする。
  • Dockerfile内でpackage.jsonをもとにyarn installする。


環境

ビルド環境

$ uname -m 
x86_64
  • Docker Desktop for Mac
    • v3.6.0
  • Docker
    • v20.10.8


ゲスト(コンテナ)環境

  • イメージ
    • node:14.16.1
  • yarn
    • v1.22.5
  • Dockerfile(サンプル)
FROM node:14.16.1
COPY package.json yarn.lock ./
RUN yarn install --non-interactive --frozen-lockfile

package.json(サンプル)

{
  "name": "test",
  "version": "0.0.1",
  "description": "",
  "author": "",
  "private": true,
  "license": "UNLICENSED",
  "dependencies": {
    "@apollo/gateway": "^0.30.0",
    "apollo-server-express": "^2.25.2",
    "class-transformer": "^0.4.0",
    "class-validator": "^0.13.1",
    "date-fns": "^2.17.0",
    "date-fns-tz": "^1.1.3",
    "reflect-metadata": "^0.1.13",
    "rimraf": "^3.0.2",
    "rxjs": "^7.2.0"
  },
  "devDependencies": {
    "@types/express": "^4.17.13",
    "@types/jest": "^26.0.24",
    "@types/node": "^16.0.0",
    "@types/supertest": "^2.0.11",
    "@typescript-eslint/eslint-plugin": "^4.28.2",
    "@typescript-eslint/parser": "^4.28.2",
    "dotenv": "^10.0.0",
    "eslint": "^7.30.0",
    "eslint-config-prettier": "^8.3.0",
    "eslint-plugin-filenames": "^1.3.2",
    "eslint-plugin-import": "^2.23.4",
    "eslint-plugin-jest": "^24.3.6",
    "jest": "^27.0.6",
    "npm-run-all": "^4.1.5",
    "prettier": "^2.3.2",
    "serverless": "2.34.0",
    "supertest": "^6.1.3",
    "ts-jest": "^27.0.3",
    "ts-loader": "^9.2.3",
    "ts-node": "^10.0.0",
    "tsconfig-paths": "^3.10.1",
    "typescript": "^4.3.5"
  }
}


現象

x86_64版ビルド

普通にビルドします。

$ docker build -t testtag . 
[+] Building 88.8s (9/9) FINISHED                                                                    
 => [internal] load build definition from Dockerfile                                            0.0s
 => => transferring dockerfile: 614B                                                            0.0s
 => [internal] load .dockerignore                                                               0.0s
 => => transferring context: 2B                                                                 0.0s
 => [internal] load metadata for docker.io/library/node:14.16.1                                 1.9s
 => [auth] library/node:pull token for registry-1.docker.io                                     0.0s
 => [internal] load build context                                                               0.0s
 => => transferring context: 1.28kB                                                             0.0s
 => CACHED [1/3] FROM docker.io/library/node:14.16.1@sha256:e77e35d3b873500c10ce8969fe2ce5e090  0.0s
 => [2/3] COPY package.json yarn.lock ./                                                        0.1s
 => [3/3] RUN yarn install --non-interactive --frozen-lockfile                                                   63.4s
 => exporting to image                                                                         23.2s 
 => => exporting layers                                                                        23.2s 
 => => writing image sha256:6983027cb91d3f013454d5fc620c531b71b8c3cb67c35ce9287cf507d13d84e8    0.0s 
 => => naming to docker.io/library/testtag                                                      0.0s 
                                                                                                     
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them 


ARM64版ビルド

--platform linux/arm64をつけてビルドします。

$ docker build -t testtag . --platform linux/arm64
[+] Building 238.3s (7/7) FINISHED                                                                   
 => [internal] load build definition from Dockerfile                                            0.0s
 => => transferring dockerfile: 460B                                                            0.0s
 => [internal] load .dockerignore                                                               0.0s
 => => transferring context: 2B                                                                 0.0s
 => [internal] load metadata for docker.io/library/node:14.16.1                                 0.8s
 => [internal] load build context                                                               0.0s
 => => transferring context: 111B                                                               0.0s
 => CACHED [1/3] FROM docker.io/library/node:14.16.1@sha256:e77e35d3b873500c10ce8969fe2ce5e090  0.0s
 => [2/3] COPY package.json yarn.lock ./                                                        0.0s
 => ERROR [3/3] RUN yarn install --non-interactive --frozen-lockfile                                            237.2s
------                                                                                               
 > [3/3] RUN yarn install --non-interactive --frozen-lockfile:                                                         
#5 2.494 yarn install v1.22.5                                                                        
#5 3.809 [1/4] Resolving packages...                                                                 
#5 8.715 [2/4] Fetching packages...                                                                  
#5 71.50 info There appears to be trouble with your network connection. Retrying...                  
#5 75.79 info There appears to be trouble with your network connection. Retrying...
#5 104.7 info There appears to be trouble with your network connection. Retrying...
#5 109.0 info There appears to be trouble with your network connection. Retrying...
#5 137.9 info There appears to be trouble with your network connection. Retrying...
#5 142.1 info There appears to be trouble with your network connection. Retrying...
#5 171.0 info There appears to be trouble with your network connection. Retrying...
#5 175.2 info There appears to be trouble with your network connection. Retrying...
#5 185.5 info There appears to be trouble with your network connection. Retrying...
#5 207.3 error An unexpected error occurred: "https://registry.yarnpkg.com/date-fns/-/date-fns-2.26.0.tgz: ESOCKETTIMEDOUT".
#5 207.3 info If you think this is a bug, please open a bug report with the information provided in "/yarn-error.log".
#5 207.3 info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
#5 218.8 info There appears to be trouble with your network connection. Retrying...
------
executor failed running [/bin/sh -c yarn install --non-interactive --frozen-lockfile]: exit code: 1


ARM64の方がyarn installに時間がかかっていて、何度もコネクション確立を試みてリトライし、ESOCKETTIMEDOUTエラーとなっているようです。

特定のモジュールのインストールだけで起きているわけではなく、他のモジュールで同じエラーが起きることも確認しています。


対応

yarn installのタイムアウトを伸ばす(2通り)


コマンドオプション

yarnコマンドに--network-timeoutオプションをつける。

yarn install --network-timeout 100000


オプションファイル

.yarnrcファイルを作成し、network-timeoutオプションを記入する。

$ cat .yarnrc

network-timeout 100000


結果

  • Dockerfile(network-timeout指定)
FROM node:14.16.1
COPY package.json yarn.lock ./
RUN yarn install --network-timeout 100000 --non-interactive --frozen-lockfile


  • ビルド成功
docker build -t testtag . --platform linux/arm64
[+] Building 333.5s (9/9) FINISHED                                                                   
 => [internal] load build definition from Dockerfile                                            0.0s
 => => transferring dockerfile: 614B                                                            0.0s
 => [internal] load .dockerignore                                                               0.0s
 => => transferring context: 2B                                                                 0.0s
 => [internal] load metadata for docker.io/library/node:14.16.1                                 1.9s
 => [auth] library/node:pull token for registry-1.docker.io                                     0.0s
 => [internal] load build context                                                               0.0s
 => => transferring context: 111B                                                               0.0s
 => [1/3] FROM docker.io/library/node:14.16.1@sha256:e77e35d3b873500c10ce8969fe2ce5e0901516f77  0.0s
 => CACHED [2/3] COPY package.json yarn.lock ./                                                 0.0s
 => [3/3] RUN yarn install --network-timeout 100000 --non-interactive --frozen-lockfile                         300.1s
 => exporting to image                                                                         31.3s 
 => => exporting layers                                                                        31.3s 
 => => writing image sha256:20a65a0851b80c6df967e955ec6d8df51e99538cfb4fef919bf612c37efafbc8    0.0s 
 => => naming to docker.io/library/testtag                                                      0.0s 
                                                                                                     
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them


x86_64と比べると変わらず時間はかかっていますが、成功しました。


補足


最後に

ECS FargateなどでもGraviton2(ARM64)対応したので早速使いたいところですが、まだ怖い面もありますね。上記の対応で良いのか、根本的な解決になっていない気も・・・