1. deploy metabase on AWS in a container with a managed postgres database

    TypeScript

    To deploy metabase on AWS in a container with a managed PostgreSQL database, we'll use the AWS RDS, ECS, and EC2 Pulumi libraries, and the pulumi/docker library.

    Here's a brief description of the Pulumi TypeScript program you're going to write:

    This program creates an Amazon RDS instance for the Metabase database, an ECS cluster to host the Metabase service, a task definition for the Metabase service, and a service that runs the task definition. It uses AWS EC2 for the ECS cluster and AWS Fargate for the ECS service.

    The task definition includes a container definition for the Metabase Docker image, that points to the RDS instance for its data storage. Also, it sets an environment variable to configure the usage of a Postgres database by Metabase.

    Here's the TypeScript code:

    import * as aws from "@pulumi/aws"; import * as pulumi from "@pulumi/pulumi"; import * as docker from "@pulumi/docker"; // Create a VPC and a public subnet within the VPC: const vpc = new aws.ec2.Vpc("vpc", { cidrBlock: "192.168.0.0/16" }); const subnet = new aws.ec2.Subnet("subnet", { vpcId: vpc.id, cidrBlock: "192.168.32.0/20" }); // Create a security group for our cluster that allows web traffic. let clusterSecurityGroup = new aws.ec2.SecurityGroup("securitygroup", { vpcId: vpc.id, ingress: [ { protocol: "tcp", fromPort: 0, toPort: 65535, cidrBlocks: ["0.0.0.0/0"] }, ], }); // postgres const db = new aws.rds.Instance("metabase-db", { instanceClass: "db.t2.medium", engine: "postgres", engineVersion: "11.9", allocatedStorage: 20, publiclyAccessible: true, dbSubnetGroupName: new aws.rds.SubnetGroup("metabase-postgres-subnet-group", { subnetIds: [subnet.id], }).name, vpcSecurityGroupIds: [clusterSecurityGroup.id], // reference security group username: "metabase", password: "metabase", skipFinalSnapshot: true, }); const fargateCluster = new aws.ecs.Cluster("fargate-cluster", { capacityProviders: ["FARGATE"] }); const taskDefinition = new aws.ecs.TaskDefinition("task-def", { networkMode: "awsvpc", cpu: "256", memory: "0.5GB", requiresCompatibilities: ["FARGATE"], executionRoleArn: "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", containerDefinitions: pulumi.interpolate`[{ "name": "container", "image": "metabase/metabase:v0.38.4", "memory": 400, "cpu": 256, "networkMode": "awsvpc", "portMappings": [{"hostPort": 3000, "containerPort": 3000, "protocol": "tcp"}], "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "awslogs-metabase", "awslogs-region": "us-west-2", "awslogs-stream-prefix": "awslogs-metabase" } }, "environment": [ {"name": "MB_DB_TYPE", "value": "postgres"}, {"name": "MB_DB_DBNAME", "value": "${db.name}"}, {"name": "MB_DB_PORT", "value": "${db.port}"}, {"name": "MB_DB_USER", "value": "${db.username}"}, {"name": "MB_DB_PASS", "value": "${db.password}"}, {"name": "MB_DB_HOST", "value": "${db.endpoint}"} ] }]` }); const service = new aws.ecs.Service("fargate-service", { cluster: fargateCluster.name, launchType: "FARGATE", taskDefinition: taskDefinition.arn, desiredCount: 1, networkConfiguration: { subnets: [subnet.id], securityGroups: [clusterSecurityGroup.id], } }); export const dbEndpoint = db.endpoint; export const serviceUrl = aws.lb.Listener.get("service", service.id).arn.apply(info => `http://localhost:3000/${info}`);

    This program exports the database endpoint and service URL so the service can be easily accessed after it is launched.

    Additionally, don't forget your stack should have AWS credentials configured and the AWS region set to a region that supports all required services.

    Resource links: