What's the best way to store a config file for a Docker container on AWS?

寵の児 提交于 2021-02-16 20:35:54

问题


I have a node.js app which has a config file with sensitive data. I want to launch it through AWS ECS (cluster) as a docker container.

What would be the best way to store the sensitive config data?

I am currently sending them through the environmental variables in the Task Definition of the Docker container, but there has to be a better way to do that.

What is the best practice for something like this? Shall I use Docker secrets or Amazon secrets manager?

I know it's a pretty general question, but I couldn't find an answer to that, so maybe somebody has a recommendation?


回答1:


What would be the best way to store the sensitive config data?

Usually you would use either SSM Parameter Store or AWS Secrets Manager. One difference between them is that the SSM Parameter Store is free (Standard type), while AWS Secrets Manager is not.

Then you would pass "links" to your secrets in store or manager using environmental variables in the Task Definition.

For this, you application would need to use AWS SDK to get the secrets in the container. Also task role would need to be setup so that your containers can access the secrets.

The task would also need to be able to access the SSM Parameter Store or the AWS Secrets Manager. Thus if you run them in private subsets without internet, NAT gateway or VPC interface endpoints for SSM and Secret Manager (depending on what you use) would need to be setup to allow the access.

Extra details below:

  • Managing Secrets for Amazon ECS Applications Using Parameter Store and IAM Roles for Tasks



回答2:


Great question. I agree that the SSM Parameter Store or AWS Secrets Manager are the recommended tools for this job, but they are just not that usable in my opinion if you follow the infrastructure as code principle.

Therefore I keep my configuration files right next to the Terraform scripts in the same Git repository and inject the actual sensitive data (passwords, keys, whatever) during runtime from the SSM Parameter Store into the specific target files.

This has several advantages over using the AWS provided solution:

  • No size limit (SSM Parameter Store limits you to 4 KB in the free version).
  • Non-sensitive configuration is version controlled with all the advantages that come with that.
  • I can easily see the current configs used and update them instead of logging into the AWS console and so on.

Here is how I manage configs/secrets with Terraform / AWS ECS

The basic idea is as following: We store configuration files without sensitive data in the repository next to Terraform. Secrets are stored in AWS parameter store. To get the data into our containers at runtime, we modify the entrypoint. We could of course just create modified images, but that creates a big maintenance overhead in my opinion. Using the entrypoint approach, we can keep using vanilla images.

The disadvantage is that I have to create custom entrypoint scripts. That means that I have to find the Dockerfile of the image I'm interested in and extract the commands used to start the actual process running in the image.

I have a git repository like this:

├── files
│   └── promstack
│       ├── grafana
│       │   ├── default-datasources.yml
│       │   ├── grafana.ini
│       │   └── run.sh
│       ├── loki
│       │   └── run.sh
│       ├── nginx
│       │   ├── nginx.conf
│       │   └── run.sh
│       └── prometheus
│           ├── prometheus.yml
│           ├── rules-alerting.yml
│           ├── rules-recording.yml
│           └── run.sh
├── myscript.tf
└── variables.tf

The run.sh scripts represent the entrypoints. Here is an exemplary run.sh:

#!/bin/sh

set -x

require () {
    if [ ! "$1" ]; then 
        echo "ERROR: var not found"
        exit 1 
    fi 
}

expand () {
    var_name="${1}"
    file="${2}"

    eval var="\$$var_name"

    sed -i "s+\${${var_name}}+${var}+g" ${file}
    sed -i "s+\$${var_name}+${var}+g" ${file}
}

require ${GRAFANA_INI}
require ${DEFAULT_DATASOURCES_YML}
require ${DOMAIN}

echo ${GRAFANA_INI} | base64 -d > /etc/grafana/grafana.ini
chmod 666 /etc/grafana/grafana.ini

expand DOMAIN /etc/grafana/grafana.ini

echo ${DEFAULT_DATASOURCES_YML} | base64 -d > /etc/grafana/provisioning/datasources/default.yml
chmod 666 /etc/grafana/provisioning/datasources/default.yml

su -s "/bin/sh" -c "/run.sh" grafana

Here a part from a Terraform script (ECS Container task definition to be exact):

{
  name: "grafana",
  image: "grafana/grafana:7.0.5",
  portMappings: [{
    containerPort : 3000,
    hostPort: 0,
    protocol: "tcp"
  }],
  user: "0",
  entryPoint: [ "/bin/sh", "-c", join(" ", [
    "export DEFAULT_DATASOURCES_YML=${base64encode(file("${path.module}/files/promstack/grafana/default-datasources.yml"))};",
    "export GRAFANA_INI=${base64encode(file("${path.module}/files/promstack/grafana/grafana.ini"))};",
    "echo '${base64encode(file("${path.module}/files/promstack/grafana/run.sh"))}' | base64 -d | sh;"
  ])],
  secrets: [
    {
      name: "DOMAIN",
      valueFrom: "<my ssm parameter>"
    }
  ]
},


来源:https://stackoverflow.com/questions/62791093/whats-the-best-way-to-store-a-config-file-for-a-docker-container-on-aws

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!