You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CloudFormation部署React应用至CloudFront遇源站连接失败求助

问题描述

尝试用CloudFormation栈将React应用从S3桶部署上线,访问CloudFront URL时出现如下错误:

ERROR
Failed to contact the origin.

以下是CloudFormation模板文件:

AWSTemplateFormatVersion: 2010-09-09
Parameters: 
  ProjectSource: 
    Type: String
    Default: "https://github.com/..."
    Description: "Source control URL (e.g. Github)"
  GithubOwner:
    Type: String
    Default: (myaccount)
  GithubRepo:
    Type: String
    Default: (myrepo)
  GithubOAuthToken:
    Type: String
    Default: "(my token)"
    Description: "Github personal access token"
  GithubBranch:
    Type: String
    Default: master
    Description: "e.g. master or main"
  
Resources:
  CodePipeline:
    Type: 'AWS::CodePipeline::Pipeline'
    Properties:
      RoleArn: !GetAtt CodePipeLineRole.Arn
      ArtifactStore:
        Location: !Ref PipelineBucket
        Type: S3
      Stages:
        - 
          Name: Source
          Actions: 
            - 
              Name: SourceAction
              ActionTypeId: 
                Category: Source
                Owner: ThirdParty
                Provider: GitHub
                Version: 1
              OutputArtifacts: 
                - 
                  Name: NameForOutput
              Configuration:
                Owner: !Ref GithubOwner
                Repo: !Ref GithubRepo
                Branch: !Ref GithubBranch
                OAuthToken: !Ref GithubOAuthToken
        - 
          Name: Build
          Actions: 
            - 
              Name: BuildAction
              ActionTypeId: 
                Category: Build
                Owner: AWS
                Version: 1
                Provider: CodeBuild
              InputArtifacts: 
                - 
                  Name: (NameHere)
              OutputArtifacts: 
                - 
                  Name: (NameBuild)
              Configuration:
                ProjectName: !Ref CodeBuild
  CodeBuildRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - 
            Effect: Allow
            Principal:
              Service:
                - "codebuild.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      Path: /service-role/
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: "2012-10-17"
            Statement: 
              - 
                Effect: Allow
                Action:
                  - "s3:GetObject"
                  - "s3:GetObjectVersion"
                  - "s3:GetBucketVersioning"
                  - "s3:PutObject"
                Resource: 
                  - !GetAtt PipelineBucket.Arn
                  - !Join ['', [!GetAtt PipelineBucket.Arn, "/*"]]
              - 
                Effect: Allow
                Action:
                  - "s3:GetObject"
                  - "s3:GetObjectVersion"
                  - "s3:GetBucketVersioning"
                  - "s3:PutObject"
                  - "s3:PutObjectAcl"
                Resource: 
                  - !GetAtt DeployBucket.Arn
                  - !Join ['', [!GetAtt DeployBucket.Arn, "/*"]]
              -
                Effect: Allow
                Action:
                  - "logs:CreateLogGroup"
                  - "logs:CreateLogStream"
                  - "logs:PutLogEvents"
                  - "cloudfront:CreateInvalidation"
                Resource:
                  - "*"
  CodePipeLineRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - 
            Effect: Allow
            Principal:
              Service:
                - "codepipeline.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: "2012-10-17"
            Statement: 
              - 
                Effect: Allow
                Action:
                  - "s3:GetObject"
                  - "s3:GetObjectVersion"
                  - "s3:GetBucketVersioning"
                  - "s3:PutObject"
                Resource: 
                  - !GetAtt PipelineBucket.Arn
                  - !Join ['', [!GetAtt PipelineBucket.Arn, "/*"]]
              - 
                Effect: Allow  
                Action:
                  - "codebuild:BatchGetBuilds"
                  - "codebuild:StartBuild"
                Resource: "*"
  CodeBuild:
    Type: 'AWS::CodeBuild::Project'
    Properties:
      Name: !Sub ${AWS::StackName}-CodeBuild
      ServiceRole: !GetAtt CodeBuildRole.Arn
      Artifacts:
        Type: CODEPIPELINE
        Name: MyProject
      Source: 
        Type: CODEPIPELINE
      Environment:
        ComputeType: BUILD_GENERAL1_SMALL
        Type: LINUX_CONTAINER
        Image: "aws/codebuild/nodejs:10.14.1"
      Source:
        Type: CODEPIPELINE
        BuildSpec: !Sub |
          version: 0.1
          phases:
            pre_build:
              commands:
                - echo Installing source NPM dependencies...
                - npm install
            build:
              commands:
                - echo Build started on `date`
                - npm run build
            post_build:
              on-failure: CONTINUE
              commands:
                - aws s3 cp --recursive --acl public-read ./build s3://${DeployBucket}/
                #uncomment if you have service-worker.js 
                #- aws s3 cp --acl public-read --cache-control="max-age=0, no-cache, no-store, must-revalidate" ./build/service-worker.js s3://${DeployBucket}/
                - aws s3 cp --acl public-read --cache-control="max-age=0, no-cache, no-store, must-revalidate" ./build/index.html s3://${DeployBucket}/
                - aws cloudfront create-invalidation --distribution-id ${Distribution} --paths /index.html /service-worker.js
          artifacts:
            files:
              - '**/*'
            base-directory: build
  PipelineBucket: 
    Type: 'AWS::S3::Bucket'
    Properties: {}
  DeployBucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      WebsiteConfiguration:
        IndexDocument: index.html
  Distribution:
    Type: "AWS::CloudFront::Distribution"
    Properties:
      DistributionConfig:
        Origins:
          - 
            DomainName: !GetAtt DeployBucket.DomainName
            Id: !Ref DeployBucket
            S3OriginConfig:
              OriginAccessIdentity: ''
        DefaultRootObject: index.html
        Enabled: true
        DefaultCacheBehavior: 
          MinTTL: 86400
          MaxTTL: 31536000
          ForwardedValues: 
            QueryString: true
          TargetOriginId: !Ref DeployBucket
          ViewerProtocolPolicy: "redirect-to-https"
问题分析与修复方案

核心问题1:CloudFront Origin配置不兼容

当前模板中CloudFront的Origin使用了S3网站域名(!GetAtt DeployBucket.DomainName),但配置了S3OriginConfig,这会导致CloudFront尝试通过S3 REST API访问桶,而非网站端点,两者不兼容是导致“无法连接源站”的主要原因。

修复方式:

将CloudFront Origin改为使用自定义源配置,指向S3网站URL:

Distribution:
  Type: "AWS::CloudFront::Distribution"
  Properties:
    DistributionConfig:
      Origins:
        - 
          DomainName: !Select [1, !Split ['//', !GetAtt DeployBucket.WebsiteURL]]
          Id: !Ref DeployBucket
          CustomOriginConfig:
            HTTPPort: 80
            HTTPSPort: 443
            OriginProtocolPolicy: "http-only" # S3网站端点仅支持HTTP
      DefaultRootObject: index.html
      Enabled: true
      DefaultCacheBehavior: 
        MinTTL: 86400
        MaxTTL: 31536000
        ForwardedValues: 
          QueryString: true
        TargetOriginId: !Ref DeployBucket
        ViewerProtocolPolicy: "redirect-to-https"

核心问题2:S3桶访问权限不足

即使CodeBuild将文件设为public-read,如果桶本身没有允许公开读取的策略,CloudFront仍无法获取内容。需给DeployBucket添加桶策略:

DeployBucketPolicy:
  Type: AWS::S3::BucketPolicy
  Properties:
    Bucket: !Ref DeployBucket
    PolicyDocument:
      Version: "2012-10-17"
      Statement:
        - Effect: Allow
          Principal: "*"
          Action: "s3:GetObject"
          Resource: !Join ['', [!GetAtt DeployBucket.Arn, "/*"]]

其他模板问题修复

  • CodePipeline输入输出名称不匹配:Source阶段输出名称为NameForOutput,但Build阶段输入名称写的是(NameHere),需统一:
    # Source阶段OutputArtifacts
    OutputArtifacts: 
      - 
        Name: SourceOutput
    # Build阶段InputArtifacts
    InputArtifacts: 
      - 
        Name: SourceOutput
    
  • CodeBuild重复定义Source属性:删除重复的Source配置,保留包含BuildSpec的那一项:
    CodeBuild:
      Type: 'AWS::CodeBuild::Project'
      Properties:
        Name: !Sub ${AWS::StackName}-CodeBuild
        ServiceRole: !GetAtt CodeBuildRole.Arn
        Artifacts:
          Type: CODEPIPELINE
          Name: MyProject
        Source:
          Type: CODEPIPELINE
          BuildSpec: !Sub |
            # 原BuildSpec内容
        Environment:
          ComputeType: BUILD_GENERAL1_SMALL
          Type: LINUX_CONTAINER
          Image: "aws/codebuild/nodejs:10.14.1"
    
  • Node.js版本过旧:建议将CodeBuild镜像升级到较新版本,比如aws/codebuild/amazonlinux2-x86_64-standard:4.0(内置Node.js 16+),避免依赖安装失败。

验证步骤

  1. 更新模板后重新部署CloudFormation栈
  2. 确认CodePipeline执行完成,Build阶段成功将React构建产物上传到DeployBucket
  3. 直接访问S3网站URL验证内容是否正常
  4. 访问CloudFront URL,确认错误消失

内容的提问来源于stack exchange,提问作者Joshua Foxworth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 00:25:50