以下の内容はhttps://miyohide.hatenablog.com/entry/2025/02/22/203828より取得しました。


コンテナ化アプリのファイル出力: Amazon EFSの活用手法

はじめに

コンテナ化したアプリを動かす際に、ファイル出力をしたいというニーズをちょくちょく聞きます。特に既存のアプリケーションに対して、なんとかコンテナ化まではできたが、ファイル出力する仕様までは変更することができなく、どうしたら良いかという話をよく耳にします。ここではその対処方法について記します。

Amazon Elastic Container Serviceでの対処方法

以下の公開情報にAmazon ECS上で取れるストレージサービスとその特性がまとまっています。

docs.aws.amazon.com

多くの場合、永続化したいというニーズかと思いますので、Amazon EFSを使うのが選択になるかなと考えています。Windowsで動かしている場合はAmazon FSx for Windows File ServerかDockerボリュームが選択肢になるかと思いますが、起動タイプがEC2しかダメなのがちょっと難点です。

App Runner

お手軽にコンテナ化したアプリを動かす環境としてApp Runnerがあります。Amazon ECSは動かすために色々とリソースを作る必要がありちょっとハードルが高いので、App Runnerを使いたいこともままあるのですが、現時点ではApp RunnerはAmazon EFSなどに永続化の目的で出力させることはできないようです。

GitHubのIssueとしてかなり若い番号で裁判された要望があるのですが、まだOpenのままでした。

github.com

実装

というわけで、Amazon ECS上でAmazon EFSをマウントすることをCDKを使って実装してみました。

import { Vpc } from 'aws-cdk-lib/aws-ec2';
import { Cluster, ContainerDefinition, ContainerImage, FargateTaskDefinition } from 'aws-cdk-lib/aws-ecs';
import { ApplicationLoadBalancedFargateService } from 'aws-cdk-lib/aws-ecs-patterns';
import { FileSystem, LifecyclePolicy, PerformanceMode, ThroughputMode } from 'aws-cdk-lib/aws-efs';
import { AnyPrincipal, PolicyStatement } from 'aws-cdk-lib/aws-iam';
import { RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib/core';
import { Construct } from 'constructs';

export class EcsWithEfsStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const vpc = new Vpc(this, 'MyVPC', { maxAzs: 2});
    const ecsCluster = new Cluster(this, 'EcsCluster', { vpc: vpc });

    const fileSystem = new FileSystem(this, 'MyEfsFileSystem', {
      vpc: vpc,
      encrypted: true,
      // テスト目的なので、removalPolicyは削除とする
      removalPolicy: RemovalPolicy.DESTROY,
      lifecyclePolicy: LifecyclePolicy.AFTER_14_DAYS,
      performanceMode: PerformanceMode.GENERAL_PURPOSE,
      throughputMode: ThroughputMode.BURSTING
    });

    fileSystem.addToResourcePolicy(
      new PolicyStatement({
        actions: ['elasticfilesystem:ClientMount'],
        principals: [new AnyPrincipal()],
        conditions: {
          Bool: {
            'elasticfilesystem:AccessedViaMountTarget': 'true'
          }
        }
      })
    );

    const taskDef = new FargateTaskDefinition(this, "MyTaskDef", {
      memoryLimitMiB: 512,
      cpu: 256,
      volumes: [
        {
          name: "hogehoge",
          efsVolumeConfiguration: {
            fileSystemId: fileSystem.fileSystemId,
          }
        }
      ]
    });

    const containerDef = new ContainerDefinition(this, 'MyContainerDefinition', {
      image: ContainerImage.fromRegistry('コンテナイメージ名'),
      taskDefinition: taskDef
    });

    containerDef.addMountPoints(
      {
        containerPath: '/mydata',
        sourceVolume: 'mydata',
        readOnly: false
      }
    );

    containerDef.addPortMappings({
      containerPort: ポート番号,
    });

    const albFargateService = new ApplicationLoadBalancedFargateService(this, 'MyALBService', {
      cluster: ecsCluster,
      taskDefinition: taskDef,
      desiredCount: 1
    });

    albFargateService.targetGroup.setAttribute('deregistration_delay.timeout_seconds', '30');

    fileSystem.grantRootAccess(albFargateService.taskDefinition.taskRole.grantPrincipal);
    fileSystem.connections.allowDefaultPortFrom(albFargateService.service.connections);
  }
}

ポイントは、タスク定義のvolumes以下の部分です。

    const taskDef = new FargateTaskDefinition(this, "MyTaskDef", {
      memoryLimitMiB: 512,
      cpu: 256,
      volumes: [
        {
          name: "hogehoge",
          efsVolumeConfiguration: {
            fileSystemId: fileSystem.fileSystemId,
          }
        }
      ]
    });

考察

まずはAmazon EFSをマウントするECSを実装してみました。複数の選択肢がありますが、永続化という目的であればAmazon EFSが有力候補になるかと思います。

実際にはAmazon EFSをECSにマウントしただけではよくなく、中身を参照したりするニーズがあります。そのニーズを満たすために以下のハンズオンが参考になりそうです。

dev.classmethod.jp

このハンズオンを元にしたより実践的なCDK実装を実装していこうかと考えています。




以上の内容はhttps://miyohide.hatenablog.com/entry/2025/02/22/203828より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14