如何在Fargate容器中启动Rails控制台

时间:2019-04-25 09:04:15

标签: ruby-on-rails amazon-web-services console amazon-ecs aws-fargate

我想在Fargate容器中打开Rails控制台以与生产安装进行交互

但是,在网上搜索并发布到AWS论坛后,我找不到该问题的答案

有人知道我该怎么做吗?在任何生产环境中,这似乎都是必须要做的事情,而且没有简单的方法可以做到,这令人惊讶的是,来自像AWS这样受人尊敬的云提供商。

谢谢

5 个答案:

答案 0 :(得分:2)

尝试了很多事情之后,我找到了一种方法来打开一个指向我的生产环境的Rails控制台,因此我将其发布在这里,以防有人遇到相同的问题

总而言之,我添加了一个部署在Fargate上的Rails应用程序,该应用程序连接到RDS postgres数据库

我所做的是为托管我的Rails应用程序和RDS数据库的VPC创建一个VPN客户端终结点

然后,在连接到该VPN之后,我只需运行我的rails生产容器(具有相同的环境变量),以覆盖容器命令来运行控制台启动脚本(bundle exec rails c production

在本地计算机上运行时,通常可以将TTY附加到此容器并访问生产控制台

我认为此解决方案很好,因为它允许从事该项目的任何开发人员打开控制台而不会产生任何费用,并且AWS端的完善安全策略可确保控制台访问安全,而且您不希望这样做必须将数据库暴露在VPC之外

希望这对某人有所帮助

答案 1 :(得分:1)

我还没有在Fargate上尝试过此操作,但是您应该能够创建命令为rails console的{​​{3}}。

然后,如果您fargate task,则应该能够启动交互式容器并可以通过stdin访问控制台。

答案 2 :(得分:1)

在将Fargate执行类型用于ECS时,无法SSH到基础主机。这意味着您无法将docker exec放入正在运行的容器中。

答案 3 :(得分:1)

使用ECS和Fargate做任何一种docker exec都是一场噩梦。这使得执行Shell或迁移之类的工作非常困难。

值得庆幸的是,ECS上的Fargate任务实际上只是一台运行一些超级定制的docker run命令的AWS服务器。因此,如果您在EC2或本地计算机上拥有dockerjq和AWS CLI,则可以自己伪造其中一些docker run命令并输入bash shell。我为Django执行此操作,因此我可以运行迁移并输入python shell,但我认为它与rails(或需要bash的任何其他容器)相同。

请注意,这仅在您只关心每次运行的任务定义中阐明的1个容器的情况下有效,尽管我想您可以通过jerry-rig来完成更复杂的操作。

为此,将需要使用与Fargate任务相同的IAM权限登录AWS CLI。您可以使用aws configure在本地执行此操作,并为具有正确IAM权限的用户提供凭据,或者通过启动具有相同权限的角色或(为了简单起见)角色的EC2实例您的Fargate任务正在运行,并且具有相同访问权限的安全组(加上允许您通过SSH进入堡垒主机的规则。)我喜欢EC2路由,因为通过公用Internet和VPN进行所有通信的速度很慢。另外,您始终可以确保您拥有与任务相同的IAM访问权限。

您还需要与Fargate任务位于同一子网中,这通常可以通过VPN来完成,也可以通过在私有子网内的EC2堡垒主机上运行此代码来完成。

就我而言,我将配置参数作为SecureStrings存储在AWS Systems Manager参数存储内,并使用ECS任务定义将其传递给我。可以很容易地获得它们,并使用

设置为本地环境变量。
export DATABASE_URL=$(aws ssm get-parameter --region $REGION \
                      --with-decryption --name parameter.name.database_url \
                      | jq '.Parameter["Value"]' -r)

我将容器存储在ECR上,因此我需要将本地Docker容器登录到ECR

eval $(aws ecr get-login --no-include-email --region $REGION)

这只是运行交互式Docker容器的一种情况,该容器传递DATABASE_URL,从ECR中提取正确的图像,然后输入bash。我还公开了端口8000,因此我可以在外壳中运行Web服务器,但这是可选的。

docker run -i -t \
           -e DATABASE_URL \
           -p 8000:8000 \
           $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$DOCKER_REPO_NAME:$TAG \
           /bin/bash

一旦运行,您应该看到docker副本从容器存储库下载映像,然后将您启动到bash(假设bash安装在您的容器中。)Docker具有相当稳定的缓存,因此这将花费一些时间是第一次下载并启动,但之后应该很快。

这是我的完整剧本

#!/bin/bash

REGION=${REGION:-us-west-2}
ENVIRONMENT=${ENVIRONMENT:-staging}
DOCKER_REPO_NAME=${DOCKER_REPO_NAME:-reponame}
TAG=${TAG:-latest}

ACCOUNT_ID=$(aws sts get-caller-identity | jq -r ".Account")

export DATABASE_URL=$(aws ssm get-parameter --region $REGION \
                      --with-decryption --name projectname.$ENVIRONMENT.database_url \
                      | jq '.Parameter["Value"]' -r)

eval $(aws ecr get-login --no-include-email --region $REGION)

IMAGE=$ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$DOCKER_REPO_NAME:$TAG

docker run -i -t \
           -e DATABASE_URL \
           -p 8000:8000 \
           $IMAGE \
           /bin/bash

答案 4 :(得分:0)

好,所以我做的事情有所不同。我没有尝试在Fargate上运行控制台,而是在本地主机上运行控制台,但将其配置为使用RAILS_ENV='production'并使其使用我的RDS实例。

当然要执行此操作,您必须通过安全组中的出口规则公开RDS实例。明智的做法是仅允许您的本地IP进行配置,以使其更加安全。

docker-compose.yml然后看起来像这样:

version: '3'
  web:
    stdin_open: true
    tty: true
    build: .
    volumes:
      - ./rails/.:/your-app
    ports:
      - "3000:3000"
    environment: &env_vars
      RAILS_ENV: 'production'
      PORT: '8080'
      RAILS_LOG_TO_STDOUT: 'true'
      RAILS_SERVE_STATIC_FILES: 'true'
      DATABASE_URL: 'postgresql://username:password@yours-aws-rds-instance:5432/your-db'

当您随后运行docker-compose run web rails c时,它会使用本地的Rails代码库,但会对RDS数据库进行实时更改(这是您仍然希望访问Rails控制台的主要原因)。