0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ECS FargateからS3Filesを使用してS3をマウントしてみた

0
Posted at

S3Filesを初めて使ってみたのでブログに残します。

S3Filesとは

2026年4月ごろに登場したS3をファイルシステムとしてマウントするための機能です。

今までS3をEC2などからマウントして使いたい場合はMountpoint for Amazon S3というものを使っていたと思うのですが、こちらはマウントした後にアクセスするとS3のAPIに変換されてバケット内のオブジェクトを取得するような動きになっているのでEFSなんかと比べるとパフォーマンスは低下します。

S3Filesの場合、ファイルやディレクトリを操作すると、メタデータなどが高性能ストレージというところにキャッシュされるらしく素早く操作することが可能になっているようです。(裏側はEFS基盤みたいです)

試してみた

構成

ざっくりこんな感じで設定してみます。
ECSはApacheのコンテナを一つ用意してドキュメントルートでマウントしてみます。
S3にはindex.htmlを配置してブラウザからアクセスしたときにWebサイトが表示できるか確認します。
s3files_ecs.drawio.png

設定

設定は以下のTerraformを使用します。

main.tf
terraform {
  required_version = ">= 1.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.58.0"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

variable "aws_region" {
  description = "AWSリージョン"
  type        = string
  default     = "ap-northeast-1"
}

variable "prefix" {
  description = "リソース名のプレフィックス"
  type        = string
  default     = "s3files-test"
}

variable "s3_bucket_name" {
  description = "S3 Files用バケット名"
  type        = string
}

# -------------------------------------------------------------------
# Data Sources
# -------------------------------------------------------------------
data "aws_caller_identity" "current" {}

# -------------------------------------------------------------------
# VPC
# -------------------------------------------------------------------
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = { Name = "${var.prefix}-vpc" }
}

resource "aws_subnet" "public_a" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "${var.aws_region}a"
  map_public_ip_on_launch = true

  tags = { Name = "${var.prefix}-public-a" }
}


resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id

  tags = { Name = "${var.prefix}-igw" }
}

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.main.id
  }

  tags = { Name = "${var.prefix}-public-rt" }
}

resource "aws_route_table_association" "public_a" {
  subnet_id      = aws_subnet.public_a.id
  route_table_id = aws_route_table.public.id
}

# -------------------------------------------------------------------
# S3バケット
# -------------------------------------------------------------------
resource "aws_s3_bucket" "main" {
  bucket = var.s3_bucket_name

  tags = { Name = var.s3_bucket_name }
}

resource "aws_s3_bucket_public_access_block" "main" {
  bucket                  = aws_s3_bucket.main.id
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

resource "aws_s3_bucket_versioning" "main" {
  bucket = aws_s3_bucket.main.id

  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "main" {
  bucket = aws_s3_bucket.main.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

# 動作確認用サンプルファイル
resource "aws_s3_object" "sample" {
  bucket       = aws_s3_bucket.main.id
  key          = "index.html"
  content      = "<html><body><h1>Hello from S3 Files!</h1></body></html>"
  content_type = "text/html"

  depends_on = [aws_s3_bucket_versioning.main]
}

# -------------------------------------------------------------------
# IAM: S3 Files ファイルシステム用ロール
# -------------------------------------------------------------------
resource "aws_iam_role" "s3files_filesystem" {
  name = "${var.prefix}-s3files-fs-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Sid    = "AllowS3FilesAssumeRole"
      Effect = "Allow"
      Principal = { Service = "elasticfilesystem.amazonaws.com" }
      Action = "sts:AssumeRole"
      Condition = {
        StringEquals = {
          "aws:SourceAccount" = data.aws_caller_identity.current.account_id
        }
        ArnLike = {
          "aws:SourceArn" = "arn:aws:s3files:${var.aws_region}:${data.aws_caller_identity.current.account_id}:file-system/*"
        }
      }
    }]
  })

  tags = { Name = "${var.prefix}-s3files-fs-role" }
}

resource "aws_iam_role_policy" "s3files_filesystem" {
  name = "${var.prefix}-s3files-fs-policy"
  role = aws_iam_role.s3files_filesystem.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "S3BucketPermissions"
        Effect = "Allow"
        Action = ["s3:ListBucket", "s3:ListBucketVersions"]
        Resource = aws_s3_bucket.main.arn
        Condition = {
          StringEquals = { "aws:ResourceAccount" = data.aws_caller_identity.current.account_id }
        }
      },
      {
        Sid    = "S3ObjectPermissions"
        Effect = "Allow"
        Action = ["s3:AbortMultipartUpload", "s3:DeleteObject*", "s3:GetObject*", "s3:List*", "s3:PutObject*"]
        Resource = "${aws_s3_bucket.main.arn}/*"
        Condition = {
          StringEquals = { "aws:ResourceAccount" = data.aws_caller_identity.current.account_id }
        }
      },
      {
        Sid    = "EventBridgeManage"
        Effect = "Allow"
        Action = ["events:DeleteRule", "events:DisableRule", "events:EnableRule", "events:PutRule", "events:PutTargets", "events:RemoveTargets"]
        Resource = ["arn:aws:events:*:*:rule/DO-NOT-DELETE-S3-Files*"]
        Condition = { StringEquals = { "events:ManagedBy" = "elasticfilesystem.amazonaws.com" } }
      },
      {
        Sid    = "EventBridgeRead"
        Effect = "Allow"
        Action = ["events:DescribeRule", "events:ListRuleNamesByTarget", "events:ListRules", "events:ListTargetsByRule"]
        Resource = ["arn:aws:events:*:*:rule/*"]
      }
    ]
  })
}

# -------------------------------------------------------------------
# IAM: ECS タスク実行ロール
# -------------------------------------------------------------------
resource "aws_iam_role" "ecs_task_execution" {
  name = "${var.prefix}-ecs-execution-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect    = "Allow"
      Principal = { Service = "ecs-tasks.amazonaws.com" }
      Action    = "sts:AssumeRole"
    }]
  })

  tags = { Name = "${var.prefix}-ecs-execution-role" }
}

resource "aws_iam_role_policy_attachment" "ecs_task_execution" {
  role       = aws_iam_role.ecs_task_execution.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}

# -------------------------------------------------------------------
# IAM: ECS タスクロール
# -------------------------------------------------------------------
resource "aws_iam_role" "ecs_task" {
  name = "${var.prefix}-ecs-task-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect    = "Allow"
      Principal = { Service = "ecs-tasks.amazonaws.com" }
      Action    = "sts:AssumeRole"
    }]
  })

  tags = { Name = "${var.prefix}-ecs-task-role" }
}

resource "aws_iam_role_policy_attachment" "ecs_task_s3files" {
  role       = aws_iam_role.ecs_task.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonS3FilesClientFullAccess"
}

# ECS Exec に必要な SSM / ログ権限
resource "aws_iam_role_policy" "ecs_task_exec_command" {
  name = "${var.prefix}-ecs-task-exec-command"
  role = aws_iam_role.ecs_task.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "ECSExec"
        Effect = "Allow"
        Action = [
          "ssmmessages:CreateControlChannel",
          "ssmmessages:CreateDataChannel",
          "ssmmessages:OpenControlChannel",
          "ssmmessages:OpenDataChannel"
        ]
        Resource = "*"
      },
      {
        Sid    = "ECSExecLogs"
        Effect = "Allow"
        Action = [
          "logs:CreateLogStream",
          "logs:DescribeLogGroups",
          "logs:DescribeLogStreams",
          "logs:PutLogEvents"
        ]
        Resource = "*"
      }
    ]
  })
}

resource "aws_iam_role_policy" "ecs_task_s3_direct" {
  name = "${var.prefix}-ecs-task-s3-direct"
  role = aws_iam_role.ecs_task.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid      = "S3ObjectReadAccess"
        Effect   = "Allow"
        Action   = ["s3:GetObject", "s3:GetObjectVersion"]
        Resource = "${aws_s3_bucket.main.arn}/*"
      },
      {
        Sid      = "S3BucketListAccess"
        Effect   = "Allow"
        Action   = "s3:ListBucket"
        Resource = aws_s3_bucket.main.arn
      }
    ]
  })
}

# -------------------------------------------------------------------
# セキュリティグループ
# -------------------------------------------------------------------
resource "aws_security_group" "s3files_mount_target" {
  name        = "${var.prefix}-s3files-mt-sg"
  description = "S3 Files mount target security group"
  vpc_id      = aws_vpc.main.id

  tags = { Name = "${var.prefix}-s3files-mt-sg" }
}

resource "aws_security_group" "ecs_task" {
  name        = "${var.prefix}-ecs-task-sg"
  description = "ECS task security group for Apache + S3 Files"
  vpc_id      = aws_vpc.main.id

  ingress {
    description = "HTTP from anywhere"
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    description     = "S3 Files mount target (TCP 2049)"
    from_port       = 2049
    to_port         = 2049
    protocol        = "tcp"
    security_groups = [aws_security_group.s3files_mount_target.id]
  }

  egress {
    description = "HTTPS outbound for ECR / CloudWatch / S3 API"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = { Name = "${var.prefix}-ecs-task-sg" }
}

resource "aws_security_group_rule" "mt_inbound_from_ecs" {
  type                     = "ingress"
  description              = "NFS from ECS task"
  from_port                = 2049
  to_port                  = 2049
  protocol                 = "tcp"
  security_group_id        = aws_security_group.s3files_mount_target.id
  source_security_group_id = aws_security_group.ecs_task.id
}

# -------------------------------------------------------------------
# S3 Files
# -------------------------------------------------------------------
resource "aws_s3files_file_system" "main" {
  bucket   = aws_s3_bucket.main.arn
  role_arn = aws_iam_role.s3files_filesystem.arn

  depends_on = [
    aws_s3_bucket_versioning.main,
    aws_iam_role_policy.s3files_filesystem,
  ]

  tags = { Name = "${var.prefix}-s3files-fs" }
}

resource "aws_s3files_mount_target" "public_a" {
  file_system_id  = aws_s3files_file_system.main.id
  subnet_id       = aws_subnet.public_a.id
  security_groups = [aws_security_group.s3files_mount_target.id]
}

# -------------------------------------------------------------------
# ECS
# -------------------------------------------------------------------
resource "aws_cloudwatch_log_group" "ecs" {
  name              = "/ecs/${var.prefix}"
  retention_in_days = 7

  tags = { Name = "${var.prefix}-logs" }
}

resource "aws_ecs_cluster" "main" {
  name = "${var.prefix}-cluster"

  setting {
    name  = "containerInsights"
    value = "disabled"
  }

  tags = { Name = "${var.prefix}-cluster" }
}

resource "aws_ecs_task_definition" "apache" {
  family                   = "${var.prefix}-task"
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  cpu                      = "256"
  memory                   = "512"
  execution_role_arn       = aws_iam_role.ecs_task_execution.arn
  task_role_arn            = aws_iam_role.ecs_task.arn

  volume {
    name = "s3files-volume"

    s3files_volume_configuration {
      file_system_arn = aws_s3files_file_system.main.arn
    }
  }

  container_definitions = jsonencode([
    {
      name      = "apache"
      image     = "httpd:2.4"
      essential = true

      portMappings = [{
        containerPort = 80
        protocol      = "tcp"
      }]

      mountPoints = [{
        sourceVolume  = "s3files-volume"
        containerPath = "/usr/local/apache2/htdocs"
        readOnly      = false
      }]

      logConfiguration = {
        logDriver = "awslogs"
        options = {
          "awslogs-group"         = aws_cloudwatch_log_group.ecs.name
          "awslogs-region"        = var.aws_region
          "awslogs-stream-prefix" = "apache"
        }
      }
    }
  ])

  tags = { Name = "${var.prefix}-task" }
}

resource "aws_ecs_service" "apache" {
  name            = "${var.prefix}-service"
  cluster         = aws_ecs_cluster.main.id
  task_definition = aws_ecs_task_definition.apache.arn
  desired_count   = 1
  launch_type     = "FARGATE"

  network_configuration {
    subnets          = [aws_subnet.public_a.id]
    security_groups  = [aws_security_group.ecs_task.id]
    assign_public_ip = true
  }

  force_new_deployment    = true
  enable_execute_command  = true

  depends_on = [
    aws_s3files_mount_target.public_a,
  ]

  tags = { Name = "${var.prefix}-service" }
}

上記のコードを使用すると、今回使用するECS、S3周りが全て作成されます。

デプロイ

以下のコマンドを実行してデプロイします。

terraform init
terraform plan # planは実行してもしなくても大丈夫です
terraofmr apply

applyを実行するとS3バケット名を聞かれるので任意のバケット名を入力してデプロイしてください。

コードの説明

今回メインになるのは以下の部分化と思います。
ここら辺の説明は全て以下のドキュメントに記載されていたので、こちらを読んでから作成すれば詰まる部分はなかったです。

S3filseのマウントポイント

この部分でS3とECSの間にあるマウントポイントを作成しています。
マウントポイントではS3バケットにアクセスするためのIAMポリシーが必要となります。
また、ファイル同期のためにEventBridgeを使うのでその権限も与えています。

# -------------------------------------------------------------------
# IAM: S3 Files ファイルシステム用ロール
# -------------------------------------------------------------------
resource "aws_iam_role" "s3files_filesystem" {
  name = "${var.prefix}-s3files-fs-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Sid    = "AllowS3FilesAssumeRole"
      Effect = "Allow"
      Principal = { Service = "elasticfilesystem.amazonaws.com" }
      Action = "sts:AssumeRole"
      Condition = {
        StringEquals = {
          "aws:SourceAccount" = data.aws_caller_identity.current.account_id
        }
        ArnLike = {
          "aws:SourceArn" = "arn:aws:s3files:${var.aws_region}:${data.aws_caller_identity.current.account_id}:file-system/*"
        }
      }
    }]
  })

  tags = { Name = "${var.prefix}-s3files-fs-role" }
}

resource "aws_iam_role_policy" "s3files_filesystem" {
  name = "${var.prefix}-s3files-fs-policy"
  role = aws_iam_role.s3files_filesystem.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "S3BucketPermissions"
        Effect = "Allow"
        Action = ["s3:ListBucket", "s3:ListBucketVersions"]
        Resource = aws_s3_bucket.main.arn
        Condition = {
          StringEquals = { "aws:ResourceAccount" = data.aws_caller_identity.current.account_id }
        }
      },
      {
        Sid    = "S3ObjectPermissions"
        Effect = "Allow"
        Action = ["s3:AbortMultipartUpload", "s3:DeleteObject*", "s3:GetObject*", "s3:List*", "s3:PutObject*"]
        Resource = "${aws_s3_bucket.main.arn}/*"
        Condition = {
          StringEquals = { "aws:ResourceAccount" = data.aws_caller_identity.current.account_id }
        }
      },
      {
        Sid    = "EventBridgeManage"
        Effect = "Allow"
        Action = ["events:DeleteRule", "events:DisableRule", "events:EnableRule", "events:PutRule", "events:PutTargets", "events:RemoveTargets"]
        Resource = ["arn:aws:events:*:*:rule/DO-NOT-DELETE-S3-Files*"]
        Condition = { StringEquals = { "events:ManagedBy" = "elasticfilesystem.amazonaws.com" } }
      },
      {
        Sid    = "EventBridgeRead"
        Effect = "Allow"
        Action = ["events:DescribeRule", "events:ListRuleNamesByTarget", "events:ListRules", "events:ListTargetsByRule"]
        Resource = ["arn:aws:events:*:*:rule/*"]
      }
    ]
  })
}

...中略...

# -------------------------------------------------------------------
# S3 Files
# -------------------------------------------------------------------
resource "aws_s3files_file_system" "main" {
  bucket   = aws_s3_bucket.main.arn
  role_arn = aws_iam_role.s3files_filesystem.arn

  depends_on = [
    aws_s3_bucket_versioning.main,
    aws_iam_role_policy.s3files_filesystem,
  ]

  tags = { Name = "${var.prefix}-s3files-fs" }
}

resource "aws_s3files_mount_target" "public_a" {
  file_system_id  = aws_s3files_file_system.main.id
  subnet_id       = aws_subnet.public_a.id
  security_groups = [aws_security_group.s3files_mount_target.id]
}

ECSの設定

ECS側ではタスク定義でマウントポイントを参照する設定を入れています。
また、S3を直接参照する権限も必要になるため、タスクロールにS3アクセス用のIAMも付与しています。

resource "aws_iam_role" "ecs_task" {
  name = "${var.prefix}-ecs-task-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect    = "Allow"
      Principal = { Service = "ecs-tasks.amazonaws.com" }
      Action    = "sts:AssumeRole"
    }]
  })

  tags = { Name = "${var.prefix}-ecs-task-role" }
}

resource "aws_iam_role_policy_attachment" "ecs_task_s3files" {
  role       = aws_iam_role.ecs_task.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonS3FilesClientFullAccess"
}

# ECS Exec に必要な SSM / ログ権限
resource "aws_iam_role_policy" "ecs_task_exec_command" {
  name = "${var.prefix}-ecs-task-exec-command"
  role = aws_iam_role.ecs_task.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "ECSExec"
        Effect = "Allow"
        Action = [
          "ssmmessages:CreateControlChannel",
          "ssmmessages:CreateDataChannel",
          "ssmmessages:OpenControlChannel",
          "ssmmessages:OpenDataChannel"
        ]
        Resource = "*"
      },
      {
        Sid    = "ECSExecLogs"
        Effect = "Allow"
        Action = [
          "logs:CreateLogStream",
          "logs:DescribeLogGroups",
          "logs:DescribeLogStreams",
          "logs:PutLogEvents"
        ]
        Resource = "*"
      }
    ]
  })
}

resource "aws_iam_role_policy" "ecs_task_s3_direct" {
  name = "${var.prefix}-ecs-task-s3-direct"
  role = aws_iam_role.ecs_task.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid      = "S3ObjectReadAccess"
        Effect   = "Allow"
        Action   = ["s3:GetObject", "s3:GetObjectVersion"]
        Resource = "${aws_s3_bucket.main.arn}/*"
      },
      {
        Sid      = "S3BucketListAccess"
        Effect   = "Allow"
        Action   = "s3:ListBucket"
        Resource = aws_s3_bucket.main.arn
      }
    ]
  })
}
...中略...

# -------------------------------------------------------------------
# ECS
# -------------------------------------------------------------------
resource "aws_cloudwatch_log_group" "ecs" {
  name              = "/ecs/${var.prefix}"
  retention_in_days = 7

  tags = { Name = "${var.prefix}-logs" }
}

resource "aws_ecs_cluster" "main" {
  name = "${var.prefix}-cluster"

  setting {
    name  = "containerInsights"
    value = "disabled"
  }

  tags = { Name = "${var.prefix}-cluster" }
}

resource "aws_ecs_task_definition" "apache" {
  family                   = "${var.prefix}-task"
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  cpu                      = "256"
  memory                   = "512"
  execution_role_arn       = aws_iam_role.ecs_task_execution.arn
  task_role_arn            = aws_iam_role.ecs_task.arn

  volume {
    name = "s3files-volume"

    s3files_volume_configuration {
      file_system_arn = aws_s3files_file_system.main.arn
    }
  }

  container_definitions = jsonencode([
    {
      name      = "apache"
      image     = "httpd:2.4"
      essential = true

      portMappings = [{
        containerPort = 80
        protocol      = "tcp"
      }]

      mountPoints = [{
        sourceVolume  = "s3files-volume"
        containerPath = "/usr/local/apache2/htdocs"
        readOnly      = false
      }]

      logConfiguration = {
        logDriver = "awslogs"
        options = {
          "awslogs-group"         = aws_cloudwatch_log_group.ecs.name
          "awslogs-region"        = var.aws_region
          "awslogs-stream-prefix" = "apache"
        }
      }
    }
  ])

  tags = { Name = "${var.prefix}-task" }
}

セキュリティグループ

S3Filesの使用するセキュリティグループでは2049番ポートを使用するのでそちらをインバウンドルールで許可しています。

resource "aws_security_group" "s3files_mount_target" {
  name        = "${var.prefix}-s3files-mt-sg"
  description = "S3 Files mount target security group"
  vpc_id      = aws_vpc.main.id

  tags = { Name = "${var.prefix}-s3files-mt-sg" }
}

resource "aws_security_group" "ecs_task" {
  name        = "${var.prefix}-ecs-task-sg"
  description = "ECS task security group for Apache + S3 Files"
  vpc_id      = aws_vpc.main.id

  ingress {
    description = "HTTP from anywhere"
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    description     = "S3 Files mount target (TCP 2049)"
    from_port       = 2049
    to_port         = 2049
    protocol        = "tcp"
    security_groups = [aws_security_group.s3files_mount_target.id]
  }

  egress {
    description = "HTTPS outbound for ECR / CloudWatch / S3 API"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = { Name = "${var.prefix}-ecs-task-sg" }
}

resource "aws_security_group_rule" "mt_inbound_from_ecs" {
  type                     = "ingress"
  description              = "NFS from ECS task"
  from_port                = 2049
  to_port                  = 2049
  protocol                 = "tcp"
  security_group_id        = aws_security_group.s3files_mount_target.id
  source_security_group_id = aws_security_group.ecs_task.id
}

ファイルの読み書きをしてみる

デプロイが完了したらブラウザからアクセスして画面が表示されるか確認してみます。
ECSタスクの画面からパブリックIPアドレスを確認してブラウザからアクセスしてみてください。
スクリーンショット 2026-08-12 210914.png

以下のような画面が表示されれば成功です。
初回アクセス時はやはり少し時間がかかるようです。
image.png

書き込みはECSタスクにECS Execで接続して確認してみます。
接続後に以下のコマンドでindex.htmlに書き込みます。

echo "<html><body><h1>hoge test</h1></body></html>" > /usr/local/apache2/htdocs/index.html

再度ブラウザからアクセスしてみると表示が変わっていることが確認できます。
image.png

さいごに

初回アクセス時はキャッシュ層にデータが無いので表示に少し時間がかかるのがわかりました。
アプリケーションでNFSしか使えないけどS3のデータが使いたい用途であれば十分な内容なのかなと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?