![](/img/trans.png)
[英]Docker buildx with node app on Apple M1 Silicon - standard_init_linux.go:211: exec user process caused "exec format error
[英]ECS Fargate task failing to start: "standard_init_linux.go:228: exec user process caused: exec format error" even when built for amd64
我的带有 Fargate 任务的 CDK 堆栈无法启动,任务直接停止并出现错误:
“standard_init_linux.go:228: exec 用户进程导致:exec 格式错误”
我知道此错误通常是由于 Docker 映像不适用于正确的 CPU 架构或某些格式错误的 shell 脚本,因此已采取措施解决此问题。
我的 Docker 镜像是一个 nodejs express 服务器,我已经在我的 MacOs M1 机器上构建了它。 我已经构建了图像多架构(amd64 和 arm)以及 amd64。
我有一个手动 AWS 控制台在另一个 AWS 账户中的 ALB 后面创建了 Fargare 服务,它模仿了我试图用 CDK 做的事情。 我在其他 AWS 账户 ECS 存储库中有相同的 Docker 映像,我的任务在那里工作。
因此,我得出结论,这不是 Docker 映像本身,而是与任务定义有关的东西。
有什么问题?
这是我的 CDK 堆栈:
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as ecr from 'aws-cdk-lib/aws-ecr';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ecsp from 'aws-cdk-lib/aws-ecs-patterns';
export class HelloEcsStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const serviceName = 'my-backend';
const servicePort = 5432;
const vpc = new ec2.Vpc(this, "MyVpc", {
maxAzs: 2
});
const cluster = new ecs.Cluster(this, "BackendCluster", {
vpc: vpc
});
const load_balanced_fargate_service = new ecsp.ApplicationLoadBalancedFargateService(this, 'Backend', {
cluster: cluster,
taskImageOptions: {
image: ecs.ContainerImage.fromEcrRepository(
ecr.Repository.fromRepositoryName(this, id, 'backend-container-repo')
),
containerPort: servicePort,
environment: {
// some key values our backend needs
}
},
listenerPort: servicePort,
publicLoadBalancer: true
});
load_balanced_fargate_service.targetGroup.configureHealthCheck({
port: `${servicePort}`,
path: '/api/health'
});
}
}
我在手册中的任务定义 JSON 和 CDK 变体之间的唯一区别是:
手动:任务内存和CPU更大(2048/1024)
光盘:
"runtimePlatform": null,
手动的:
"runtimePlatform": {
"operatingSystemFamily": "LINUX",
"cpuArchitecture": null
},
还有一些值,CDK 的数组为空,而手动任务 def 中的值为 null。 不确定这是否重要。 示例:手册:“entryPoint”:null,CDK:“entryPoint”:[],
为了完整起见,这是我的图像 Dockerfile:
# --------------> The build image
FROM node:latest AS build
WORKDIR /usr/src/app
COPY package*.json /usr/src/app/
RUN npm ci --only=production
# --------------> The production image
FROM node:lts-alpine
RUN apk add dumb-init
ENV NODE_ENV production
USER node
WORKDIR /usr/src/app
COPY --chown=node:node --from=build /usr/src/app/node_modules /usr/src/app/node_modules
COPY --chown=node:node . /usr/src/app
# Setup backend port (default can be overridden by --build-arg PORT <port value>)
ARG PORT=5432
ENV PORT=$PORT
EXPOSE $PORT
RUN echo
CMD ["dumb-init", "node", "server.js"]
毕竟它实际上是图像。
我的问题是我首先在本地构建了一个图像,但是在部署时我使用了一个 shell 脚本。 该脚本没有正确标记图像,因此实际推送的图像是旧图像(架构错误)。 通过在本地清除我的 docker 映像和容器发现了这一点,即使在构建后运行脚本时也会出错。
更正后的构建和部署脚本现在如下:
#!/bin/bash
if [ -z "$1" ]
then
echo "Please provide all parameters"
echo "usage: ./docker_deploy.sh <AWS account profile> <AWS region>"
exit 1
fi
if [ -z "$2" ]
then
echo "Please provide all parameters"
echo "usage: ./docker_deploy.sh <AWS account profile> <AWS region>"
exit 1
fi
PROFILE="$1"
REGION="$2"
export AWS_PROFILE=$PROFILE
export AWS_REGION=$REGION
REPO_NAME=your-repo
if aws ecr describe-repositories --repository-names ${REPO_NAME} >/dev/null ; then
echo "ECR repository exists"
else
echo "ECR repository doest not exist, creating..."
aws ecr create-repository --repository-name ${REPO_NAME} >/dev/null
fi
REPO_URI=`aws ecr describe-repositories --repository-names ${REPO_NAME} | jq -r '.repositories[].repositoryUri | match( "([^/]*)" ).string'`
set -e # fail script on any individual command failing
aws ecr get-login-password --profile ${PROFILE} --region ${REGION} | docker login --username AWS --password-stdin ${REPO_URI}
docker build --platform=linux/amd64 -t ${REPO_NAME} .
docker tag ${REPO_NAME}:latest ${REPO_URI}/${REPO_NAME}:latest
docker push ${REPO_URI}/${REPO_NAME}:latest
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.