How to provide a config file to a Fargate Task?

Viewed 2508

What is the easiest way to provide one or several external configuration file(s) to an app running as an AWS Fargate task?

  • The files cannot be part of the Docker image because they depend on the stage environment and may contain secrets.
  • Creating an EFS volume just for this seems to be overengineered (we only need read access to some kb of properties).
  • Using the AWS SDK to access a S3 bucket at startup means that the app has a dependency to the SDK, and one has to manage S3 buckets.*
  • Using AWS AppConfig would still require the app to use the AWS SDK to access the config values.*
  • Having hundreds of key-value pairs in the Parameter Store would be ugly.

*It is an important aspect of our applications to not depend on the AWS SDK, because we need to be able to deploy to different cloud platforms, so solutions that avoid this are preferable.

It would be nice to just be able to define this in the task definition, so that Fargate mounts a couple of files in the container. Is this or a similar low-key solution available?

3 Answers

Not an answer to the question but in case someone comes here looking for solutions, we had the same requirements but did not find an easy solution to deploy configuration file directly in ECS instance for the container to read. I'm sure it's possible, just would make is difficult to configure, therefore we did not see the effort worthy.

What we did:

  1. Added EnvironmentConfigBuilder as discribed in MS docs here
  2. Passed in configuration values using environment variables as described in AWS docs here.

You can specify your AWS AppConfig dependency as a separate container. AWS gives you the option to set container dependency execution conditions in your Task Definition. See: https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ContainerDependency.html

You could set your container dependency status to COMPLETE for the container that pulls the config files from AppConfig and then just treat the files as a dumb mount, separating the AWS dependency completely. For Example:

    "containerDefinitions": [
    {
        "name": "app-config-script",
        "image": "1234567890.dkr.ecr.SOME_REGION.amazonaws.com/app-config-script:ver",
        "essential": false,
        "mountPoints": [
            {
                "sourceVolume": "config",
                "containerPath": "/data/config/nginx",
                "readOnly": ""
            }
        ],
        "dependsOn": null,
        "repositoryCredentials": {
            "credentialsParameter": ""
        }
    },
    {
        "name": "nginx",
        "image": "nginx",
        "essential": true,
        "portMappings": [
            {
                "containerPort": "80",
                "protocol": "tcp"
            },
            {
                "containerPort": "443",
                "protocol": "tcp"
            }
        ],
        "mountPoints": [
            {
                "sourceVolume": "config",
                "containerPath": "/etc/nginx",
                "readOnly": true
            }
        ],
        "dependsOn": [
            {
                "containerName": "app-config-script",
                "condition": "COMPLETE"
            }
        ],
        "repositoryCredentials": {
            "credentialsParameter": ""
        }
    }
],

Your Entrypoint/CMD script in the bootstrap container would then be something like:

#!/bin/sh
token=$(aws appconfigdata start-configuration-session --application-identifier "${APPLICATION_ID}" --environment-identifier "${ENVIRONMENT_ID}" --configuration-profile-identifier "${CONFIGURATION_ID}" | jq -r .InitialConfigurationToken)
aws appconfigdata get-latest-configuration --configuration-token "${token}" /data/config/nginx/nginx.conf
Related